From 6e23904902cd77d05f781a38d98e69562ace1fbc Mon Sep 17 00:00:00 2001 From: mh Date: Thu, 9 May 2024 17:56:56 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E7=94=A8=E8=83=BD=E9=A2=84=E6=B5=8B?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2024数据库脚本.sql | 107 ++++++++---- user-service/pom.xml | 7 + .../mh/user/config/RestTemplateConfig.java | 12 +- .../java/com/mh/user/constants/Constant.java | 1 + .../user/controller/EnergyPreController.java | 18 ++ .../java/com/mh/user/dto/EnergyPreDTO.java | 15 ++ .../com/mh/user/entity/HistoryDataPre.java | 155 +++++++++++++++++ .../com/mh/user/entity/SysParamEntity.java | 1 + .../com/mh/user/job/CollectionLoopRunner.java | 5 + .../java/com/mh/user/job/DealDataJob.java | 27 ++- .../com/mh/user/job/GetWeatherInfoJob.java | 64 +++++++ .../mh/user/mapper/HistoryDataPreMapper.java | 121 +++++++++++++ .../user/service/HistoryDataPreService.java | 39 +++++ .../impl/HistoryDataPreServiceImpl.java | 163 ++++++++++++++++++ .../java/com/mh/user/utils/CacheUtil.java | 5 - .../src/main/resources/application-dev.yml | 5 +- .../src/main/resources/application-prod.yml | 3 + .../src/main/resources/application-test.yml | 3 + .../mh/user/UserServiceApplicationTests.java | 10 ++ 19 files changed, 720 insertions(+), 41 deletions(-) create mode 100644 user-service/src/main/java/com/mh/user/controller/EnergyPreController.java create mode 100644 user-service/src/main/java/com/mh/user/dto/EnergyPreDTO.java create mode 100644 user-service/src/main/java/com/mh/user/entity/HistoryDataPre.java create mode 100644 user-service/src/main/java/com/mh/user/job/GetWeatherInfoJob.java create mode 100644 user-service/src/main/java/com/mh/user/mapper/HistoryDataPreMapper.java create mode 100644 user-service/src/main/java/com/mh/user/service/HistoryDataPreService.java create mode 100644 user-service/src/main/java/com/mh/user/service/impl/HistoryDataPreServiceImpl.java diff --git a/2024数据库脚本.sql b/2024数据库脚本.sql index 4f0c9a3..1989919 100644 --- a/2024数据库脚本.sql +++ b/2024数据库脚本.sql @@ -1,38 +1,81 @@ -- 2024-05-07 维修表缺少字段 -ALTER TABLE maintain_info ADD cost numeric(2,0) NULL; +ALTER TABLE maintain_info + ADD cost numeric(2, 0) NULL; EXEC sys.sp_addextendedproperty 'MS_Description', N'材料费用', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'cost'; -ALTER TABLE maintain_info ADD contents varchar(100) NULL; +ALTER TABLE maintain_info + ADD contents varchar(100) NULL; EXEC sys.sp_addextendedproperty 'MS_Description', N'维保内容', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'contents'; -ALTER TABLE maintain_info ADD evaluate varchar(10) NULL; +ALTER TABLE maintain_info + ADD evaluate varchar(10) NULL; EXEC sys.sp_addextendedproperty 'MS_Description', N'评价内容', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'evaluate'; -- 训练集合: -select - eds.cur_date, - eds.building_id, - isnull(eds.water_value, - 0) as water_value, - isnull(eds.elect_value, - 0) as elect_value, - isnull(convert(numeric(24,2),t1.water_level), - 0) as water_level -from - energy_day_sum eds - left join ( - select - convert(date, - cur_date) as cur_date, - building_id, - avg(isnull(convert(numeric(24, 2), water_level), 0)) as water_level - from - history_data - group by - convert(date, - cur_date), - building_id - ) t1 on - eds.cur_date = t1.cur_date and eds.building_id = t1.building_id -where eds.building_id != '所有' -order by - eds.building_id, - eds.cur_date +begin tran + insert into history_data_pre(cur_date,building_id,water_value,elect_value,water_level,env_min_temp,env_max_temp) + select eds.cur_date, + eds.building_id, + isnull(eds.water_value, + 0) as water_value, + isnull(eds.elect_value, + 0) as elect_value, + isnull(convert(numeric (24, 2), t1.water_level), + 0) as water_level, + th.tempmin, + th.tempmax + from energy_day_sum eds + left join (select convert(date, + cur_date) as cur_date, + building_id, + avg(isnull(convert(numeric (24, 2), water_level), 0)) as water_level + from history_data + group by convert(date, + cur_date), + building_id) t1 on + eds.cur_date = t1.cur_date and eds.building_id = t1.building_id + left join temp_history th + on eds.cur_date = th.cur_date + where eds.building_id != '所有' + order by + eds.building_id, + eds.cur_date +rollback + +-- 2024-05-09 创建历史预测表 +-- 历史水电用量以及预测值 +CREATE TABLE history_data_pre +( + cur_date date NULL, + building_id varchar(50) COLLATE Chinese_PRC_CI_AS NULL, + env_min_temp numeric(24, 2) NULL, + env_max_temp numeric(24, 2) NULL, + water_value numeric(24, 2) NULL, + elect_value numeric(24, 2) NULL, + water_level numeric(24, 2) NULL, + id bigint IDENTITY(1,1) NOT NULL, + water_value_pre numeric(24, 2) NULL, + elect_value_pre numeric(24, 2) NULL, + water_level_pre numeric(24, 2) NULL, + remark varchar(200) COLLATE Chinese_PRC_CI_AS NULL, + CONSTRAINT PK_history_data_pre PRIMARY KEY (id) +); +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'历史水电用量以及预测值', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'日期', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'cur_date'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'楼栋编号', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'building_id'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'环境最低温度', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'env_min_temp'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'环境最高温度', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'env_max_temp'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'实际用水量', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'water_value'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'实际用电量', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'elect_value'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'平均水位', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'water_level'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'id', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'id'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'用水量预测值', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'water_value_pre'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'用电量预测值', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'elect_value_pre'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'平均水位预测值', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'water_level_pre'; +EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'备注', @level0type=N'Schema', @level0name=N'dbo', @level1type=N'Table', @level1name=N'history_data_pre', @level2type=N'Column', @level2name=N'remark'; + +create index history_data_pre_building_id on history_data_pre (building_id); +create index history_data_pre_cur_date on history_data_pre (cur_date); + +-- 2024-05-09 系统参数表增加天气区域 +ALTER TABLE SysParam + ADD proArea varchar(100) NULL; +EXEC sp_addextendedproperty 'MS_Description', N'天气区域', 'schema', N'dbo', 'table', N'SysParam', 'column', N'proArea'; diff --git a/user-service/pom.xml b/user-service/pom.xml index 80143bf..22e0853 100644 --- a/user-service/pom.xml +++ b/user-service/pom.xml @@ -171,6 +171,13 @@ 1.1.1 + + + com.mh + algorithm + 1.0.0 + + diff --git a/user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java b/user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java index f6074d8..e50e924 100644 --- a/user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java +++ b/user-service/src/main/java/com/mh/user/config/RestTemplateConfig.java @@ -1,14 +1,22 @@ package com.mh.user.config; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; /** - * @author ljf + * @author LJF * @title : - * @description : redis配置 + * @description 请求数据 * @updateTime 2020-08-20 * @throws : */ @Configuration public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + } diff --git a/user-service/src/main/java/com/mh/user/constants/Constant.java b/user-service/src/main/java/com/mh/user/constants/Constant.java index 4668e55..4f349b6 100644 --- a/user-service/src/main/java/com/mh/user/constants/Constant.java +++ b/user-service/src/main/java/com/mh/user/constants/Constant.java @@ -11,6 +11,7 @@ public class Constant { public static final CharSequence CUSTOM_NAME_HUAXIA = "华夏"; public static final CharSequence CUSTOM_NAME_GUANGSHANG = "广商"; + public static final String WEATHER_DATA = "weather_data"; public static boolean CONTROL_WEB_FLAG = false; public static boolean SEND_STATUS = false; // 指令发送状态 public static volatile boolean FLAG = false; diff --git a/user-service/src/main/java/com/mh/user/controller/EnergyPreController.java b/user-service/src/main/java/com/mh/user/controller/EnergyPreController.java new file mode 100644 index 0000000..bf38d45 --- /dev/null +++ b/user-service/src/main/java/com/mh/user/controller/EnergyPreController.java @@ -0,0 +1,18 @@ +package com.mh.user.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 用能预测controller + * @date 2024-05-09 17:24:48 + */ +@RestController +@RequestMapping("/energy_pre") +public class EnergyPreController { + + +} diff --git a/user-service/src/main/java/com/mh/user/dto/EnergyPreDTO.java b/user-service/src/main/java/com/mh/user/dto/EnergyPreDTO.java new file mode 100644 index 0000000..5dc4120 --- /dev/null +++ b/user-service/src/main/java/com/mh/user/dto/EnergyPreDTO.java @@ -0,0 +1,15 @@ +package com.mh.user.dto; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 用能预测前端类 + * @date 2024-05-09 17:31:27 + */ +public class EnergyPreDTO { + + private String buildingId; + + +} diff --git a/user-service/src/main/java/com/mh/user/entity/HistoryDataPre.java b/user-service/src/main/java/com/mh/user/entity/HistoryDataPre.java new file mode 100644 index 0000000..f4fee7a --- /dev/null +++ b/user-service/src/main/java/com/mh/user/entity/HistoryDataPre.java @@ -0,0 +1,155 @@ +package com.mh.user.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 历史预测数据表 + * @date 2024-05-09 09:55:09 + */ +public class HistoryDataPre { + + private Long id; + + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date curDate; + + private String buildingId; + + private BigDecimal envMinTemp; + + private BigDecimal envMaxTemp; + + private BigDecimal waterValue; + + private BigDecimal electValue; + + private BigDecimal waterLevel; + + private BigDecimal waterValuePre; + + private BigDecimal electValuePre; + + private BigDecimal waterLevelPre; + + private String remark; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getCurDate() { + return curDate; + } + + public void setCurDate(Date curDate) { + this.curDate = curDate; + } + + public String getBuildingId() { + return buildingId; + } + + public void setBuildingId(String buildingId) { + this.buildingId = buildingId; + } + + public BigDecimal getEnvMinTemp() { + return envMinTemp; + } + + public void setEnvMinTemp(BigDecimal envMinTemp) { + this.envMinTemp = envMinTemp; + } + + public BigDecimal getEnvMaxTemp() { + return envMaxTemp; + } + + public void setEnvMaxTemp(BigDecimal envMaxTemp) { + this.envMaxTemp = envMaxTemp; + } + + public BigDecimal getWaterValue() { + return waterValue; + } + + public void setWaterValue(BigDecimal waterValue) { + this.waterValue = waterValue; + } + + public BigDecimal getElectValue() { + return electValue; + } + + public void setElectValue(BigDecimal electValue) { + this.electValue = electValue; + } + + public BigDecimal getWaterLevel() { + return waterLevel; + } + + public void setWaterLevel(BigDecimal waterLevel) { + this.waterLevel = waterLevel; + } + + public BigDecimal getWaterValuePre() { + return waterValuePre; + } + + public void setWaterValuePre(BigDecimal waterValuePre) { + this.waterValuePre = waterValuePre; + } + + public BigDecimal getElectValuePre() { + return electValuePre; + } + + public void setElectValuePre(BigDecimal electValuePre) { + this.electValuePre = electValuePre; + } + + public BigDecimal getWaterLevelPre() { + return waterLevelPre; + } + + public void setWaterLevelPre(BigDecimal waterLevelPre) { + this.waterLevelPre = waterLevelPre; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + @Override + public String toString() { + return "HistoryDataPre{" + + "id=" + id + + ", curDate=" + curDate + + ", buildingId='" + buildingId + '\'' + + ", envMinTemp=" + envMinTemp + + ", envMaxTemp=" + envMaxTemp + + ", waterValue=" + waterValue + + ", electValue=" + electValue + + ", waterLevel=" + waterLevel + + ", waterValuePre=" + waterValuePre + + ", electValuePre=" + electValuePre + + ", waterLevelPre=" + waterLevelPre + + ", remark='" + remark + '\'' + + '}'; + } +} diff --git a/user-service/src/main/java/com/mh/user/entity/SysParamEntity.java b/user-service/src/main/java/com/mh/user/entity/SysParamEntity.java index 520a342..bb2c4ea 100644 --- a/user-service/src/main/java/com/mh/user/entity/SysParamEntity.java +++ b/user-service/src/main/java/com/mh/user/entity/SysParamEntity.java @@ -7,4 +7,5 @@ public class SysParamEntity { private String customName; //公司或者单位名称 private String logo; //logo地址 + private String proArea; // 区域编码 } diff --git a/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java b/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java index e9ce21d..a6888ca 100644 --- a/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java +++ b/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java @@ -38,6 +38,9 @@ public class CollectionLoopRunner implements ApplicationRunner { @Resource private DeviceCodeParamService deviceCodeParamService; + @Resource + private GetWeatherInfoJob getWeatherInfoJob; + @Override public void run(ApplicationArguments args) throws Exception { // collectionMeterAndCloud();//采集 @@ -46,6 +49,8 @@ public class CollectionLoopRunner implements ApplicationRunner { initialDeviceCodeParams(); // 模拟采集 //simulationCollection(); + // 获取天气数据 + getWeatherInfoJob.getWeatherInfo(); } private void simulationCollection() throws Exception { diff --git a/user-service/src/main/java/com/mh/user/job/DealDataJob.java b/user-service/src/main/java/com/mh/user/job/DealDataJob.java index 7eb75bf..3d86c49 100644 --- a/user-service/src/main/java/com/mh/user/job/DealDataJob.java +++ b/user-service/src/main/java/com/mh/user/job/DealDataJob.java @@ -2,13 +2,17 @@ package com.mh.user.job; import com.mh.user.constants.Constant; import com.mh.user.entity.DeviceCodeParamEntity; +import com.mh.user.model.BuildingModel; import com.mh.user.serialport.SerialPortThread; +import com.mh.user.service.BuildingService; import com.mh.user.service.DealDataService; +import com.mh.user.service.HistoryDataPreService; import com.mh.user.utils.CacheUtil; import com.mh.user.utils.ComThreadPoolService; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; import java.text.SimpleDateFormat; import java.util.Date; @@ -31,8 +35,14 @@ public class DealDataJob { private final DealDataService dealDataService; - public DealDataJob(DealDataService dealDataService) { + private final BuildingService buildingService; + + private final HistoryDataPreService historyDataPreService; + + public DealDataJob(DealDataService dealDataService, BuildingService buildingService, HistoryDataPreService historyDataPreService) { this.dealDataService = dealDataService; + this.buildingService = buildingService; + this.historyDataPreService = historyDataPreService; } ThreadPoolExecutor comThreadPool = ComThreadPoolService.getInstance(); @@ -141,6 +151,9 @@ public class DealDataJob { @Scheduled(cron = "0 0/15 * * * ?") public void dealData() { try { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); Date date = new Date(); String curDate = sdf1.format(date); @@ -159,6 +172,18 @@ public class DealDataJob { dealDataService.proDeviceState(curDate); //汇总设备状态 dealDataService.proTotalPumpMinutes(curDate); //统计周\月热泵运行时长 log.info("进入定时调试数据库过程汇总数据!yyyy-MM-dd"); + + // 开始预测数据 + List buildingModels = buildingService.selectBuildingName(); + for (BuildingModel buildingModel : buildingModels) { + String buildingId = String.valueOf(buildingModel.getBuildingId()); + // 训练数据 + historyDataPreService.startTrainData(buildingId); + // 预测数据 + historyDataPreService.startPredictData(buildingId, curDate); + } + stopWatch.stop(); + log.info("定时处理数据以及预测数据结束!耗时:" + stopWatch.getTotalTimeSeconds() + "秒"); } catch (Exception e) { log.error("定时处理数据异常==>", e); } diff --git a/user-service/src/main/java/com/mh/user/job/GetWeatherInfoJob.java b/user-service/src/main/java/com/mh/user/job/GetWeatherInfoJob.java new file mode 100644 index 0000000..e609b74 --- /dev/null +++ b/user-service/src/main/java/com/mh/user/job/GetWeatherInfoJob.java @@ -0,0 +1,64 @@ +package com.mh.user.job; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.github.benmanes.caffeine.cache.Cache; +import com.mh.common.utils.StringUtils; +import com.mh.user.entity.SysParamEntity; +import com.mh.user.service.SysParamService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; + +/** + * @author LJF + * @version 1.0 + * @project NewZhujiang_Server + * @description 定期获取时间 + * @date 2023-12-05 14:12:56 + */ +@Component +@Slf4j +public class GetWeatherInfoJob { + + @Resource + private SysParamService sysParamService; + + @Resource + private RestTemplate restTemplate; + + @Resource + @Qualifier("caffeineCache") + private Cache caffeineCache; + + @Value("${amap.key}") + String amapKey; + + /** + * 定时获取每天天气 + */ + @Scheduled(cron = "0 0 0 0/1 * ? ") + public void getWeatherInfo() { + // 从系统参数中获取对应的项目区域 + SysParamEntity sysParam = sysParamService.selectSysParam(); + if (null != sysParam) { + String url = "https://restapi.amap.com/v3/weather/weatherInfo?extensions=all&key="+amapKey+"&city="+sysParam.getProArea(); + String returnResult = restTemplate.getForObject(url, String.class); + if (!StringUtils.isBlank(returnResult)) { + JSONObject jsonObject = JSON.parseObject(returnResult); + if ("1".equals(jsonObject.get("status"))) { + Object wetTemp = caffeineCache.getIfPresent(sysParam.getProArea()); + if (wetTemp != null) { + caffeineCache.invalidate(sysParam.getProArea()); + } + caffeineCache.put(sysParam.getProArea(), jsonObject.toString()); + } + } + } + } +} diff --git a/user-service/src/main/java/com/mh/user/mapper/HistoryDataPreMapper.java b/user-service/src/main/java/com/mh/user/mapper/HistoryDataPreMapper.java new file mode 100644 index 0000000..0736e1a --- /dev/null +++ b/user-service/src/main/java/com/mh/user/mapper/HistoryDataPreMapper.java @@ -0,0 +1,121 @@ +package com.mh.user.mapper; + +import com.mh.user.entity.HistoryDataPre; +import org.apache.ibatis.annotations.*; +import org.springframework.security.core.parameters.P; +import tk.mybatis.mapper.common.BaseMapper; + +import java.util.List; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 预测历史数据mapper + * @date 2024-05-09 10:01:46 + */ +@Mapper +public interface HistoryDataPreMapper extends BaseMapper { + + @Results(id ="rs_train_data",value ={ + @Result(column = "env_min_temp", property = "envMinTemp"), + @Result(column = "env_max_temp", property = "envMaxTemp"), + @Result(column = "water_value", property = "waterValue"), + @Result(column = "elect_value", property = "electValue"), + @Result(column = "water_level", property = "waterLevel"), + }) + @Select("select env_min_temp, env_max_temp, water_value, elect_value, water_level from history_data_pre where building_id = #{buildingId} order by cur_date ") + List getTrainData(@Param("buildingId") String buildingId); + + @Results(id ="rs_recent_data",value ={ + @Result(column = "id",property = "id" ), + @Result(column = "building_id", property = "buildingId"), + @Result(column = "cur_date", property = "curDate"), + @Result(column = "env_min_temp", property = "envMinTemp"), + @Result(column = "env_max_temp", property = "envMaxTemp"), + @Result(column = "water_value", property = "waterValue"), + @Result(column = "elect_value", property = "electValue"), + @Result(column = "water_level", property = "waterLevel"), + @Result(column = "water_value_pre", property = "waterValuePre"), + @Result(column = "elect_value_pre", property = "electValuePre"), + @Result(column = "water_level_pre", property = "waterLevelPre"), + @Result(column = "remark", property = "remark") + }) + @Select("select * from history_date_pre where building_id = #{buildingId} and cur_date = #{curDate} order by cur_date ") + List getRecentData(@Param("buildingId") String buildingId, + @Param("curDate") String curDate); + + @Update("update history_data_pre set water_value_pre = #{waterValuePre},elect_value_pre = #{electValuePre},water_level_pre = #{waterLevelPre} where id = #{id} and building_id = #{buildingId}") + void updateById(HistoryDataPre preHistoryData); + + @Select("select count(*) from history_data_pre where building_id = #{buildingId} and cur_date = #{curDate} and env_min_temp is not null ") + int selectIsPre(@Param("buildingId") String buildingId, + @Param("curDate") String curDate); + + @Results(id ="rs_cur_data",value ={ + @Result(column = "id",property = "id" ), + @Result(column = "building_id", property = "buildingId"), + @Result(column = "cur_date", property = "curDate"), + @Result(column = "env_min_temp", property = "envMinTemp"), + @Result(column = "env_max_temp", property = "envMaxTemp"), + @Result(column = "water_value", property = "waterValue"), + @Result(column = "elect_value", property = "electValue"), + @Result(column = "water_level", property = "waterLevel") + }) + @Select("select top 1 " + + " convert(date,eds.cur_date) as cur_date, " + + " eds.building_id, " + + " isnull(eds.water_value, " + + " 0) as water_value, " + + " isnull(eds.elect_value, " + + " 0) as elect_value, " + + " isnull(convert(numeric(24, " + + " 2), " + + " t1.water_level), " + + " 0) as water_level " + + "from " + + " energy_day_sum eds " + + "left join ( " + + " select " + + " convert(date, " + + " cur_date) as cur_date, " + + " building_id, " + + " avg(isnull(convert(numeric(24, 2), water_level), 0)) as water_level " + + " from " + + " history_data " + + " where " + + " building_id = #{buildingId} " + + " and cur_date = #{curDate} " + + " group by " + + " convert(date, " + + " cur_date), " + + " building_id " + + " ) t1 on " + + " eds.cur_date = t1.cur_date " + + " and eds.building_id = t1.building_id " + + "where " + + " eds.building_id != '所有' " + + " and eds.building_id = #{buildingId} " + + " and eds.cur_date = #{curDate} " + + "order by " + + " eds.building_id, " + + " eds.cur_date ") + HistoryDataPre selectCurData(@Param("buildingId") String buildingId, + @Param("curDate") String curDate); + + @Insert("insert into history_data_pre(cur_date, building_id, env_min_temp, env_max_temp, water_value, elect_value, water_level) values(" + + "convert(date,#{curDate}), #{buildingId}, #{envMinTemp}, #{envMaxTemp}, #{waterValue}, #{electValue}, #{waterLevel}" + + ")") + void insertData(HistoryDataPre curHistoryData); + + @Results(id ="rs_one_data",value ={ + @Result(column = "id",property = "id" ), + @Result(column = "building_id", property = "buildingId"), + @Result(column = "cur_date", property = "curDate"), + @Result(column = "env_min_temp", property = "envMinTemp"), + @Result(column = "env_max_temp", property = "envMaxTemp"), + }) + @Select("select top 1 id, building_id, cur_date, env_min_temp, env_max_temp from history_data_pre where building_id = #{buildingId} and cur_date = #{curDate} ") + HistoryDataPre selectOneData(@Param("buildingId") String buildingId, + @Param("curDate") String curDate); +} diff --git a/user-service/src/main/java/com/mh/user/service/HistoryDataPreService.java b/user-service/src/main/java/com/mh/user/service/HistoryDataPreService.java new file mode 100644 index 0000000..8f9263c --- /dev/null +++ b/user-service/src/main/java/com/mh/user/service/HistoryDataPreService.java @@ -0,0 +1,39 @@ +package com.mh.user.service; + +import com.mh.user.entity.HistoryDataPre; + +import java.util.List; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 预测历史数据服务类 + * @date 2024-05-09 10:02:54 + */ +public interface HistoryDataPreService { + + /** + * 获取训练数据 + * @param buildingId + * @throws Exception + */ + void startTrainData(String buildingId) throws Exception; + + /** + * 开始预测数据 + * @param buildingId + * @param curDate + * @throws Exception + */ + void startPredictData(String buildingId, String curDate) throws Exception; + + /** + * 获取每栋楼的数据 + * @param buildingId + * @param curDate + * @return + */ + List getRecentData(String buildingId, String curDate); + +} diff --git a/user-service/src/main/java/com/mh/user/service/impl/HistoryDataPreServiceImpl.java b/user-service/src/main/java/com/mh/user/service/impl/HistoryDataPreServiceImpl.java new file mode 100644 index 0000000..932ffaa --- /dev/null +++ b/user-service/src/main/java/com/mh/user/service/impl/HistoryDataPreServiceImpl.java @@ -0,0 +1,163 @@ +package com.mh.user.service.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.github.benmanes.caffeine.cache.Cache; +import com.mh.algorithm.bpnn.BPModel; +import com.mh.algorithm.bpnn.BPNeuralNetworkFactory; +import com.mh.algorithm.bpnn.BPParameter; +import com.mh.algorithm.matrix.Matrix; +import com.mh.algorithm.utils.CsvInfo; +import com.mh.algorithm.utils.SerializationUtil; +import com.mh.user.entity.HistoryDataPre; +import com.mh.user.entity.SysParamEntity; +import com.mh.user.mapper.HistoryDataPreMapper; +import com.mh.user.service.HistoryDataPreService; +import com.mh.user.service.SysParamService; +import com.mh.user.utils.DateUtil; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 预测历史数据服务实现类 + * @date 2024-05-09 10:03:24 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class HistoryDataPreServiceImpl implements HistoryDataPreService { + + @Resource + private HistoryDataPreMapper historyDataPreMapper; + + @Resource + @Qualifier("caffeineCache") + private Cache caffeineCache; + + @Resource + private SysParamService sysParamService; + + public static String[] convert(HistoryDataPre dataPre) { + // 假设HistoryDataPre有字段如field1, field2, field3等,根据需要进行转换 + return new String[] { + String.valueOf(dataPre.getEnvMinTemp()), + String.valueOf(dataPre.getEnvMaxTemp()), + String.valueOf(dataPre.getWaterValue()), + String.valueOf(dataPre.getElectValue()), + String.valueOf(dataPre.getWaterLevel()) + }; + } + + @Override + public void startTrainData(String buildingId) throws Exception { + List trainData = historyDataPreMapper.getTrainData(buildingId); + List historyDataPreList = new ArrayList<>(); + for (HistoryDataPre dataPre : trainData) { + historyDataPreList.add(convert(dataPre)); + } + // 创建训练集矩阵 + CsvInfo csvInfo = new CsvInfo(); + csvInfo.setCsvFileList(new ArrayList<>(historyDataPreList)); + Matrix trainSet = csvInfo.toMatrix(); + + // 创建BPNN工厂对象 + BPNeuralNetworkFactory factory = new BPNeuralNetworkFactory(); + + // 创建BP参数对象 + BPParameter bpParameter = new BPParameter(); + bpParameter.setInputLayerNeuronCount(2); + bpParameter.setHiddenLayerNeuronCount(3); + bpParameter.setOutputLayerNeuronCount(3); + bpParameter.setPrecision(0.01); + bpParameter.setMaxTimes(50000); + + // 训练BP神经网络 + BPModel bpModel = factory.trainBP(bpParameter, trainSet); + + // 将BPModel序列化到本地 + SerializationUtil.serialize(bpModel, buildingId+"_pre_data"); + } + + @Override + public void startPredictData(String buildingId, String curDate) throws Exception { + // 判断是否存在天气温度数据以及现在的用水量用电量等 + int isPre = historyDataPreMapper.selectIsPre(buildingId, curDate); + if (isPre > 0) { + return; + } + // 获取当前天气数据 + SysParamEntity sysParam = sysParamService.selectSysParam(); + Object weather = caffeineCache.getIfPresent(sysParam.getProArea()); + if (weather == null) { + return; + } + String weatherStr = (String) weather; + JSONObject jsonObject = JSON.parseObject(weatherStr); + if (null == jsonObject) { + return; + } + String envMinTemp = ""; + String envMaxTemp = ""; + JSONArray jsonArray = jsonObject.getJSONArray("forecasts").getJSONObject(0).getJSONArray("casts"); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject1 = jsonArray.getJSONObject(i); + if (jsonObject1.getString("date").equals(curDate)) { + envMinTemp =jsonObject1.getString("nighttemp"); + envMaxTemp = jsonObject1.getString("daytemp"); + break; + } + } + // 获取当前用水量和用电量以及实际平均水位 + HistoryDataPre curHistoryData = historyDataPreMapper.selectCurData(buildingId, curDate); + // 插入数据 + curHistoryData.setEnvMaxTemp(new BigDecimal(envMaxTemp)); + curHistoryData.setEnvMinTemp(new BigDecimal(envMinTemp)); + historyDataPreMapper.insertData(curHistoryData); + + // 开始预测 + HistoryDataPre historyDataPre1 = historyDataPreMapper.selectOneData(buildingId, curDate); + + String[] preData = new String[]{historyDataPre1.getEnvMinTemp().toString(), historyDataPre1.getEnvMaxTemp().toString()}; + + CsvInfo csvInfo = new CsvInfo(); + ArrayList list = new ArrayList<>(); + list.add(preData); + csvInfo.setCsvFileList(list); + Matrix data = csvInfo.toMatrix(); + // 将BPModel反序列化 + BPModel bpModel1 = (BPModel) SerializationUtil.deSerialization(buildingId+"_pre_data"); + // 创建工厂 + BPNeuralNetworkFactory factory = new BPNeuralNetworkFactory(); + Matrix result = factory.computeBP(bpModel1, data); + // 得出预测数据 + HistoryDataPre preHistoryData = new HistoryDataPre(); + preHistoryData.setId(historyDataPre1.getId()); + preHistoryData.setBuildingId(buildingId); + for (int i = 0; i < result.getMatrixRowCount(); i++) { + String[] record = new String[result.getMatrixColCount()]; + for (int j = 0; j < result.getMatrixColCount(); j++) { + record[j] = result.getValOfIdx(i, j)+""; + } + // 拼接预测值 + preHistoryData.setWaterValuePre(new BigDecimal(record[0])); + preHistoryData.setElectValuePre(new BigDecimal(record[1])); + preHistoryData.setWaterLevelPre(new BigDecimal(record[2])); + } + // 更新预测值 + historyDataPreMapper.updateById(preHistoryData); + } + + @Override + public List getRecentData(String buildingId, String curDate) { + return historyDataPreMapper.getRecentData(buildingId, curDate); + } +} diff --git a/user-service/src/main/java/com/mh/user/utils/CacheUtil.java b/user-service/src/main/java/com/mh/user/utils/CacheUtil.java index 5c07f23..f65967e 100644 --- a/user-service/src/main/java/com/mh/user/utils/CacheUtil.java +++ b/user-service/src/main/java/com/mh/user/utils/CacheUtil.java @@ -3,16 +3,11 @@ package com.mh.user.utils; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.github.benmanes.caffeine.cache.Cache; -import com.mh.user.constants.Constant; -import com.mh.user.entity.ChillersEntity; import com.mh.user.entity.DeviceCodeParamEntity; import com.mh.user.service.DeviceCodeParamService; import org.springframework.context.ApplicationContext; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * @Classname CacheUtil diff --git a/user-service/src/main/resources/application-dev.yml b/user-service/src/main/resources/application-dev.yml index bd40c48..13ccfb9 100644 --- a/user-service/src/main/resources/application-dev.yml +++ b/user-service/src/main/resources/application-dev.yml @@ -8,7 +8,7 @@ spring: type: com.alibaba.druid.pool.DruidDataSource druid: #添加allowMultiQueries=true 在批量更新时才不会出错 - url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=chws_chx;allowMultiQueries=true + url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=chws_gsh;allowMultiQueries=true driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver username: sa password: mh@803 @@ -89,5 +89,8 @@ logging: path: logs/${spring.application.name} ##软件最后更新日期20230111 +amap: + key: 984603bf28ef94ac78765a3ea27a6c26 + diff --git a/user-service/src/main/resources/application-prod.yml b/user-service/src/main/resources/application-prod.yml index a3d410d..b8b46cf 100644 --- a/user-service/src/main/resources/application-prod.yml +++ b/user-service/src/main/resources/application-prod.yml @@ -114,4 +114,7 @@ logging: ##软件最后更新日期20230111 +amap: + key: 984603bf28ef94ac78765a3ea27a6c26 + diff --git a/user-service/src/main/resources/application-test.yml b/user-service/src/main/resources/application-test.yml index 697691c..caa2e85 100644 --- a/user-service/src/main/resources/application-test.yml +++ b/user-service/src/main/resources/application-test.yml @@ -121,4 +121,7 @@ logging: ##软件最后更新日期20230111 +amap: + key: 984603bf28ef94ac78765a3ea27a6c26 + diff --git a/user-service/src/test/java/com/mh/user/UserServiceApplicationTests.java b/user-service/src/test/java/com/mh/user/UserServiceApplicationTests.java index e74cd1f..ce7e0bb 100644 --- a/user-service/src/test/java/com/mh/user/UserServiceApplicationTests.java +++ b/user-service/src/test/java/com/mh/user/UserServiceApplicationTests.java @@ -3,6 +3,7 @@ package com.mh.user; import com.mh.user.entity.DeviceManageEntity; import com.mh.user.entity.GaugeEntity; import com.mh.user.factory.PressureTrans; +import com.mh.user.job.DealDataJob; import com.mh.user.serialport.SerialPortThread; import com.mh.user.service.DeviceManageService; import com.mh.user.service.GaugeService; @@ -124,4 +125,13 @@ class UserServiceApplicationTests { "30030200E105C8" ); } + + @Autowired + private DealDataJob dealDataJob; + + @Test + public void testDealData() { + dealDataJob.dealData(); + } + }