Commit 643579e4 authored by ZWT's avatar ZWT

feat(吉林演示): 松原

1.修改风电站运行状态接口,增加模拟实际发电功率处理逻辑,完成接口冒烟测试;
2.修改天气数据处理定时任务,解决晚上十一点半天气预报数据处理异常问题,修改风资源预测数据和光伏资源预测数据时间处理逻辑,完成接口冒烟测试;
3.修改风机预测数据模块相关功能接口,增加判断当前部署环境逻辑,解决查询全量数据问题;
4.修改风机预测数据生成模块第三方风力发电数据生成功能,增加数据拆分逻辑,区分15分数据层级,完成功能冒烟测试;
5.修改风机预测监控页面历史风速统计接口,统计数据不显示问题及小数位过多问题;
6.修改天气预报数据爬取定时任务,解决8:00-11:00期间没有数据问题,完成功能验证;
7,修改风资源预测历史数据处理定时任务,修改查询逻辑,解决未保存历史预测数据问题;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent 710821ad
......@@ -23,29 +23,6 @@
<artifactId>guava</artifactId>
<version>32.0.0-android</version>
</dependency>
<!--POI start-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.4.6</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<!--POI end-->
<dependency>
<groupId>com.belerweb</groupId>
......
package pps.core.common.utils;
import cn.hutool.core.collection.CollUtil;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.util.JxlsHelper;
import java.io.*;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
/**
* Description:模板导出工具类
* date: 2020/8/20 18:56
*
* @author zjw
*/
public class ExportExcelUtils {
public static void outputFileData(byte[] fileBuff, String filePath) {
File file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try (OutputStream out = Files.newOutputStream(file.toPath())) {
out.write(fileBuff);
out.flush();
} catch (IOException ignored) {
}
}
/**
* 根据参数生成excel文件的二进制数据
*
* @param inputStream excel模板路径
* @param params 模板中相关参数的Map
* @return 生成文件的byte数组
*/
public static byte[] genSingleExcelFileData(InputStream inputStream, Map<String, Object> params) {
Context context = new Context();
if (CollUtil.isNotEmpty(params)) {
for (String key : params.keySet()) {
context.putVar(key, params.get(key));
}
}
ByteArrayOutputStream buff = new ByteArrayOutputStream();
try {
JxlsHelper jxlsHelper = JxlsHelper.getInstance();
Transformer transformer = jxlsHelper.createTransformer(inputStream, buff);
JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig().getExpressionEvaluator();
Map<String, Object> funcs = new HashMap<>();
funcs.put("utils", new JxlsUtils()); //添加自定义功能
evaluator.getJexlEngine().setFunctions(funcs);
jxlsHelper.processTemplate(context, transformer);
} catch (IOException ignored) {
}
return buff.toByteArray();
}
}
\ No newline at end of file
package pps.core.common.utils;
import cn.hutool.core.util.RandomUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* 验证码
......@@ -36,7 +38,7 @@ public class VerificationCode {
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics gd = buffImg.getGraphics();
// 创建一个随机数生成器类
Random random = new Random();
SecureRandom random = RandomUtil.getSecureRandom();
// 将图像填充为白色
gd.setColor(Color.WHITE);
gd.fillRect(0, 0, width, height);
......
package pps.cloud.base.service;
import pps.cloud.base.service.data.CrawlBaseWatherInput;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
import xstartup.data.XServiceResult;
@XService
public interface BaseWatherCloudService {
@XText("获取电站天气信息")
XServiceResult crawlPlantBaseWatherData(XContext context);
@XText("获取天气信息")
XServiceResult crawlBaseWatherData(XContext context);
@XText("获取天气信息")
XServiceResult crawlBaseWatherDataByCityCode(XContext context, CrawlBaseWatherInput input);
}
package pps.core.base.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import pps.core.base.service.BaseLineService;
import pps.core.base.service.data.third_weather_data.ThirdApiWeatherExcelData;
import xstartup.base.XContext;
import java.util.ArrayList;
import java.util.List;
/**
* 天气数据监听器
*
* @author ZWT
* @date 2024/04/30 11:04
*/
public class ThirdApiWeatherDataListener implements ReadListener<ThirdApiWeatherExcelData> {
private XContext context;
/**
* 缓存的数据
*/
private List<ThirdApiWeatherExcelData> cachedDataList = new ArrayList<>(4096);
public ThirdApiWeatherDataListener(XContext context) {
this.context = context;
}
@Override
public void invoke(ThirdApiWeatherExcelData thirdApiWeatherData, AnalysisContext analysisContext) {
cachedDataList.add(thirdApiWeatherData);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
BaseLineService bean = context.getBean(BaseLineService.class);
bean.saveHistory(context, cachedDataList);
}
}
package pps.core.base.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import pps.core.base.service.BaseLineService;
import pps.core.base.service.data.base_excel.WindPredictionExcelData;
import xstartup.base.XContext;
import java.util.ArrayList;
import java.util.List;
/**
* 风资源数据
*
* @author ZWT
* @date 2024/08/30 15:46
*/
public class WindPredictionDataListener implements ReadListener<WindPredictionExcelData> {
private XContext context;
private String stationId;
/**
* 缓存的数据
*/
private List<WindPredictionExcelData> cachedDataList = new ArrayList<>(4096);
public WindPredictionDataListener(XContext context, String stationId) {
this.context = context;
this.stationId = stationId;
}
@Override
public void invoke(WindPredictionExcelData windPredictionExcelData, AnalysisContext analysisContext) {
cachedDataList.add(windPredictionExcelData);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
BaseLineService bean = context.getBean(BaseLineService.class);
bean.saveWindPredictionHistory(context, cachedDataList, stationId);
}
}
......@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.NioUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
......@@ -95,9 +94,7 @@ public class BaseWeatherCloudServiceImpl implements IBaseWeatherCloudService {
re.getMailContent(message);
String tempFilePath = this.saveAttachment(message);
logger.info("------ weatherDataProcess load file: {}", tempFilePath);
FileReader fileReader = new FileReader(tempFilePath);
String jsonString = fileReader.readString();
JSONObject jsonObject = JSON.parseObject(jsonString);
JSONObject jsonObject = JSON.parseObject(FileUtil.readUtf8String(tempFilePath));
jsonObjectList.add(jsonObject);
logger.info("------ weatherDataProcess del temp file path: {}", tempFilePath);
FileUtil.del(tempFilePath);
......@@ -180,9 +177,8 @@ public class BaseWeatherCloudServiceImpl implements IBaseWeatherCloudService {
re.getMailContent(message);
String tempFilePath = this.saveAttachment(message);
logger.info("------ weatherApiDataProcess load file: {}", tempFilePath);
FileReader fileReader = new FileReader(tempFilePath);
String jsonString = fileReader.readString();
//处理读取流部分数据丢失精度问题
String jsonString = FileUtil.readUtf8String(tempFilePath);
jsonString = CharSequenceUtil.replace(jsonString, "%", ".");
List<Weather15mData> weather15mDataList = JSON.parseArray(jsonString, Weather15mData.class);
if (CollUtil.isEmpty(weather15mDataList)) {
......
package pps.core.base.utils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
public class HttpUtils {
public static String send2(String url, String param) throws Exception {
URL localURL = new URL(url);
URLConnection connection = localURL.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept", "application/json");
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(param.length()));
httpURLConnection.setConnectTimeout(10000);
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
String resultBuffer = "";
try {
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(param);
outputStreamWriter.flush();
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception(
"HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
inputStream = httpURLConnection.getInputStream();
resultBuffer = convertStreamToString(inputStream);
System.out.println(resultBuffer);
} catch (Exception ignored) {
} finally {
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
}
return resultBuffer;
}
public static String convertStreamToString(InputStream is) {
StringBuilder sb1 = new StringBuilder();
byte[] bytes = new byte[4096];
int size;
try {
while ((size = is.read(bytes)) > 0) {
String str = new String(bytes, 0, size, StandardCharsets.UTF_8);
sb1.append(str);
}
} catch (IOException ignored) {
} finally {
try {
is.close();
} catch (IOException ignored) {
}
}
return sb1.toString();
}
}
......@@ -38,10 +38,7 @@ public class ThirdPartyApiConstant {
* 长庆Token
*/
public static final String CQ_TOKEN = "/Smart_Well_Data/api/v1/Auth/GetToken";
/**
* 长庆三叠Token
*/
public static final String CQ_SD_LOGIN = "http://10.59.249.10:8183/admin-api/system/auth/login";
/**
* 获取日耗电日产液等信息
*/
......
package pps.core.prediction.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import pps.core.common.utils.ExcelUtils;
import pps.core.common.utils.ExportExcelUtils;
import pps.core.prediction.entity.PlantPowerDataEnt;
import pps.core.prediction.entity.PlantPowerDataView;
import pps.core.prediction.enums.ImportFieldDic;
import pps.core.prediction.mapper.PlantPowerDataMapper;
import pps.core.prediction.mapper.PlantPowerDataViewMapper;
import pps.core.prediction.service.data.plant_power_data.ImportFileInput;
import pps.core.prediction.service.data.plant_power_data.QueryPlantPowerDataInput;
import pps.core.prediction.service.data.plant_power_data.QueryPlantPowerDataOutput;
import pps.core.prediction.utils.HttpUtils;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
import xstartup.base.tool.XStorageTool;
import xstartup.data.XFileResult;
import xstartup.data.XFileType;
import xstartup.data.XPageResult;
import xstartup.data.XServiceResult;
import xstartup.feature.api.annotation.XApiGet;
import xstartup.feature.api.annotation.XApiUpload;
import xstartup.feature.mybatis.helper.XMapperHelper;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
@XService
@XText("电站实际发电数据")
public class PlantPowerDataService {
......@@ -48,84 +29,4 @@ public class PlantPowerDataService {
queryWrapper.lambda().orderByDesc(PlantPowerDataEnt::getDataDate);
return XMapperHelper.query(mapper, input, queryWrapper, QueryPlantPowerDataOutput.class);
}
@XText("下载电站实际发电数据导入模板")
@XApiGet
public XFileResult downloadImportTemplate(XContext context) {
String fileSavePath = XStorageTool.getAbsolutePath("/temp/excel/导入模板_" + DateUtil.formatDate(DateUtil.date()) + ".xlsx");
String templateFilePath = "template/import_plant_data_template.xlsx";
try (InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream(templateFilePath)) {
byte[] excelContent = ExportExcelUtils.genSingleExcelFileData(templateInputStream, null);
ExportExcelUtils.outputFileData(excelContent, fileSavePath);
} catch (Exception e) {
context.getLogger().error(e);
}
return XFileResult.success(XFileType.APPLICATION_XLSX, fileSavePath);
}
@XText("导入电站实际发电数据")
@XApiUpload
public XServiceResult importPlantPowerData(XContext context, ImportFileInput input) {
List<String> headerList = getExcelHeaderList();
List<Map<String, Object>> mapList = ExcelUtils.readExcel(input.getFile().getInputStream(), input.getFile().getFileName(), headerList, 0);
try {
List<PlantPowerDataView> dataList = new ArrayList<>();
Date minDate = null;
Date maxDate = null;
for (Map<String, Object> objectMap : mapList) {
PlantPowerDataView dataView = BeanUtil.toBean(objectMap, PlantPowerDataView.class);
dataView.setPlantId(input.getPlantId());
if (ObjectUtil.isNotNull(dataView.getDataDate())) {
if (ObjectUtil.isNull(minDate)) {
minDate = dataView.getDataDate();
maxDate = dataView.getDataDate();
}
if (minDate.compareTo(dataView.getDataDate()) > 0) {
minDate = dataView.getDataDate();
} else if (maxDate.compareTo(dataView.getDataDate()) < 0) {
maxDate = dataView.getDataDate();
}
dataList.add(dataView);
}
}
if (ObjectUtil.isNull(minDate)) {
return XServiceResult.error(1000, "日期错误");
}
PlantPowerDataMapper mapper = context.getBean(PlantPowerDataMapper.class);
mapper.delete(new QueryWrapper<PlantPowerDataEnt>()
.lambda()
.eq(PlantPowerDataEnt::getPlantId, input.getPlantId())
.ge(PlantPowerDataEnt::getDataDate, minDate)
.le(PlantPowerDataEnt::getDataDate, maxDate));
PlantPowerDataViewMapper viewMapper = context.getBean(PlantPowerDataViewMapper.class);
viewMapper.insertBatch(dataList);
//进行训练
doTrainData(context, input.getPlantId());
} catch (Exception e) {
return XServiceResult.error(-1, e.getMessage());
}
return XServiceResult.OK;
}
private List<String> getExcelHeaderList() {
List<Map<String, Object>> fieldList = new ArrayList<>();
for (ImportFieldDic value : ImportFieldDic.values()) {
Map<String, Object> map = new HashMap<>();
map.put("col", value.getCol());
map.put("sort", value.getSort());
fieldList.add(map);
}
fieldList.sort(Comparator.comparing(o -> ((Integer) o.get("sort"))));
return fieldList.stream().map(x -> ((String) x.get("col"))).collect(Collectors.toList());
}
public void doTrainData(XContext context, String plantId) {
try {
Object ret = HttpUtils.send2("http://127.0.0.1:10098/aiprediction/xgbtrain?plantId=" + plantId,
"");
context.getLogger().info(ret.toString());
} catch (Exception e) {
throw new RuntimeException("调用训练接口失败");
}
}
}
\ No newline at end of file
......@@ -13,7 +13,6 @@ import pps.core.prediction.mapper.PlantPredictedPowerLongTermDataMapper;
import pps.core.prediction.service.data.plant_predicted_power_data.DoPlantPredictedPowerDataInput;
import pps.core.prediction.service.data.plant_predicted_power_data.GetPlantPredictedPowerDataInput;
import pps.core.prediction.service.data.plant_predicted_power_data.GetPlantPredictedPowerDataOutput;
import pps.core.prediction.utils.HttpUtils;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
......@@ -137,17 +136,6 @@ public class PlantPredictedPowerDataService {
@XText("预测电站发电数据")
@XApiPost
public XServiceResult doPredictedPowerData(XContext context, DoPlantPredictedPowerDataInput input) {
doPredictedData(context, input.getPlantId());
return XServiceResult.OK;
}
public void doPredictedData(XContext context, String plantId) {
try {
Object ret = HttpUtils.send2("http://127.0.0.1:10098/aiprediction/xgbreason?plantId=" + plantId,
"");
context.getLogger().info(ret.toString());
} catch (Exception e) {
throw new RuntimeException("调用训练接口失败");
}
}
}
\ No newline at end of file
package pps.core.prediction.service;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import pps.core.common.cache.ThirdPartyConfigCache;
import pps.core.prediction.constant.ThirdPartyApiConstant;
import pps.core.prediction.entity.ThirdActivePowerView;
import pps.core.prediction.enums.BusinessError;
import pps.core.prediction.mapper.ThirdActivePowerViewMapper;
import pps.core.prediction.service.data.third_active_power.GetThirdActivePowerOutput;
import pps.core.prediction.service.data.third_active_power.GetThirdSanDieLoginInfoOutput;
import pps.core.prediction.service.data.third_active_power_daily_update.GetThirdActivePowerDailyUpdateInput;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
import xstartup.base.exception.XServiceException;
import xstartup.base.util.XCopyUtils;
import xstartup.base.util.XHttpUtils;
import xstartup.data.XListResult;
import xstartup.data.XSingleResult;
import xstartup.feature.api.annotation.XApiPost;
import java.util.List;
......@@ -56,56 +44,7 @@ public class ThirdActivePowerService {
return XListResult.success(XCopyUtils.copyNewList(list, GetThirdActivePowerOutput.class));
}
/**
* 获取三叠登录信息
*
* @param context 上下文
* @return {@link XSingleResult}<{@link GetThirdSanDieLoginInfoOutput}>
*/
@XText("第三方--获取三叠登录信息")
@XApiPost
public XSingleResult<GetThirdSanDieLoginInfoOutput> getThirdSanDieLoginInfo(XContext context) {
String loginInfo;
ThirdPartyConfigCache exist = ThirdPartyConfigCache.exist(context, ThirdPartyApiConstant.CQ_TOKEN_SAN_DIE_CACHE_KEY);
if (ObjectUtil.isNull(exist)) {
loginInfo = this.getSanDieToken(context);
} else {
long duration = (long) exist.getDuration();
if (duration - DateUtil.between(exist.getCurrentDate(), DateUtil.date(), DateUnit.SECOND) < ThirdPartyApiConstant.MAX_SECOND) {
loginInfo = this.getSanDieToken(context);
} else {
loginInfo = exist.getCode();
}
}
return XSingleResult.success(JSON.parseObject(loginInfo, GetThirdSanDieLoginInfoOutput.class));
}
/*---------------------------------- 私有方法 ----------------------------------*/
/**
* 获取三叠令牌
*
* @param context 上下文
* @return {@link String}
*/
private String getSanDieToken(XContext context) {
JSONObject param = new JSONObject();
param.put("username", "31b5604627e345ebb48175de8f2ee0bdem55ajAwMQ==kj");
param.put("password", "sdSktfem55ajAwMSFAIzEw8ef354f215d44c0eafd403ab7a1ce74a");
String result = XHttpUtils.postAsJson(ThirdPartyApiConstant.CQ_SD_LOGIN, param.toJSONString(), 10000);
context.getLogger().info("**** getThirdSanDieLoginInfo result: {}", result);
param = JSON.parseObject(result);
param = param.getJSONObject("data");
if (ObjectUtil.isEmpty(param)) {
throw new XServiceException(context, BusinessError.GetSanDieLoginInfoError);
}
String data = param.toJSONString();
ThirdPartyConfigCache cache = new ThirdPartyConfigCache();
cache.setCodeKey(ThirdPartyApiConstant.CQ_TOKEN_SAN_DIE_CACHE_KEY);
cache.setCode(data);
cache.setValidity(15);
cache.setCurrentDate(DateUtil.date());
ThirdPartyConfigCache.set(context, cache);
return data;
}
}
package pps.core.prediction.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class HttpUtils {
public static String send2(String url, String param) throws Exception {
URL localURL = new URL(url);
URLConnection connection = localURL.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept", "application/json");
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(param.length()));
httpURLConnection.setConnectTimeout(10000);
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
String resultBuffer = "";
try {
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(param);
outputStreamWriter.flush();
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception(
"HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
inputStream = httpURLConnection.getInputStream();
resultBuffer = convertStreamToString(inputStream);
} finally {
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
}
return resultBuffer;
}
public static String convertStreamToString(InputStream is) {
StringBuilder sb1 = new StringBuilder();
byte[] bytes = new byte[4096];
int size;
try {
while ((size = is.read(bytes)) > 0) {
String str = new String(bytes, 0, size, "UTF-8");
sb1.append(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb1.toString();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment