Browse Source

1、添加中央热水系统相关api;

dev
3067418132@qq.com 6 days ago
parent
commit
2ceb622eb6
  1. 10
      mh-admin/src/main/java/com/mh/web/controller/device/CollectionParamsManageController.java
  2. 26
      mh-admin/src/main/java/com/mh/web/controller/device/OperationController.java
  3. 109
      mh-admin/src/main/java/com/mh/web/controller/energy/HotWaterEnergyController.java
  4. 20
      mh-admin/src/main/java/com/mh/web/controller/monitor/HotWaterMonitorController.java
  5. 18
      mh-admin/src/main/java/com/mh/web/controller/space/BuildingInfoController.java
  6. 5
      mh-admin/src/main/java/com/mh/web/controller/space/SpaceController.java
  7. 10
      mh-admin/src/main/resources/application-dev.yml
  8. 2
      mh-admin/src/main/resources/application.yml
  9. 25
      mh-common/src/main/java/com/mh/common/constant/EnergyType.java
  10. 68
      mh-common/src/main/java/com/mh/common/core/domain/dto/DataResultDTO.java
  11. 46
      mh-common/src/main/java/com/mh/common/core/domain/entity/AnalysisMonth.java
  12. 27
      mh-common/src/main/java/com/mh/common/core/domain/entity/AnalysisYear.java
  13. 81
      mh-common/src/main/java/com/mh/common/core/domain/entity/CollectionParamsManage.java
  14. 8
      mh-common/src/main/java/com/mh/common/core/domain/entity/CpmSpaceRelation.java
  15. 84
      mh-common/src/main/java/com/mh/common/core/domain/entity/DeviceState.java
  16. 89
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyDay.java
  17. 74
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyDaySum.java
  18. 220
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyHour.java
  19. 89
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyMonth.java
  20. 74
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyMonthSum.java
  21. 89
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyYear.java
  22. 74
      mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyYearSum.java
  23. 9
      mh-common/src/main/java/com/mh/common/core/domain/entity/GatewayManage.java
  24. 15
      mh-common/src/main/java/com/mh/common/core/domain/entity/HouseInfo.java
  25. 117
      mh-common/src/main/java/com/mh/common/core/domain/entity/WaterLevel.java
  26. 117
      mh-common/src/main/java/com/mh/common/core/domain/entity/WaterTemp.java
  27. 63
      mh-common/src/main/java/com/mh/common/core/redis/RedisLock.java
  28. 5
      mh-common/src/main/java/com/mh/common/model/request/AdvantechDatas.java
  29. 336
      mh-common/src/main/java/com/mh/common/utils/AnalysisReceiveOrder485.java
  30. 253
      mh-common/src/main/java/com/mh/common/utils/CRC16.java
  31. 69
      mh-common/src/main/java/com/mh/common/utils/DateUtils.java
  32. 1350
      mh-common/src/main/java/com/mh/common/utils/ExchangeStringUtil.java
  33. 67
      mh-common/src/main/java/com/mh/common/utils/ModbusUtils.java
  34. 77
      mh-common/src/main/java/com/mh/common/utils/NettyTools.java
  35. 64
      mh-common/src/main/java/com/mh/common/utils/SendOrderUtils.java
  36. 57
      mh-framework/src/main/java/com/mh/framework/netty/EchoServer.java
  37. 427
      mh-framework/src/main/java/com/mh/framework/netty/EchoServerHandler.java
  38. 18
      mh-framework/src/main/java/com/mh/framework/netty/INettyService.java
  39. 135
      mh-framework/src/main/java/com/mh/framework/netty/NettyServiceImpl.java
  40. 33
      mh-framework/src/main/java/com/mh/framework/netty/ServerChannelInitializer.java
  41. 66
      mh-framework/src/main/java/com/mh/framework/netty/session/ServerSession.java
  42. 96
      mh-framework/src/main/java/com/mh/framework/netty/session/SessionMap.java
  43. 20
      mh-framework/src/main/java/com/mh/framework/netty/task/CallbackTask.java
  44. 78
      mh-framework/src/main/java/com/mh/framework/netty/task/CallbackTaskScheduler.java
  45. 6
      mh-framework/src/main/java/com/mh/framework/netty/task/ExecuteTask.java
  46. 67
      mh-framework/src/main/java/com/mh/framework/netty/task/FutureTaskScheduler.java
  47. 291
      mh-quartz/src/main/java/com/mh/quartz/task/HotWaterTask.java
  48. 38
      mh-system/src/main/java/com/mh/system/mapper/device/CollectionParamsManageMapper.java
  49. 13
      mh-system/src/main/java/com/mh/system/mapper/device/DeviceLedgerMapper.java
  50. 22
      mh-system/src/main/java/com/mh/system/mapper/device/DeviceStateMapper.java
  51. 2
      mh-system/src/main/java/com/mh/system/mapper/device/GatewayManageMapper.java
  52. 56
      mh-system/src/main/java/com/mh/system/mapper/energy/AnalysisMapper.java
  53. 28
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyDayMapper.java
  54. 22
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyDaySumMapper.java
  55. 27
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyHourMapper.java
  56. 28
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyMonthMapper.java
  57. 23
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyMonthSumMapper.java
  58. 27
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyYearMapper.java
  59. 24
      mh-system/src/main/java/com/mh/system/mapper/energy/EnergyYearSumMapper.java
  60. 125
      mh-system/src/main/java/com/mh/system/mapper/energy/HotEnergyQueryMapper.java
  61. 102
      mh-system/src/main/java/com/mh/system/mapper/energy/WaterLevelMapper.java
  62. 103
      mh-system/src/main/java/com/mh/system/mapper/energy/WaterTempMapper.java
  63. 11
      mh-system/src/main/java/com/mh/system/mapper/space/CpmSpaceRelationMapper.java
  64. 15
      mh-system/src/main/java/com/mh/system/service/device/ICollectionParamsManageService.java
  65. 5
      mh-system/src/main/java/com/mh/system/service/device/IDeviceLedgerService.java
  66. 2
      mh-system/src/main/java/com/mh/system/service/device/IGatewayManageService.java
  67. 451
      mh-system/src/main/java/com/mh/system/service/device/impl/CollectionParamsManageServiceImpl.java
  68. 20
      mh-system/src/main/java/com/mh/system/service/device/impl/DeviceLedgerServiceImpl.java
  69. 5
      mh-system/src/main/java/com/mh/system/service/device/impl/GatewayManageServiceImpl.java
  70. 33
      mh-system/src/main/java/com/mh/system/service/energy/IEnergyQueryService.java
  71. 14
      mh-system/src/main/java/com/mh/system/service/energy/IWaterLevelService.java
  72. 14
      mh-system/src/main/java/com/mh/system/service/energy/IWaterTempService.java
  73. 3
      mh-system/src/main/java/com/mh/system/service/energy/impl/EnergyAnalyzeServiceImpl.java
  74. 275
      mh-system/src/main/java/com/mh/system/service/energy/impl/EnergyQueryServiceImpl.java
  75. 60
      mh-system/src/main/java/com/mh/system/service/energy/impl/WaterLevelServiceImpl.java
  76. 60
      mh-system/src/main/java/com/mh/system/service/energy/impl/WaterTempServiceImpl.java
  77. 2
      mh-system/src/main/java/com/mh/system/service/operation/IOperationDeviceService.java
  78. 17
      mh-system/src/main/java/com/mh/system/service/operation/impl/OperationDeviceServiceImpl.java
  79. 2
      mh-system/src/main/java/com/mh/system/service/space/IHouseInfoService.java
  80. 299
      mh-system/src/main/java/com/mh/system/service/space/impl/HouseInfoServiceImpl.java

10
mh-admin/src/main/java/com/mh/web/controller/device/CollectionParamsManageController.java

@ -88,4 +88,14 @@ public class CollectionParamsManageController extends BaseController {
return toAjax(iCollectionParamsManageService.deleteCommunicationByIds(cpmIds)); return toAjax(iCollectionParamsManageService.deleteCommunicationByIds(cpmIds));
} }
/**
* 删除设备采集参数管理
*/
@Log(title = "设备采集参数管理")
@GetMapping("/list/{deviceLegerIds}")
public TableDataInfo queryList(@PathVariable String[] deviceLegerIds)
{
return getDataTable(iCollectionParamsManageService.selectCollectionParamsManageListByIds(deviceLegerIds));
}
} }

26
mh-admin/src/main/java/com/mh/web/controller/device/OperationController.java

@ -11,6 +11,7 @@ import com.mh.common.core.domain.vo.DeviceOperateMonitorVO;
import com.mh.common.core.page.TableDataInfo; import com.mh.common.core.page.TableDataInfo;
import com.mh.common.enums.BusinessType; import com.mh.common.enums.BusinessType;
import com.mh.framework.mqtt.service.IMqttGatewayService; import com.mh.framework.mqtt.service.IMqttGatewayService;
import com.mh.framework.netty.INettyService;
import com.mh.system.service.device.ICollectionParamsManageService; import com.mh.system.service.device.ICollectionParamsManageService;
import com.mh.system.service.operation.IOperationDeviceService; import com.mh.system.service.operation.IOperationDeviceService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -45,13 +46,16 @@ public class OperationController extends BaseController {
private final IMqttGatewayService iMqttGatewayService; private final IMqttGatewayService iMqttGatewayService;
private final INettyService nettyService;
@Autowired @Autowired
public OperationController(ICollectionParamsManageService iCollectionParamsManageService, public OperationController(ICollectionParamsManageService iCollectionParamsManageService,
IOperationDeviceService iOperationService, IOperationDeviceService iOperationService,
IMqttGatewayService iMqttGatewayService) { IMqttGatewayService iMqttGatewayService, INettyService nettyService) {
this.iCollectionParamsManageService = iCollectionParamsManageService; this.iCollectionParamsManageService = iCollectionParamsManageService;
this.iOperationService = iOperationService; this.iOperationService = iOperationService;
this.iMqttGatewayService = iMqttGatewayService; this.iMqttGatewayService = iMqttGatewayService;
this.nettyService = nettyService;
} }
/** /**
@ -95,11 +99,21 @@ public class OperationController extends BaseController {
@ControlDeviceAno(value = "设备操作") @ControlDeviceAno(value = "设备操作")
public AjaxResult operationDevice(@RequestBody List<OrderEntity> changeValues) { public AjaxResult operationDevice(@RequestBody List<OrderEntity> changeValues) {
try { try {
String sendOrder = iOperationService.operationDevice(changeValues); // 判断id是否是DTU设备类型
String name = mhConfig.getName(); if (!iOperationService.isAdvanTech(changeValues)) {
// 获取mqtt操作队列(后期通过mqtt队列配置发送主题) String sendOrder = iOperationService.operationDevice(changeValues);
log.info("发送主题:{},消息:{}", name + "/"+ controlTopic, sendOrder); String name = mhConfig.getName();
iMqttGatewayService.publish(name + "/"+ controlTopic, sendOrder, 1); // 获取mqtt操作队列(后期通过mqtt队列配置发送主题)
log.info("发送主题:{},消息:{}", name + "/" + controlTopic, sendOrder);
iMqttGatewayService.publish(name + "/" + controlTopic, sendOrder, 1);
} else {
// 目前只有DTU设备需要发送4G指令
if (nettyService.sendOrder(changeValues)) {
return AjaxResult.success();
} else {
return AjaxResult.error();
}
}
} catch (Exception e) { } catch (Exception e) {
log.error("设备操作失败", e); log.error("设备操作失败", e);
return AjaxResult.error(); return AjaxResult.error();

109
mh-admin/src/main/java/com/mh/web/controller/energy/HotWaterEnergyController.java

@ -0,0 +1,109 @@
package com.mh.web.controller.energy;
import com.mh.common.core.controller.BaseController;
import com.mh.common.core.domain.entity.WaterLevel;
import com.mh.common.core.domain.entity.WaterTemp;
import com.mh.common.core.page.TableDataInfo;
import com.mh.system.service.energy.IEnergyQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 生活热水能耗分析
* @date 2025-06-18 17:49:49
*/
@RestController
@RequestMapping("/hot_energy")
public class HotWaterEnergyController extends BaseController {
private final IEnergyQueryService energyQueryService;
public HotWaterEnergyController(IEnergyQueryService iEnergyQueryService) {
this.energyQueryService = iEnergyQueryService;
}
@GetMapping("/query")
public TableDataInfo queryEnergy(@RequestParam(value = "buildingId", required = false) String buildingId,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "type") int type) {
startPage();
List<?> result = energyQueryService.queryEnergyDataList(buildingId, startDate, endDate, type);
return getDataTable(result);
}
//查询日月年用量汇总
@GetMapping(value = "/energySum")
public TableDataInfo queryEnergySum(@RequestParam(value = "buildingId", required = false) String buildingId,
@RequestParam(value = "curDate", required = false) String curDate,
@RequestParam(value = "type", required = true) Integer type) {
startPage();
List<?> result = energyQueryService.queryEnergyDataSumList(buildingId, curDate, type);
return getDataTable(result);
}
/**
* 温度变化表
*
* @param buildingId
* @param curDate
* @return
*/
@GetMapping("/waterTemp")
public TableDataInfo queryWaterTemp(@RequestParam(value = "buildingId", required = false) String buildingId,
@RequestParam(value = "curDate", required = false) String curDate) {
startPage();
List<WaterTemp> result = energyQueryService.queryWaterTemp(buildingId, curDate);
return getDataTable(result);
}
/**
* 水位变化表
*
* @param buildingId
* @param curDate
* @return
*/
@GetMapping("/waterLevel")
public TableDataInfo queryWaterLevel(@RequestParam(value = "buildingId", required = false) String buildingId,
@RequestParam(value = "curDate", required = false) String curDate) {
startPage();
List<WaterLevel> result = energyQueryService.queryWaterLevel(buildingId, curDate);
return getDataTable(result);
}
@GetMapping("/queryDeviceDatas")
public TableDataInfo queryDeviceDatas(@RequestParam(value = "buildingId", required = false) String buildingId,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "deviceType", required = false) String deviceType) {
startPage();
List<?> result = energyQueryService.queryDeviceDatas(buildingId, startDate, endDate, deviceType);
return getDataTable(result);
}
@GetMapping("/analysis/queryYear") //type=1(水),2(电),3(能耗),4(维保)
public TableDataInfo queryAnalysisYear(@RequestParam(value = "curDate",required = true) String curDate,
@RequestParam(value = "buildingId",required = true) String buildingId,
@RequestParam(value = "type",defaultValue = "3") int type) {
startPage();
List<?> result = energyQueryService.queryAnalysisYear(curDate, buildingId, type);
return getDataTable(result);
}
@GetMapping("/analysis/queryMonth") //type=1(水),2(电),3(能耗),4(维保),5(使用时间)
public TableDataInfo queryAnalysisMonth(@RequestParam(value = "curDate",required = true) String curDate,
@RequestParam(value = "buildingId",required = true) String buildingId,
@RequestParam(value = "type",defaultValue = "3") int type) {
startPage();
List<?> result = energyQueryService.queryAnalysisMonth(curDate, buildingId, type);
return getDataTable(result);
}
}

20
mh-admin/src/main/java/com/mh/web/controller/monitor/HotWaterMonitorController.java

@ -1,14 +1,15 @@
package com.mh.web.controller.monitor; package com.mh.web.controller.monitor;
import com.mh.common.core.controller.BaseController; import com.mh.common.core.controller.BaseController;
import com.mh.common.core.domain.ColumnData;
import com.mh.common.core.domain.ColumnFilter; import com.mh.common.core.domain.ColumnFilter;
import com.mh.common.core.domain.entity.DeviceState;
import com.mh.common.core.domain.dto.HotWaterControlDTO; import com.mh.common.core.domain.dto.HotWaterControlDTO;
import com.mh.common.core.domain.dto.HotWaterNowDataDTO; import com.mh.common.core.domain.dto.HotWaterNowDataDTO;
import com.mh.common.core.domain.dto.PumpInfoDTO; import com.mh.common.core.domain.dto.PumpInfoDTO;
import com.mh.common.core.domain.entity.ChillersEntity; import com.mh.common.core.domain.entity.ChillersEntity;
import com.mh.common.core.page.TableDataInfo; import com.mh.common.core.page.TableDataInfo;
import com.mh.system.service.device.ICollectionParamsManageService; import com.mh.system.service.device.ICollectionParamsManageService;
import com.mh.system.service.device.IDeviceLedgerService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -30,9 +31,12 @@ public class HotWaterMonitorController extends BaseController {
private final ICollectionParamsManageService iCollectionParamsManageService; private final ICollectionParamsManageService iCollectionParamsManageService;
private final IDeviceLedgerService deviceLedgerService;
@Autowired @Autowired
public HotWaterMonitorController(ICollectionParamsManageService iCollectionParamsManageService) { public HotWaterMonitorController(ICollectionParamsManageService iCollectionParamsManageService, IDeviceLedgerService deviceLedgerService) {
this.iCollectionParamsManageService = iCollectionParamsManageService; this.iCollectionParamsManageService = iCollectionParamsManageService;
this.deviceLedgerService = deviceLedgerService;
} }
/** /**
@ -89,4 +93,16 @@ public class HotWaterMonitorController extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
/**
* 获取设备状态信息数据
* @param systemType
* @return
*/
@GetMapping("/deviceState")
public TableDataInfo deviceState(@RequestParam("systemType") String systemType) {
startPage();
List<DeviceState> list = deviceLedgerService.deviceState(systemType);
return getDataTable(list);
}
} }

18
mh-admin/src/main/java/com/mh/web/controller/space/BuildingInfoController.java

@ -6,6 +6,7 @@ import com.mh.common.core.domain.AjaxResult;
import com.mh.common.core.domain.entity.BuildingInfo; import com.mh.common.core.domain.entity.BuildingInfo;
import com.mh.common.core.page.TableDataInfo; import com.mh.common.core.page.TableDataInfo;
import com.mh.common.enums.BusinessType; import com.mh.common.enums.BusinessType;
import com.mh.system.service.energy.IEnergyQueryService;
import com.mh.system.service.space.IBuildingInfoService; import com.mh.system.service.space.IBuildingInfoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -13,6 +14,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author LJF * @author LJF
@ -28,6 +30,9 @@ public class BuildingInfoController extends BaseController {
@Autowired @Autowired
private IBuildingInfoService buildingInfoService; private IBuildingInfoService buildingInfoService;
@Autowired
private IEnergyQueryService energyQueryService;
/** /**
* 获取楼栋管理列表内容数据 * 获取楼栋管理列表内容数据
*/ */
@ -85,4 +90,17 @@ public class BuildingInfoController extends BaseController {
return toAjax(buildingInfoService.deleteBuildingInfoByIds(buildingIds)); return toAjax(buildingInfoService.deleteBuildingInfoByIds(buildingIds));
} }
/**
* 获取楼栋管理列表内容数据
*/
@GetMapping("/hot_list")
public TableDataInfo hotWaterList()
{
List<Map<String, Object>> list = energyQueryService.queryFloorInfo();
// 在当前list首个坐标加个值
list.addFirst(Map.of("id", "所有", "building_name", "所有"));
return getDataTable(list);
}
} }

5
mh-admin/src/main/java/com/mh/web/controller/space/SpaceController.java

@ -29,4 +29,9 @@ public class SpaceController extends BaseController {
return AjaxResult.success(houseInfoService.buildTree(systemType)); return AjaxResult.success(houseInfoService.buildTree(systemType));
} }
@GetMapping("/floorTree")
public AjaxResult floorTree(@RequestParam(value = "systemType", required = false) String systemType) {
return AjaxResult.success(houseInfoService.buildFloorTree(systemType));
}
} }

10
mh-admin/src/main/resources/application-dev.yml

@ -191,10 +191,10 @@ mqttSpring:
# BASIC parameters are required. # BASIC parameters are required.
BASIC: BASIC:
protocol: MQTT protocol: MQTT
host: 127.0.0.1 host: 192.168.1.79
port: 2883 port: 1883
username: mh username: test123456
password: mhtech@803 password: test123456
# protocol: MQTT # protocol: MQTT
# host: mqtt.mhito.net # host: mqtt.mhito.net
# port: 1883 # port: 1883
@ -209,7 +209,7 @@ mqttSpring:
# 无人机远程控制模式(drone remote control) # 无人机远程控制模式(drone remote control)
DRC: DRC:
protocol: WS protocol: WS
host: 127.0.0.1 host: 192.168.1.79
port: 8083 port: 8083
path: /mqtt path: /mqtt
control: control:

2
mh-admin/src/main/resources/application.yml

@ -1,6 +1,6 @@
spring: spring:
profiles: profiles:
active: prod active: dev
# 用户配置 # 用户配置
user: user:

25
mh-common/src/main/java/com/mh/common/constant/EnergyType.java

@ -0,0 +1,25 @@
package com.mh.common.constant;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description
* @date 2025-06-18 16:32:56
*/
public enum EnergyType {
HOUR("hour"),
DAY("day"),
MONTH("month"),
YEAR("year");
private final String code;
EnergyType(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}

68
mh-common/src/main/java/com/mh/common/core/domain/dto/DataResultDTO.java

@ -0,0 +1,68 @@
package com.mh.common.core.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class DataResultDTO {
private Long id;
private String buildingId;
private String buildingName;
private String deviceNum;
private String deviceName;
private String deviceCode;
private String deviceType;
private BigDecimal lastValue;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastTime;
private double curValue;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date curTime;
private BigDecimal usedValue;
private int ratio;
private BigDecimal calcValue;
private int grade;
private String registerAddr;
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("buildingId", buildingId)
.append("buildingName", buildingName)
.append("deviceNum", deviceNum)
.append("deviceName", deviceName)
.append("deviceCode", deviceCode)
.append("deviceType", deviceType)
.append("lastValue", lastValue)
.append("lastTime", lastTime)
.append("curValue", curValue)
.append("curTime", curTime)
.append("usedValue", usedValue)
.append("ratio", ratio)
.append("calcValue", calcValue)
.append("grade", grade)
.append("registerAddr", registerAddr)
.toString();
}
}

46
mh-common/src/main/java/com/mh/common/core/domain/entity/AnalysisMonth.java

@ -0,0 +1,46 @@
package com.mh.common.core.domain.entity;
import lombok.Data;
@Data
public class AnalysisMonth {
private Long id;
private String curDate;
private String itemType;
private String day01;
private String day02;
private String day03;
private String day04;
private String day05;
private String day06;
private String day07;
private String day08;
private String day09;
private String day10;
private String day11;
private String day12;
private String day13;
private String day14;
private String day15;
private String day16;
private String day17;
private String day18;
private String day19;
private String day20;
private String day21;
private String day22;
private String day23;
private String day24;
private String day25;
private String day26;
private String day27;
private String day28;
private String day29;
private String day30;
private String day31;
private String day32;
private String totalValue;
private String buildingId;
private String buildingName;
}

27
mh-common/src/main/java/com/mh/common/core/domain/entity/AnalysisYear.java

@ -0,0 +1,27 @@
package com.mh.common.core.domain.entity;
import lombok.Data;
@Data
public class AnalysisYear {
private Long id;
private String curDate;
private String itemType;
private String month01;
private String month02;
private String month03;
private String month04;
private String month05;
private String month06;
private String month07;
private String month08;
private String month09;
private String month10;
private String month11;
private String month12;
private String totalValue;
private String buildingId;
private String buildingName;
}

81
mh-common/src/main/java/com/mh/common/core/domain/entity/CollectionParamsManage.java

@ -14,6 +14,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.StringJoiner;
/** /**
* @author LJF * @author LJF
@ -144,6 +145,11 @@ public class CollectionParamsManage extends BaseEntity {
*/ */
private String communicationType; private String communicationType;
/**
* 通信质量
*/
private String quality;
/** /**
* 读取响应的寄存器大小创建指令的时候需要 * 读取响应的寄存器大小创建指令的时候需要
*/ */
@ -192,42 +198,49 @@ public class CollectionParamsManage extends BaseEntity {
*/ */
private String terminalDeviceType; private String terminalDeviceType;
/**
* 价格
*/
private BigDecimal price;
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this) return new StringJoiner(", ", CollectionParamsManage.class.getSimpleName() + "[", "]")
.append("id", id) .add("id='" + id + "'")
.append("deviceLedgerId", deviceLedgerId) .add("deviceLedgerId='" + deviceLedgerId + "'")
.append("mtType", mtType) .add("mtType='" + mtType + "'")
.append("mtNum", mtNum) .add("mtNum='" + mtNum + "'")
.append("mtCode", mtCode) .add("mtCode='" + mtCode + "'")
.append("registerAddr", registerAddr) .add("registerAddr='" + registerAddr + "'")
.append("funcCode", funcCode) .add("funcCode='" + funcCode + "'")
.append("identifyCode", identifyCode) .add("identifyCode='" + identifyCode + "'")
.append("mtCaliberPulse", mtCaliberPulse) .add("mtCaliberPulse='" + mtCaliberPulse + "'")
.append("mtRange", mtRange) .add("mtRange=" + mtRange)
.append("mtRatio", mtRatio) .add("mtRatio=" + mtRatio)
.append("mtInitValue", mtInitValue) .add("mtInitValue=" + mtInitValue)
.append("digits", digits) .add("digits=" + digits)
.append("dataType", dataType) .add("dataType=" + dataType)
.append("curValue", curValue) .add("curValue=" + curValue)
.append("curTime", curTime) .add("curTime=" + curTime)
.append("mtIsSum", mtIsSum) .add("mtIsSum=" + mtIsSum)
.append("unit", unit) .add("unit='" + unit + "'")
.append("orderNum", orderNum) .add("orderNum=" + orderNum)
.append("gatewayId", gatewayId) .add("gatewayId='" + gatewayId + "'")
.append("communicationParamId", communicationParamId) .add("communicationParamId='" + communicationParamId + "'")
.append("protocolType", protocolType) .add("protocolType='" + protocolType + "'")
.append("communicationType", communicationType) .add("communicationType='" + communicationType + "'")
.append("registerSize", registerSize) .add("quality='" + quality + "'")
.append("isUse", isUse) .add("registerSize=" + registerSize)
.append("otherName", otherName) .add("isUse=" + isUse)
.append("grade", grade) .add("otherName='" + otherName + "'")
.append("searchValue", searchValue) .add("grade=" + grade)
.append("params", params) .add("searchValue='" + searchValue + "'")
.append("paramType", paramType) .add("params=" + params)
.append("systemType", systemType) .add("paramType='" + paramType + "'")
.append("collectionType", collectionType) .add("systemType='" + systemType + "'")
.append("terminalDeviceType", terminalDeviceType) .add("collectionType='" + collectionType + "'")
.add("terminalDeviceType='" + terminalDeviceType + "'")
.add("price=" + price)
.toString(); .toString();
} }
} }

8
mh-common/src/main/java/com/mh/common/core/domain/entity/CpmSpaceRelation.java

@ -30,6 +30,14 @@ public class CpmSpaceRelation extends BaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_UUID) @TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id; private String id;
/** 删除标志(0代表存在 2代表删除) */
private String delFlag;
/**
* 台账id
*/
private String ledgerId;
/** /**
* 采集参数id * 采集参数id
*/ */

84
mh-common/src/main/java/com/mh/common/core/domain/entity/DeviceState.java

@ -0,0 +1,84 @@
package com.mh.common.core.domain.entity;
import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author LJF
* @version 1.0
* @date 2025-02-14 09:30:47
* @description 设备统计状态表
*/
@Data
public class DeviceState {
/**
* 当前时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date curDate;
/**
* 设备数目
*/
private int deviceNum;
/**
* 电表数目
*/
private int electNum;
/**
* 水表数目
*/
private int waterNum;
/**
* 泵数目
*/
private int pumpNum;
/**
* 压力表数目
*/
private int pressureNum;
/**
* 在线设备数目
*/
private int onlineNum;
/**
* 离线设备数目
*/
private int offlineNum;
/**
* 故障设备数目
*/
private int faultNum;
/**
* 上次故障数目
*/
private int lastFaultNum;
/**
* 故障环比
*/
private String faultP;
/**
* 热泵正在运行的数目
*/
private int pumpOnline;
/**
* 其他设备数目
*/
private int otherNum;
}

89
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyDay.java

@ -0,0 +1,89 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_day")
public class EnergyDay {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 产热量
*/
private BigDecimal hotWaterValue;
/**
* 使用用量
*/
private BigDecimal useHotWater;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 入住人数
*/
private int checkInCount;
/**
* 人均用电
*/
private BigDecimal perElect;
/**
* 人均用水
*/
private BigDecimal perWater;
/**
* 更新标志
*/
private String updateFlag;
/**
* 建筑名称
*/
private String buildingName;
/**
* 当前电表读数
*/
private BigDecimal electCurValue;
/**
* 当前水表读数
*/
private BigDecimal wtCurValue;
}

74
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyDaySum.java

@ -0,0 +1,74 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_day_sum")
public class EnergyDaySum {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 补水
*/
private BigDecimal fillWater;
/**
* 补水与昨日比
*/
private String fillWaterP;
/**
* 用水
*/
private BigDecimal waterValue;
/**
* 用水与昨日比
*/
private String waterP;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 用电与昨日比
*/
private String electP;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 单耗与昨日比
*/
private String electWaterP;
}

220
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyHour.java

@ -0,0 +1,220 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@TableName("energy_hour")
public class EnergyHour {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 产热量
*/
private BigDecimal hotWaterValue;
/**
* 使用用量
*/
private BigDecimal useHotWater;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 入住人数
*/
private int checkInCount;
/**
* 人均用电
*/
private BigDecimal perElect;
/**
* 人均用水
*/
private BigDecimal perWater;
/**
* 更新标志
*/
private String updateFlag;
/**
* 建筑名称
*/
private String buildingName;
/**
* 当前电表读数
*/
private BigDecimal electCurValue;
/**
* 当前水表读数
*/
private BigDecimal wtCurValue;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCurDate() {
return curDate;
}
public void setCurDate(String curDate) {
this.curDate = curDate;
}
public String getBuildingId() {
return buildingId;
}
public void setBuildingId(String buildingId) {
this.buildingId = buildingId;
}
public BigDecimal getHotWaterValue() {
return hotWaterValue;
}
public void setHotWaterValue(BigDecimal hotWaterValue) {
this.hotWaterValue = hotWaterValue;
}
public BigDecimal getUseHotWater() {
return useHotWater;
}
public void setUseHotWater(BigDecimal useHotWater) {
this.useHotWater = useHotWater;
}
public BigDecimal getElectValue() {
return electValue;
}
public void setElectValue(BigDecimal electValue) {
this.electValue = electValue;
}
public BigDecimal getElectWater() {
return electWater;
}
public void setElectWater(BigDecimal electWater) {
this.electWater = electWater;
}
public int getCheckInCount() {
return checkInCount;
}
public void setCheckInCount(int checkInCount) {
this.checkInCount = checkInCount;
}
public BigDecimal getPerElect() {
return perElect;
}
public void setPerElect(BigDecimal perElect) {
this.perElect = perElect;
}
public BigDecimal getPerWater() {
return perWater;
}
public void setPerWater(BigDecimal perWater) {
this.perWater = perWater;
}
public String getUpdateFlag() {
return updateFlag;
}
public void setUpdateFlag(String updateFlag) {
this.updateFlag = updateFlag;
}
public String getBuildingName() {
return buildingName;
}
public void setBuildingName(String buildingName) {
this.buildingName = buildingName;
}
public BigDecimal getElectCurValue() {
return electCurValue;
}
public void setElectCurValue(BigDecimal electCurValue) {
this.electCurValue = electCurValue;
}
public BigDecimal getWtCurValue() {
return wtCurValue;
}
public void setWtCurValue(BigDecimal wtCurValue) {
this.wtCurValue = wtCurValue;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("curDate", curDate)
.append("buildingId", buildingId)
.append("hotWaterValue", hotWaterValue)
.append("useHotWater", useHotWater)
.append("electValue", electValue)
.append("electWater", electWater)
.append("checkInCount", checkInCount)
.append("perElect", perElect)
.append("perWater", perWater)
.append("updateFlag", updateFlag)
.append("buildingName", buildingName)
.append("electCurValue", electCurValue)
.append("wtCurValue", wtCurValue)
.toString();
}
}

89
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyMonth.java

@ -0,0 +1,89 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_month")
public class EnergyMonth {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 产热量
*/
private BigDecimal hotWaterValue;
/**
* 使用用量
*/
private BigDecimal useHotWater;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 入住人数
*/
private int checkInCount;
/**
* 人均用电
*/
private BigDecimal perElect;
/**
* 人均用水
*/
private BigDecimal perWater;
/**
* 更新标志
*/
private String updateFlag;
/**
* 建筑名称
*/
private String buildingName;
/**
* 当前电表读数
*/
private BigDecimal electCurValue;
/**
* 当前水表读数
*/
private BigDecimal wtCurValue;
}

74
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyMonthSum.java

@ -0,0 +1,74 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_month_sum")
public class EnergyMonthSum {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 补水
*/
private BigDecimal fillWater;
/**
* 补水与昨日比
*/
private String fillWaterP;
/**
* 用水
*/
private BigDecimal waterValue;
/**
* 用水与昨日比
*/
private String waterP;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 用电与昨日比
*/
private String electP;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 单耗与昨日比
*/
private String electWaterP;
}

89
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyYear.java

@ -0,0 +1,89 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_year")
public class EnergyYear {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 产热量
*/
private BigDecimal hotWaterValue;
/**
* 使用用量
*/
private BigDecimal useHotWater;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 入住人数
*/
private int checkInCount;
/**
* 人均用电
*/
private BigDecimal perElect;
/**
* 人均用水
*/
private BigDecimal perWater;
/**
* 更新标志
*/
private String updateFlag;
/**
* 建筑名称
*/
private String buildingName;
/**
* 当前电表读数
*/
private BigDecimal electCurValue;
/**
* 当前水表读数
*/
private BigDecimal wtCurValue;
}

74
mh-common/src/main/java/com/mh/common/core/domain/entity/EnergyYearSum.java

@ -0,0 +1,74 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水时间能耗实体类
* @date 2025-06-18 14:28:30
*/
@Data
@TableName("energy_month_sum")
public class EnergyYearSum {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 时间
*/
private String curDate;
/**
* 建筑id
*/
private String buildingId;
/**
* 补水
*/
private BigDecimal fillWater;
/**
* 补水与昨日比
*/
private String fillWaterP;
/**
* 用水
*/
private BigDecimal waterValue;
/**
* 用水与昨日比
*/
private String waterP;
/**
* 用电量
*/
private BigDecimal electValue;
/**
* 用电与昨日比
*/
private String electP;
/**
* 单耗
*/
private BigDecimal electWater;
/**
* 单耗与昨日比
*/
private String electWaterP;
}

9
mh-common/src/main/java/com/mh/common/core/domain/entity/GatewayManage.java

@ -35,6 +35,7 @@ public class GatewayManage extends BaseEntity {
private int communicationType; // 通讯类型 private int communicationType; // 通讯类型
private int grade; // 标志位(连接状态) 0:正常;1:不在线;2:异常 private int grade; // 标志位(连接状态) 0:正常;1:不在线;2:异常
private Integer status; // (连接状态) 0:正常;1:不在线;2:异常 private Integer status; // (连接状态) 0:正常;1:不在线;2:异常
private String heartBeat; // 心跳包
@JsonIgnore @JsonIgnore
@TableField(exist = false) @TableField(exist = false)
@ -47,6 +48,14 @@ public class GatewayManage extends BaseEntity {
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params; private Map<String, Object> params;
public String getHeartBeat() {
return heartBeat;
}
public void setHeartBeat(String heartBeat) {
this.heartBeat = heartBeat;
}
public Integer getStatus() { public Integer getStatus() {
return status; return status;
} }

15
mh-common/src/main/java/com/mh/common/core/domain/entity/HouseInfo.java

@ -12,6 +12,7 @@ import lombok.Setter;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -92,6 +93,20 @@ public class HouseInfo extends BaseEntity {
private int orderNum; private int orderNum;
/**
* 台账id
*/
// @JsonIgnore
@TableField(exist = false)
private List<String> ledgerId;
/**
* 采集节点id
*/
// @JsonIgnore
@TableField(exist = false)
private List<String> cpmId;
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this) return new ToStringBuilder(this)

117
mh-common/src/main/java/com/mh/common/core/domain/entity/WaterLevel.java

@ -0,0 +1,117 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Date;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水液位
* @date 2025-06-19 16:18:12
*/
@Data
@TableName("water_level")
public class WaterLevel {
private String id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date curDate;
private String buildingId;
private String buildingName;
private String deviceNum;
private String deviceName;
private String temp00;
private String temp01;
private String temp02;
private String temp03;
private String temp04;
private String temp05;
private String temp06;
private String temp07;
private String temp08;
private String temp09;
private String temp10;
private String temp11;
private String temp12;
private String temp13;
private String temp14;
private String temp15;
private String temp16;
private String temp17;
private String temp18;
private String temp19;
private String temp20;
private String temp21;
private String temp22;
private String temp23;
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("curDate", curDate)
.append("buildingId", buildingId)
.append("buildingName", buildingName)
.append("deviceNum", deviceNum)
.append("deviceName", deviceName)
.append("temp00", temp00)
.append("temp01", temp01)
.append("temp02", temp02)
.append("temp03", temp03)
.append("temp04", temp04)
.append("temp05", temp05)
.append("temp06", temp06)
.append("temp07", temp07)
.append("temp08", temp08)
.append("temp09", temp09)
.append("temp10", temp10)
.append("temp11", temp11)
.append("temp12", temp12)
.append("temp13", temp13)
.append("temp14", temp14)
.append("temp15", temp15)
.append("temp16", temp16)
.append("temp17", temp17)
.append("temp18", temp18)
.append("temp19", temp19)
.append("temp20", temp20)
.append("temp21", temp21)
.append("temp22", temp22)
.append("temp23", temp23)
.toString();
}
}

117
mh-common/src/main/java/com/mh/common/core/domain/entity/WaterTemp.java

@ -0,0 +1,117 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Date;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度
* @date 2025-06-19 16:18:12
*/
@Data
@TableName("water_temp")
public class WaterTemp {
private String id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date curDate;
private String buildingId;
private String buildingName;
private String deviceNum;
private String deviceName;
private String temp00;
private String temp01;
private String temp02;
private String temp03;
private String temp04;
private String temp05;
private String temp06;
private String temp07;
private String temp08;
private String temp09;
private String temp10;
private String temp11;
private String temp12;
private String temp13;
private String temp14;
private String temp15;
private String temp16;
private String temp17;
private String temp18;
private String temp19;
private String temp20;
private String temp21;
private String temp22;
private String temp23;
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("curDate", curDate)
.append("buildingId", buildingId)
.append("buildingName", buildingName)
.append("deviceNum", deviceNum)
.append("deviceName", deviceName)
.append("temp00", temp00)
.append("temp01", temp01)
.append("temp02", temp02)
.append("temp03", temp03)
.append("temp04", temp04)
.append("temp05", temp05)
.append("temp06", temp06)
.append("temp07", temp07)
.append("temp08", temp08)
.append("temp09", temp09)
.append("temp10", temp10)
.append("temp11", temp11)
.append("temp12", temp12)
.append("temp13", temp13)
.append("temp14", temp14)
.append("temp15", temp15)
.append("temp16", temp16)
.append("temp17", temp17)
.append("temp18", temp18)
.append("temp19", temp19)
.append("temp20", temp20)
.append("temp21", temp21)
.append("temp22", temp22)
.append("temp23", temp23)
.toString();
}
}

63
mh-common/src/main/java/com/mh/common/core/redis/RedisLock.java

@ -0,0 +1,63 @@
package com.mh.common.core.redis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description
* @date 2025-06-06 16:08:13
*/
@Slf4j
@Component
public class RedisLock {
private final StringRedisTemplate redisTemplate;
public RedisLock(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 获取锁
*/
public boolean lock(String key, String requestId, long expireTimeInSeconds) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(key, requestId, expireTimeInSeconds, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
/**
* 尝试获取锁带超时
*/
public boolean tryLock(String key, String requestId, long expireTime, long timeoutMs) throws InterruptedException {
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < timeoutMs) {
if (lock(key, requestId, expireTime)) {
return true;
}
Thread.sleep(50);
}
return false;
}
/**
* 释放锁使用 Lua 脚本保证原子性
*/
public void unlock(String key, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
RedisScript<Long> redisScript = RedisScript.of(script, Long.class);
Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), requestId);
if (result == null || result == 0) {
log.warn("释放锁失败,可能已被其他线程释放 key={}", key);
}
}
}

5
mh-common/src/main/java/com/mh/common/model/request/AdvantechDatas.java

@ -22,4 +22,9 @@ public class AdvantechDatas<T extends Number> {
*/ */
private T value; private T value;
/**
* 质量值
*/
private T quality;
} }

336
mh-common/src/main/java/com/mh/common/utils/AnalysisReceiveOrder485.java

@ -0,0 +1,336 @@
package com.mh.common.utils;
import com.mh.common.core.domain.entity.CollectionParamsManage;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author ljf
* @title
* @description 解析485接收的数据
* @updateTime 2020-04-23
* @throws
*/
@Slf4j
public class AnalysisReceiveOrder485 {
// 调用service
// private final SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// private final DecimalFormat df = new DecimalFormat("#.##");
//解析冷量表
public void analysisCloudOrder485(final String dataStr1, final CollectionParamsManage deviceCodeParam) {
// 去掉空格
String dataStr = dataStr1.replace(" ", "").toUpperCase();
// 检验报文
String checkStr = dataStr.substring(0, dataStr.length() - 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(checkStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
if (checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) {
//创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30
// Date date = new Date();
// String dateStr = sdf1.format(date);
//保留两位小数处理
DecimalFormat decimalFormat = new DecimalFormat("0.00");
// 表号
String cloudId = ExchangeStringUtil.hexToDec(dataStr.substring(0, 2));
// 读数
String data = "";
data = dataStr.substring(dataStr.length() - 8, dataStr.length() - 6)
+ dataStr.substring(dataStr.length() - 6, dataStr.length() - 4)
+ dataStr.substring(dataStr.length() - 12, dataStr.length() - 10)
+ dataStr.substring(dataStr.length() - 10, dataStr.length() - 8);
String registerAddr = deviceCodeParam.getRegisterAddr();
// if (ExchangeStringUtil.isInDate(date, "00:00:00", "00:00:30")) {
// dateStr = dateStr.substring(0, 17) + "00";
// } else if (ExchangeStringUtil.isInDate(date, "00:00:30", "00:00:59")) {
// dateStr = dateStr.substring(0, 17) + "30";
// }
try {
if (registerAddr.equals("32") || registerAddr.equals("33") || registerAddr.equals("35") || registerAddr.equals("36")) {
data = decimalFormat.format(Math.abs(ExchangeStringUtil.hexToSingle(data)));//十六进制字符串转IEEE754浮点型
log.info("冷量计==>{},寄存器地址==>{},读数==>{}", cloudId, registerAddr, data);
} else if (registerAddr.equals("31") || registerAddr.equals("34")) {
long lData = Long.parseLong(ExchangeStringUtil.hexToDec(data));
log.info("冷量计==>{},寄存器地址==>{},累计读数==>{}", cloudId, registerAddr, lData);
}
} catch (Exception e) {
log.error("保存冷量计数据失败!", e);
}
} else {
log.info("冷量计校验失败===>{}", dataStr);
}
}
/**
* 解析水表返回的数据
*
* @param dataStr1
*/
public String analysisWaterOrder485(final String dataStr1, final CollectionParamsManage deviceCodeParam) {
// 去掉空格
String dataStr = dataStr1.replace(" ", "").toUpperCase();
// 检验报文
String checkStr = dataStr.substring(0, dataStr.length() - 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(checkStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
if (checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) {
//创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30
// Date date = new Date();
// String dateStr = sdf1.format(date);
//保留两位小数处理
DecimalFormat decimalFormat = new DecimalFormat("0.00");
// 表号
String cloudId = ExchangeStringUtil.hexToDec(dataStr.substring(0, 2));
// 读数
String data = "";
data = dataStr.substring(dataStr.length() - 8, dataStr.length() - 6)
+ dataStr.substring(dataStr.length() - 6, dataStr.length() - 4)
+ dataStr.substring(dataStr.length() - 12, dataStr.length() - 10)
+ dataStr.substring(dataStr.length() - 10, dataStr.length() - 8);
int dataType = deviceCodeParam.getDataType();
// if (ExchangeStringUtil.isInDate(date, "00:00:00", "00:00:30")) {
// dateStr = dateStr.substring(0, 17) + "00";
// // System.out.println("插入时间00" + dateStr);
// } else if (ExchangeStringUtil.isInDate(date, "00:00:30", "00:00:59")) {
// dateStr = dateStr.substring(0, 17) + "30";
// // System.out.println("插入时间30" + dateStr);
// }
try {
if (dataType == 3) {
data = decimalFormat.format(Math.abs(ExchangeStringUtil.hexToSingle(data)));//十六进制字符串转IEEE754浮点型
log.info("水表==>{},寄存器地址==>{},读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
} else if (dataType == 2) {
data = dataStr.substring(dataStr.length() - 12, dataStr.length() - 10)
+ dataStr.substring(dataStr.length() - 10, dataStr.length() - 8)
+ dataStr.substring(dataStr.length() - 8, dataStr.length() - 6)
+ dataStr.substring(dataStr.length() - 6, dataStr.length() - 4);
data = ExchangeStringUtil.hexToDec(data);
BigDecimal bigDecimal = new BigDecimal(data);
bigDecimal = bigDecimal.divide(new BigDecimal((int) Math.pow(10, deviceCodeParam.getDigits()))).setScale(2, RoundingMode.HALF_UP); // 除以1000并保留整数
data = bigDecimal.toString();
log.info("水表==>{},寄存器地址==>{},累计读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
}
// 判断data大于99999999,就返回空
if (new BigDecimal(data).intValue() > 99999999) {
return "";
}
return data;
} catch (Exception e) {
log.error("保存水表数据失败!", e);
}
} else {
log.info("水表===>{}", dataStr);
return "";
}
return "";
}
/**
* 解析电表返回的数据
*
* @param dataStr1
*/
public String analysisMeterOrder485(final String dataStr1, final CollectionParamsManage deviceCodeParam) {
// 去掉空格
String dataStr = dataStr1.replace(" ", "").toUpperCase();
// 检验报文
String checkStr = dataStr.substring(0, dataStr.length() - 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(checkStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
if (checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) {
//创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30
// Date date = new Date();
// String dateStr = sdf1.format(date);
;
//保留两位小数处理
DecimalFormat decimalFormat = new DecimalFormat("0.00");
// 表号
String cloudId = ExchangeStringUtil.hexToDec(dataStr.substring(0, 2));
// 读数
String data = "";
data = dataStr.substring(dataStr.length() - 8, dataStr.length() - 6)
+ dataStr.substring(dataStr.length() - 6, dataStr.length() - 4)
+ dataStr.substring(dataStr.length() - 12, dataStr.length() - 10)
+ dataStr.substring(dataStr.length() - 10, dataStr.length() - 8);
int dataType = deviceCodeParam.getDataType();
// if (ExchangeStringUtil.isInDate(date, "00:00:00", "00:00:30")) {
// dateStr = dateStr.substring(0, 17) + "00";
// // System.out.println("插入时间00" + dateStr);
// } else if (ExchangeStringUtil.isInDate(date, "00:00:30", "00:00:59")) {
// dateStr = dateStr.substring(0, 17) + "30";
// // System.out.println("插入时间30" + dateStr);
// }
try {
if (dataType == 3) {
data = decimalFormat.format(Math.abs(ExchangeStringUtil.hexToSingle(data)));//十六进制字符串转IEEE754浮点型
log.info("电表==>{},寄存器地址==>{},读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
} else if (dataType == 2) {
data = ExchangeStringUtil.hexToDec(data);
log.info("电表==>{},寄存器地址==>{},累计读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
}
// 判断data大于99999999,就返回空
if (new BigDecimal(data).intValue() > 99999999) {
return "";
}
return data;
} catch (Exception e) {
log.error("保存电表数据失败!", e);
}
} else {
log.info("电表===>{}", dataStr);
return "";
}
return "";
}
public static int dValue(String lastDate) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date lastTime = format.parse(lastDate);
long min = lastTime.getTime();
Calendar calendar = Calendar.getInstance();
long min1 = calendar.getTimeInMillis();
long subtract = min1 - min;
// // System.out.println("相减值: " + subtract/(1000*60));
return (int) subtract / (1000 * 60);
}
// 判断是否存在寄存器地址
public Boolean queryRegisterAddr(List<String> stringList, String registerAddr) {
boolean flag = false;
for (int i = 0; i < stringList.size(); i++) {
if (stringList.get(i).equalsIgnoreCase(registerAddr)) {
flag = true;
break;
}
}
return flag;
}
public String analysisHeatPumpOrder485(String receiveStr, CollectionParamsManage deviceCodeParam) {
// 去掉空格
String dataStr = receiveStr.replace(" ", "").toUpperCase();
// 检验报文
String checkStr = dataStr.substring(0, dataStr.length() - 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(checkStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
if (checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) {
//创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30
// Date date = new Date();
// String dateStr = sdf1.format(date);
//保留两位小数处理
DecimalFormat decimalFormat = new DecimalFormat("0.00");
// 表号
String cloudId = ExchangeStringUtil.hexToDec(dataStr.substring(0, 2));
// 读数
String data = "";
data = dataStr.substring(dataStr.length() - 8, dataStr.length() - 6)
+ dataStr.substring(dataStr.length() - 6, dataStr.length() - 4);
int dataType = deviceCodeParam.getDataType();
// if (ExchangeStringUtil.isInDate(date, "00:00:00", "00:00:30")) {
// dateStr = dateStr.substring(0, 17) + "00";
// // System.out.println("插入时间00" + dateStr);
// } else if (ExchangeStringUtil.isInDate(date, "00:00:30", "00:00:59")) {
// dateStr = dateStr.substring(0, 17) + "30";
// // System.out.println("插入时间30" + dateStr);
// }
try {
if (dataType == 3) {
data = decimalFormat.format(Math.abs(ExchangeStringUtil.hexToSingle(data)));//十六进制字符串转IEEE754浮点型
} else if (dataType == 2 && (deviceCodeParam.getParamType().equals("5")
|| deviceCodeParam.getParamType().equals("2")
|| deviceCodeParam.getParamType().equals("12")
|| deviceCodeParam.getParamType().equals("14")
|| deviceCodeParam.getParamType().equals("48")
)) {
data = ExchangeStringUtil.hexToDec(data);
}
log.info("热泵==>{},寄存器地址==>{},读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
return data;
} catch (Exception e) {
log.error("保存热泵数据失败!", e);
}
} else {
log.info("热泵===>{}", dataStr);
return "";
}
return "";
}
public String analysisLiquidOrder485(String receiveStr, CollectionParamsManage deviceCodeParam) {
// 去掉空格
String dataStr = receiveStr.replace(" ", "").toUpperCase();
// 检验报文
String checkStr = dataStr.substring(0, dataStr.length() - 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(checkStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
if (checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) {
//创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30
// Date date = new Date();
// String dateStr = sdf1.format(date);
// 表号
String cloudId = ExchangeStringUtil.hexToDec(dataStr.substring(0, 2));
// 读数
String data = "";
data = dataStr.substring(dataStr.length() - 8, dataStr.length() - 4);
int dataType = deviceCodeParam.getDataType();
// if (ExchangeStringUtil.isInDate(date, "00:00:00", "00:00:30")) {
// dateStr = dateStr.substring(0, 17) + "00";
// //// System.out.println("插入时间00" + dateStr);
// } else if (ExchangeStringUtil.isInDate(date, "00:00:30", "00:00:59")) {
// dateStr = dateStr.substring(0, 17) + "30";
// //.out.println("插入时间30" + dateStr);
// }
try {
if (dataType == 2 && (deviceCodeParam.getParamType().equals("11"))) {
data = ExchangeStringUtil.hexToDec(data);
BigDecimal bigDecimal = new BigDecimal(data);
bigDecimal = bigDecimal.divide(new BigDecimal((int) Math.pow(10, deviceCodeParam.getDigits()))).setScale(3, RoundingMode.HALF_UP); // 除以1000并保留整数
data = bigDecimal.toString();
log.info("液位==>{},寄存器地址==>{},实时读数==>{}", cloudId, deviceCodeParam.getRegisterAddr(), data);
}
// 判断data大于99999999,就返回空
if (new BigDecimal(data).intValue() > 100) {
return "";
}
return data;
} catch (Exception e) {
log.error("保存液位数据失败!", e);
}
} else {
log.info("液位===>{}", dataStr);
return "";
}
return "";
}
}

253
mh-common/src/main/java/com/mh/common/utils/CRC16.java

@ -0,0 +1,253 @@
package com.mh.common.utils;
/**
* CRC16_CCITT多项式x16+x12+x5+10x1021初始值0x0000低位在前高位在后结果与0x0000异或
* CRC16_CCITT_FALSE多项式x16+x12+x5+10x1021初始值0xFFFF低位在后高位在前结果与0x0000异或
* CRC16_XMODEM多项式x16+x12+x5+10x1021初始值0x0000低位在后高位在前结果与0x0000异或
* CRC16_X25多项式x16+x12+x5+10x1021初始值0xffff低位在前高位在后结果与0xFFFF异或
* CRC16_MODBUS多项式x16+x15+x2+10x8005初始值0xFFFF低位在前高位在后结果与0x0000异或
* CRC16_IBM多项式x16+x15+x2+10x8005初始值0x0000低位在前高位在后结果与0x0000异或
* CRC16_MAXIM多项式x16+x15+x2+10x8005初始值0x0000低位在前高位在后结果与0xFFFF异或
* CRC16_USB多项式x16+x15+x2+10x8005初始值0xFFFF低位在前高位在后结果与0xFFFF异或
* CRC16_DNP多项式x16+x13+x12+x11+x10+x8+x6+x5+x2+10x3D65初始值0x0000低位在前高位在后结果与0xFFFF异或
* <p>
* 1预置1个16位的寄存器为十六进制FFFF即全为1称此寄存器为CRC寄存器
* 2把第一个8位二进制数据既通讯信息帧的第一个字节与16位的CRC寄存器的低8位相异或把结果放于CRC寄存器高八位数据不变
* 3把CRC寄存器的内容右移一位朝低位用0填补最高位并检查右移后的移出位
* 4如果移出位为0重复第3步再次右移一位如果移出位为1CRC寄存器与多项式A0011010 0000 0000 0001进行异或
* 5重复步骤3和4直到右移8次这样整个8位数据全部进行了处理
* 6重复步骤2到步骤5进行通讯信息帧下一个字节的处理
* 7将该通讯信息帧所有字节按上述步骤计算完成后得到的16位CRC寄存器的高低字节进行交换
* 8最后得到的CRC寄存器内容即为CRC码
* <p>
* 以上计算步骤中的多项式0xA001是0x8005按位颠倒后的结果
* 0x8408是0x1021按位颠倒后的结果
* 在线校验工具
* http://www.ip33.com/crc.html
* https://blog.csdn.net/htmlxx/article/details/17369105
* <p>
* Author:Water
* Time:2018/11/19 0019 15:03
*/
public class CRC16 {
/**
* CRC16_CCITT多项式x16+x12+x5+10x1021初始值0x0000低位在前高位在后结果与0x0000异或
* 0x8408是0x1021按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_CCITT(byte[] buffer) {
int wCRCin = 0x0000;
int wCPoly = 0x8408;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
// wCRCin=(wCRCin<<8)|(wCRCin>>8);
// wCRCin &= 0xffff;
return wCRCin ^= 0x0000;
}
/**
* CRC-CCITT (0xFFFF)
* CRC16_CCITT_FALSE多项式x16+x12+x5+10x1021初始值0xFFFF低位在后高位在前结果与0x0000异或
*
* @param buffer
* @return
*/
public static int CRC16_CCITT_FALSE(byte[] buffer) {
int wCRCin = 0xffff;
int wCPoly = 0x1021;
for (byte b : buffer) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((wCRCin >> 15 & 1) == 1);
wCRCin <<= 1;
if (c15 ^ bit)
wCRCin ^= wCPoly;
}
}
wCRCin &= 0xffff;
return wCRCin ^= 0x0000;
}
/**
* CRC-CCITT (XModem)
* CRC16_XMODEM多项式x16+x12+x5+10x1021初始值0x0000低位在后高位在前结果与0x0000异或
*
* @param buffer
* @return
*/
public static int CRC16_XMODEM(byte[] buffer) {
int wCRCin = 0x0000; // initial value 65535
int wCPoly = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
for (byte b : buffer) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((wCRCin >> 15 & 1) == 1);
wCRCin <<= 1;
if (c15 ^ bit)
wCRCin ^= wCPoly;
}
}
wCRCin &= 0xffff;
return wCRCin ^= 0x0000;
}
/**
* CRC16_X25多项式x16+x12+x5+10x1021初始值0xffff低位在前高位在后结果与0xFFFF异或
* 0x8408是0x1021按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_X25(byte[] buffer) {
int wCRCin = 0xffff;
int wCPoly = 0x8408;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0xffff;
}
/**
* CRC-16 (Modbus)
* CRC16_MODBUS多项式x16+x15+x2+10x8005初始值0xFFFF低位在前高位在后结果与0x0000异或
* 0xA001是0x8005按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_MODBUS(byte[] buffer) {
int wCRCin = 0xffff;
int POLYNOMIAL = 0xa001;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= POLYNOMIAL;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0x0000;
}
/**
* CRC-16
* CRC16_IBM多项式x16+x15+x2+10x8005初始值0x0000低位在前高位在后结果与0x0000异或
* 0xA001是0x8005按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_IBM(byte[] buffer) {
int wCRCin = 0x0000;
int wCPoly = 0xa001;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0x0000;
}
/**
* CRC16_MAXIM多项式x16+x15+x2+10x8005初始值0x0000低位在前高位在后结果与0xFFFF异或
* 0xA001是0x8005按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_MAXIM(byte[] buffer) {
int wCRCin = 0x0000;
int wCPoly = 0xa001;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0xffff;
}
/**
* CRC16_USB多项式x16+x15+x2+10x8005初始值0xFFFF低位在前高位在后结果与0xFFFF异或
* 0xA001是0x8005按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_USB(byte[] buffer) {
int wCRCin = 0xFFFF;
int wCPoly = 0xa001;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0xffff;
}
/**
* CRC16_DNP多项式x16+x13+x12+x11+x10+x8+x6+x5+x2+10x3D65初始值0x0000低位在前高位在后结果与0xFFFF异或
* 0xA6BC是0x3D65按位颠倒后的结果
*
* @param buffer
* @return
*/
public static int CRC16_DNP(byte[] buffer) {
int wCRCin = 0x0000;
int wCPoly = 0xA6BC;
for (byte b : buffer) {
wCRCin ^= ((int) b & 0x00ff);
for (int j = 0; j < 8; j++) {
if ((wCRCin & 0x0001) != 0) {
wCRCin >>= 1;
wCRCin ^= wCPoly;
} else {
wCRCin >>= 1;
}
}
}
return wCRCin ^= 0xffff;
}
}

69
mh-common/src/main/java/com/mh/common/utils/DateUtils.java

@ -37,6 +37,40 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static String localDateToStr(LocalDateTime timeType) {
return timeType.format(DATE_TIME_FORMATTER);
}
public static String dayOfWeekValue() {
int dayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
String result = "";
switch (dayOfWeek) {
case Calendar.MONDAY:
result = "星期一";
break;
case Calendar.TUESDAY:
result = "星期二";
break;
case Calendar.WEDNESDAY:
result = "星期三";
break;
case Calendar.THURSDAY:
result = "星期四";
break;
case Calendar.FRIDAY:
result = "星期五";
break;
case Calendar.SATURDAY:
result = "星期六";
break;
case Calendar.SUNDAY:
result = "星期日";
break;
}
return result;
}
/** /**
* Date 类型的 curTime 转换为 LocalTime * Date 类型的 curTime 转换为 LocalTime
* *
@ -437,4 +471,39 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
// 格式化日期 // 格式化日期
return zonedDateTime.format(formatter); return zonedDateTime.format(formatter);
} }
public static boolean isBetween(LocalTime nowTime, LocalTime startTime, LocalTime endTime) {
if (startTime.isBefore(endTime)) {
return !nowTime.isBefore(startTime) && !nowTime.isAfter(endTime);
} else {
// 跨天情况,比如 22:00 - 6:00
return !nowTime.isBefore(startTime) || !nowTime.isAfter(endTime);
}
}
public static Date getStartOfDay(Date curTime) {
if (curTime != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(curTime);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
return null;
}
public static Date getEndOfDay(Date curTime) {
if (curTime != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(curTime);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
return calendar.getTime();
}
return null;
}
} }

1350
mh-common/src/main/java/com/mh/common/utils/ExchangeStringUtil.java

File diff suppressed because it is too large Load Diff

67
mh-common/src/main/java/com/mh/common/utils/ModbusUtils.java

@ -0,0 +1,67 @@
package com.mh.common.utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description Modbus协议工具类
* @date 2025-06-06 14:40:24
*/
@Slf4j
public class ModbusUtils {
public static String createReadOrder(String mtCode, String funCode, String registerAddr, String registerNum) {
// 开始创建指令
// 拼接指令
String sendOrderStr = ExchangeStringUtil.addZeroForNum(mtCode, 2)
+ ExchangeStringUtil.addZeroForNum(funCode, 2)
+ ExchangeStringUtil.addZeroForNum(registerAddr, 4)
+ ExchangeStringUtil.addZeroForNum(registerNum, 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(sendOrderStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
sendOrderStr = sendOrderStr + checkWord;
return sendOrderStr;
}
public static String createControlCode(String mtCode, Integer type, String registerAddr, String param) {
String orderStr;
mtCode = ExchangeStringUtil.addZeroForNum(mtCode, 2);
registerAddr = ExchangeStringUtil.addZeroForNum(registerAddr, 4);
param = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(param), 4);
orderStr = mtCode + "06" + registerAddr + param;
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(orderStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
// 发送的指令
log.info("发送指令:{}", orderStr+checkWord);
return orderStr + checkWord;
}
public static ByteBuf getByteBuf(ChannelHandlerContext ctx, String sendStr) {
// byte类型的数据
// String sendStr = "5803004900021914"; // 冷量计
// 申请一个数据结构存储信息
ByteBuf buffer = ctx.alloc().buffer();
// 将信息放入数据结构中
buffer.writeBytes(ExchangeStringUtil.hexStrToBinaryStr(sendStr));//对接需要16进制
return buffer;
}
public static ByteBuf createByteBuf(String sendStr) {
// byte类型的数据
// String sendStr = "5803004900021914"; // 冷量计
// 申请一个数据结构存储信息
ByteBuf buffer = Unpooled.buffer();
// 将信息放入数据结构中
buffer.writeBytes(ExchangeStringUtil.hexStrToBinaryStr(sendStr));//对接需要16进制
return buffer;
}
}

77
mh-common/src/main/java/com/mh/common/utils/NettyTools.java

@ -0,0 +1,77 @@
package com.mh.common.utils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* @author LJF
* @version 1.0
* @project TAD_Server
* @description 缓存等待数据
* @date 2023/7/4 08:45:16
*/
@Slf4j
public class NettyTools {
/**
* 响应消息缓存
*/
private static final Cache<String, BlockingQueue<String>> responseMsgCache = CacheBuilder.newBuilder()
.maximumSize(500)
.expireAfterWrite(1000, TimeUnit.SECONDS)
.build();
/**
* 等待响应消息
* @param key 消息唯一标识
* @return ReceiveDdcMsgVo
*/
public static boolean waitReceiveMsg(String key) {
try {
//设置超时时间
String vo = Objects.requireNonNull(responseMsgCache.getIfPresent(key))
.poll(1000 * 10, TimeUnit.MILLISECONDS);
//删除key
responseMsgCache.invalidate(key);
return StringUtils.isNotBlank(vo);
} catch (Exception e) {
log.error("获取数据异常,sn={},msg=null",key);
return false;
}
}
/**
* 初始化响应消息的队列
* @param key 消息唯一标识
*/
public static void initReceiveMsg(String key) {
responseMsgCache.put(key,new LinkedBlockingQueue<String>(1));
}
/**
* 设置响应消息
* @param key 消息唯一标识
*/
public static void setReceiveMsg(String key, String msg) {
if(responseMsgCache.getIfPresent(key) != null){
Objects.requireNonNull(responseMsgCache.getIfPresent(key)).add(msg);
return;
}
log.warn("sn {}不存在",key);
}
}

64
mh-common/src/main/java/com/mh/common/utils/SendOrderUtils.java

@ -0,0 +1,64 @@
package com.mh.common.utils;
import com.mh.common.core.domain.entity.CollectionParamsManage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
/**
* @author ljf
* @title
* @description 发送指令工具类
* @updateTime 2021-01-26
* @throws
*/
@Slf4j
public class SendOrderUtils {
// 发送所有类型采集报文
public static void sendAllOrder(CollectionParamsManage paramsManage, ChannelHandlerContext ctx, int num, int size) {
// 开始创建指令
String mtCode = paramsManage.getMtCode(); // 采集编号
String funCode = paramsManage.getFuncCode(); // 功能码
String registerAddr = paramsManage.getRegisterAddr(); // 寄存器地址
String registerNum = String.valueOf(paramsManage.getRegisterSize()); // 寄存器数量
// 拼接指令
String sendOrderStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(mtCode), 2)
+ ExchangeStringUtil.addZeroForNum(funCode, 2)
+ ExchangeStringUtil.addZeroForNum(registerAddr, 4)
+ ExchangeStringUtil.addZeroForNum(registerNum, 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(sendOrderStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
sendOrderStr = sendOrderStr + checkWord;
ByteBuf buffer = getByteBuf(ctx, sendOrderStr);
// 发送数据
ctx.channel().writeAndFlush(buffer);
log.info("sends :" + sendOrderStr + ",num:" + num + ",records:" + size);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
}
private static ByteBuf getByteBuf(ChannelHandlerContext ctx, String sendStr) {
// 申请一个数据结构存储信息
ByteBuf buffer = ctx.alloc().buffer();
// 将信息放入数据结构中
buffer.writeBytes(ExchangeStringUtil.hexStrToBinaryStr(sendStr));//对接需要16进制
return buffer;
}
public static void sendOrderToDTU(ChannelHandlerContext ctx, String sendStr) {
ByteBuf buffer = getByteBuf(ctx, sendStr);
// 发送数据
ctx.channel().writeAndFlush(buffer);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
}
}

57
mh-framework/src/main/java/com/mh/framework/netty/EchoServer.java

@ -0,0 +1,57 @@
package com.mh.framework.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void start() {
// 创建EventLoopGroup
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.localAddress(port)
.option(ChannelOption.SO_BACKLOG, 1204)
.childHandler(new ServerChannelInitializer());
// 异步绑定端口
ChannelFuture channelFuture = serverBootstrap.bind();
// 添加监听器处理绑定结果
channelFuture.addListener(future -> {
if (future.isSuccess()) {
log.info("服务器启动成功,开始监听端口: {}", port);
} else {
log.error("服务器启动失败,端口: {}", port, future.cause());
bossGroup.shutdownGracefully(); // 绑定失败立即关闭资源
workerGroup.shutdownGracefully();
}
});
// ❌ 移除 sync() 阻塞调用
// channelFuture.channel().closeFuture().sync(); --> 删除这行
// 可选:添加 JVM 关闭钩子优雅关闭资源
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("JVM 正在关闭,准备释放 Netty 资源...");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
log.info("Netty 资源已释放");
}));
}
}

427
mh-framework/src/main/java/com/mh/framework/netty/EchoServerHandler.java

@ -0,0 +1,427 @@
package com.mh.framework.netty;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.mh.common.constant.Constants;
import com.mh.common.core.domain.entity.CollectionParamsManage;
import com.mh.common.core.domain.entity.SysDictData;
import com.mh.common.core.redis.RedisCache;
import com.mh.common.model.request.AdvantechDatas;
import com.mh.common.model.request.AdvantechReceiver;
import com.mh.common.utils.*;
import com.mh.common.utils.spring.SpringUtils;
import com.mh.framework.netty.session.ServerSession;
import com.mh.framework.netty.session.SessionMap;
import com.mh.framework.netty.task.CallbackTask;
//import com.mh.framework.netty.task.CallbackTaskScheduler;
import com.mh.framework.netty.task.CallbackTaskScheduler;
import com.mh.framework.rabbitmq.producer.SendMsgByTopic;
import com.mh.system.service.device.ICollectionParamsManageService;
import com.mh.system.service.device.IGatewayManageService;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
// 调用service层的接口信息
IGatewayManageService gatewayManageService = SpringUtils.getBean(IGatewayManageService.class);
ICollectionParamsManageService collectionParamsManageService = SpringUtils.getBean(ICollectionParamsManageService.class);
SendMsgByTopic sendMsgByTopic = SpringUtils.getBean(SendMsgByTopic.class);
RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
/**
* 空闲次数
*/
private int idleCount = 1;
private int count = 0;
private List<String> orderList;
private int num = 0;
private int size = 0;
private String IP;
private String port;
private String receiveStr = "";
private List<CollectionParamsManage> deviceCodeParamList;
/**
* 客户端连接会触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("Channel active......");
}
/**
* 超时处理
* 如果120秒没有接受客户端的心跳就触发;
* 如果超过3次则直接关闭;
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
if (obj instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) obj;
if (IdleState.READER_IDLE.equals(event.state())) { //如果读通道处于空闲状态,说明没有接收到心跳命令
log.info("第{}已经40秒没有接收到客户端的信息了", idleCount);
receiveStr = "";
num = num + 1;
if (num > size - 1) {
num = 0;
// // 关闭连接
// ctx.close();
// 继续发送下一个采集指令
SendOrderUtils.sendAllOrder(deviceCodeParamList.get(num),ctx,num,size);
} else {
// 继续发送下一个采集指令
SendOrderUtils.sendAllOrder(deviceCodeParamList.get(num), ctx, num, size);
}
}
} else {
super.userEventTriggered(ctx, obj);
}
}
// 对于每一个传入的消息都要被调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
//接收到服务端发来的数据进行业务处理
ByteBuf buf = (ByteBuf) msg;
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);//复制内容到字节数组bytes
buf.clear();
// 截取IP地址
IP = ExchangeStringUtil.getMidString(ctx.channel().remoteAddress() + "", "/", ":");
// 截取端口号
port = ExchangeStringUtil.getMidString(ctx.channel().remoteAddress() + "", ":", "");
if (bytes.length <= 1024) {
//将接收到的数据转为字符串,此字符串就是客户端发送的字符串
receiveStr = receiveStr + ExchangeStringUtil.bytesToHexString(bytes);//将接收到的数据转为字符串,此字符串就是客户端发送的字符串
receiveStr = receiveStr.replace("null", ""); //去null
receiveStr = receiveStr.replace(" ", ""); //去空格
//log.info("channelRead接收到的数据:" + receiveStr + ",length:" + receiveStr.length());
}
} catch (Exception e) {
log.error("channelRead异常", e);
} finally {
ReferenceCountUtil.release(msg);
}
}
// 当前批量读取中的最后一条消息
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//心跳包报文: 24 00 60 95
receiveStr = receiveStr.toUpperCase();//返回值全部变成大写
log.info("channelReadComplete接收到的数据{}, 长度: ===> {}", receiveStr, receiveStr.length());
//心跳包处理
if ((receiveStr.length() == 8) && receiveStr.startsWith("24")) {
// if ((receiveStr.length() == 8) && receiveStr.startsWith("C0A801FE")) {
log.info("接收到心跳包 ===> {}", receiveStr);
// 开始进行会话保存
dealSession(ctx);
idleCount = 1;
port = receiveStr.substring(4, 8);//心跳包包含网关端口(自己定义返回心跳包)
// 更新对应的网关在线情况
gatewayManageService.updateGatewayStatus(receiveStr);
//根据端口或者IP或者心跳包查询网关对应的项目名称
// 生成采集指令
if (!SpringUtils.getBean(RedisCache.class).hasKey(receiveStr)) {
collectionParamsManageService.createDtuCollectionParams();
}
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(receiveStr);
if (StringUtils.isNotNull(arrayCache)) {
deviceCodeParamList = arrayCache.toList(CollectionParamsManage.class);
}
size = deviceCodeParamList.size();
// log.info("deviceCodeParam size ===> {}", size);
// 清空receiveStr
receiveStr = "";
num = 0;
// 发送采集报文
if (size > 0) {
if (idleCount < 2) {
Thread.sleep(200);
SendOrderUtils.sendAllOrder(deviceCodeParamList.get(num), ctx, num, size);
idleCount++;
} else {
ctx.channel().close();
}
} else {
log.info("gateway not find deviceCodeParam!");
}
} else if (receiveStr.length() == 18) {
// 水电表返回数据解析
idleCount = 1;
log.info("水电表、热泵设置接收==>{},长度:{}", receiveStr, receiveStr.length());
nextSendOrder(ctx);
} else if (receiveStr.length() == 12 || receiveStr.length() == 14) {
// 热泵返回数据解析
idleCount = 1;
log.info("热泵读取接收===>{},长度:{},是否存在order_send_read: {}", receiveStr, receiveStr.length(), redisCache.hasKey("order_send_read"));
if (redisCache.hasKey("order_send_read")) {
log.error("order_send_read存在,接收到指令是{}", receiveStr);
if (redisCache.hasKey("order_send_register")) {
Object orderSendRegister = redisCache.getCacheObject("order_send_register");
String orderSendRegisterStr = String.valueOf(orderSendRegister);
// 根据_进行数据转换成数组
// redisCache.setCacheObject("order_send_register",
// collectionParamsManage.getMtCode() + "_"
// + collectionParamsManage.getRegisterAddr() + "_"
// + collectionParamsManage.getRegisterSize() + "_"
// + collectionParamsManage.getParamType() + "_"
// + collectionParamsManage.getDataType() + "_"
// + collectionParamsManage.getOtherName()
// );
String[] split = orderSendRegisterStr.split("_");
CollectionParamsManage collectionParamsManage = new CollectionParamsManage();
collectionParamsManage.setDataType(Integer.valueOf(split[4]));
collectionParamsManage.setParamType(split[3]);
collectionParamsManage.setOtherName(split[5]);
collectionParamsManage.setQuality("0");
analysisReceiveData(receiveStr, collectionParamsManage);
redisCache.deleteObject("order_send_read");
}
} else {
nextSendOrder(ctx);
}
} else if (receiveStr.length() == 16) {
idleCount = 1;
nextSendOrder(ctx);
// 热泵设置指令返回
controlOrder(ctx);
} else if (receiveStr.length() > 20 && receiveStr.length() < 100) {
idleCount = 1;
// 清空receiveStr
nextSendOrder(ctx);
controlOrder(ctx);
}
ctx.flush();
}
private void controlOrder(ChannelHandlerContext ctx) {
// 热泵设置指令返回
if (redisCache.hasKey("order_send")) {
// 判断是否有指令发送
Object orderSend = redisCache.getCacheObject("order_send");
String orderSendStr = String.valueOf(orderSend);
String orderSendRegisterStr = "";
if (redisCache.hasKey("order_send_register")) {
Object orderSendRegister = redisCache.getCacheObject("order_send_register");
orderSendRegisterStr = String.valueOf(orderSendRegister);
// 根据_进行数据转换成数组
// redisCache.setCacheObject("order_send_register",
// collectionParamsManage.getMtCode() + "_"
// + collectionParamsManage.getRegisterAddr() + "_"
// + collectionParamsManage.getRegisterSize() + "_"
// + collectionParamsManage.getRegisterSize() + "_"
// + collectionParamsManage.getDataType()
// );
String[] split = orderSendRegisterStr.split("_");
orderSendRegisterStr = split[1];
} else {
orderSendRegisterStr = orderSendStr.substring(4, 8);
}
// // 发送读取热泵设置温度
// String controlCode = ModbusUtils.createReadOrder(orderSendStr.substring(0, 2),
// "03",
// "0003",
// "1");
// SendOrderUtils.sendOrderToDTU(ctx, controlCode);
if (receiveStr.contains(orderSendStr)) {
String readOrder = ModbusUtils.createReadOrder(orderSendStr.substring(0, 2),
"03",
orderSendRegisterStr,
"1");
// 初始化发送指令
// NettyTools.initReceiveMsg("order_wait_read");
// 发送读取指令
redisCache.setCacheObject("order_send_read", readOrder, 10, TimeUnit.SECONDS);
ctx.writeAndFlush(ModbusUtils.createByteBuf(readOrder));
// 发送读取指令
log.error("热泵设置读取指令发送:{},order_send_read键值:{}", readOrder, redisCache.hasKey("order_send_read"));
log.error("热泵设置指令返回:{}", receiveStr);
NettyTools.setReceiveMsg("order_wait", receiveStr);
redisCache.deleteObject("order_send");
receiveStr = "";
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
private void dealSession(ChannelHandlerContext ctx) {
// 获取表号
String deviceCode =receiveStr;
String meterNum = deviceCode;
deviceCode = deviceCode + ctx.channel().remoteAddress();
//新的session的创建
ServerSession session = new ServerSession(ctx.channel(), deviceCode);
//进行登录逻辑处理,异步进行处理。并且需要知道 处理的结果。 callbacktask就要
//派上用场了
String finalDeviceCode = deviceCode;
CallbackTaskScheduler.add(new CallbackTask<Boolean>() {
@Override
public Boolean execute() throws Exception {
//进行 login 逻辑的处理
return action(session, finalDeviceCode, ctx);
}
//没有异常的话,我们进行处理
@Override
public void onBack(Boolean result) {
if(result) {
log.info("设备保存会话: 设备号 = " + session.getSessionId());
//ctx.pipeline().remove(LoginRequestHandler.class); //压测需要放开
} else {
log.info("设备刷新会话: 设备号 = " + session.getSessionId());
SessionMap.inst().updateSession(finalDeviceCode ,session, meterNum);
//log.info("设备登录失败: 设备号 = " + session.getSessionId());
//ServerSession.closeSession(ctx);
// 假如说已经在会话中了,直接断开连接
//ctx.close();
}
}
//有异常的话,我们进行处理
@Override
public void onException(Throwable t) {
log.info("设备登录异常: 设备号 = " + session.getSessionId());
ServerSession.closeSession(ctx);
}
});
}
private void nextSendOrder(ChannelHandlerContext ctx) throws InterruptedException {
// 发送指令响应不用解析
if (receiveStr.length() != 16 && receiveStr.length() < 20) {
// 解析采集的报文,并保存到数据库
analysisReceiveData(receiveStr, deviceCodeParamList.get(num));
}
// 判断是否有远程指令发送,如果有先不采集
if (redisCache.hasKey("order_send")) {
log.error("有远程设置指令发送,不进行采集");
return;
}
// 清空receiveStr
receiveStr = "";
// 判断发送的下标,如果不等于指令数组大小
num = num + 1;
if (num > size - 1) {
num = 0;
Thread.sleep(1000);
// 继续发送下一个采集指令
SendOrderUtils.sendAllOrder(deviceCodeParamList.get(num), ctx, num, size);
log.info("------一轮采集完成,继续下一轮--------");
} else {
// 添加一个状态值,判断是否继续发送指令 update by ljf on 2020-08-07
if (Constants.WEB_FLAG) {
num = 0;
// 关闭连接
receiveStr = null;
ctx.close();
} else {
Thread.sleep(1000);
// 继续发送下一个采集指令
SendOrderUtils.sendAllOrder(deviceCodeParamList.get(num), ctx, num, size);
}
}
}
private void analysisReceiveData(final String receiveStr, final CollectionParamsManage deviceCodeParamEntity) {
AnalysisReceiveOrder485 analysisReceiveOrder485 = new AnalysisReceiveOrder485();
String analysisData = "";
switch (deviceCodeParamEntity.getParamType()) {
case "16" ->
// 电表
analysisData = analysisReceiveOrder485.analysisMeterOrder485(receiveStr, deviceCodeParamEntity);
case "18" ->
// 水表
analysisData = analysisReceiveOrder485.analysisWaterOrder485(receiveStr, deviceCodeParamEntity);
case "5" ->
// 热泵故障报警
analysisData = analysisReceiveOrder485.analysisHeatPumpOrder485(receiveStr, deviceCodeParamEntity);
case "2" ->
// 热泵启停控制
analysisData = analysisReceiveOrder485.analysisHeatPumpOrder485(receiveStr, deviceCodeParamEntity);
case "12" ->
// 热泵实际温度
analysisData = analysisReceiveOrder485.analysisHeatPumpOrder485(receiveStr, deviceCodeParamEntity);
case "14" ->
// 热泵读取温度设置
analysisData = analysisReceiveOrder485.analysisHeatPumpOrder485(receiveStr, deviceCodeParamEntity);
case "48" ->
// 热泵读取电流
analysisData = analysisReceiveOrder485.analysisHeatPumpOrder485(receiveStr, deviceCodeParamEntity);
case "11" ->
// 液位计
analysisData = analysisReceiveOrder485.analysisLiquidOrder485(receiveStr, deviceCodeParamEntity);
default -> {
log.info("设备类型错误");
return;
}
}
if (analysisData.isEmpty()) {
log.info("解析数据为空");
return;
}
// 格式化数据,配置成研华网关 AdvantechReceiver
AdvantechReceiver advantechReceiver = new AdvantechReceiver();
advantechReceiver.setTs(DateUtils.dateToString(new Date(), Constants.DATE_FORMAT));
List<AdvantechDatas> advantechDatas = new ArrayList<>();
AdvantechDatas datas = new AdvantechDatas();
datas.setValue(new BigDecimal(analysisData));
datas.setTag(deviceCodeParamEntity.getOtherName());
datas.setQuality(0);
advantechDatas.add(datas);
advantechReceiver.setD(advantechDatas);
sendMsgByTopic.sendToDeviceMQ(JSONObject.toJSONString(advantechReceiver));
}
// 异常捕捉
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.getCause().printStackTrace();
log.info("异常捕捉,执行ctx.close" + cause.getCause());
ctx.close(); // 关闭该Channel
}
// 客户端断开
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.close();// 关闭流
log.info("客户端断开,执行ctx.close()......");
}
private boolean action(ServerSession session, String deviceCode, ChannelHandlerContext ctx) {
//user验证
boolean isValidUser = checkUser(deviceCode,session);
session.bind();
return true;
}
private boolean checkUser(String deviceCode,ServerSession session) {
//当前用户已经登录
if(SessionMap.inst().hasLogin(deviceCode)) {
log.info("设备已经登录: 设备号 = " + deviceCode);
return false;
}
//一般情况下,我们会将 user存储到 DB中,然后对user的用户名和密码进行校验
//但是,我们这边没有进行db的集成,所以我们想一个别的办法进行user的校验。在我们的sessionMap进行以下校验
//为什么选sessionmap,因为我们user的会话,都是存储到sessionmap中的,sessionmap中只要有这个user的会话,说明就是ok的
return true;
}
}

18
mh-framework/src/main/java/com/mh/framework/netty/INettyService.java

@ -0,0 +1,18 @@
package com.mh.framework.netty;
import com.mh.common.core.domain.entity.OrderEntity;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description netty
* @date 2025-06-06 15:13:06
*/
public interface INettyService {
boolean sendOrder(List<OrderEntity> changeValues);
}

135
mh-framework/src/main/java/com/mh/framework/netty/NettyServiceImpl.java

@ -0,0 +1,135 @@
package com.mh.framework.netty;
import com.mh.common.core.domain.AjaxResult;
import com.mh.common.core.domain.entity.CollectionParamsManage;
import com.mh.common.core.domain.entity.GatewayManage;
import com.mh.common.core.domain.entity.OrderEntity;
import com.mh.common.core.redis.RedisCache;
import com.mh.common.core.redis.RedisLock;
import com.mh.common.utils.ModbusUtils;
import com.mh.common.utils.NettyTools;
import com.mh.common.utils.StringUtils;
import com.mh.framework.netty.session.ServerSession;
import com.mh.framework.netty.session.SessionMap;
import com.mh.system.mapper.device.CollectionParamsManageMapper;
import com.mh.system.mapper.device.GatewayManageMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description netty实现类
* @date 2025-06-06 15:13:23
*/
@Slf4j
@Service
public class NettyServiceImpl implements INettyService {
@Resource
private CollectionParamsManageMapper collectionParamsManageMapper;
@Resource
private GatewayManageMapper gatewayManageMapper;
@Resource
private RedisCache redisCache;
@Resource
private RedisLock redisLock;
@Override
public boolean sendOrder(List<OrderEntity> changeValues) {
for (OrderEntity changeValue : changeValues) {
String cpmId = changeValue.getId();
CollectionParamsManage collectionParamsManage = collectionParamsManageMapper.selectById(cpmId);
if (null == collectionParamsManage) {
return false;
}
GatewayManage gatewayManage = gatewayManageMapper.selectById(collectionParamsManage.getGatewayId());
if (null == gatewayManage || StringUtils.isEmpty(gatewayManage.getHeartBeat())) {
return false;
}
ConcurrentHashMap<String, ServerSession> map = SessionMap.inst().getMap();
Set<Map.Entry<String, ServerSession>> entries = map.entrySet();
boolean flag = false;
String keyVal = null;
for (Map.Entry<String, ServerSession> entry : entries) {
String key = entry.getKey();
if (key.contains(gatewayManage.getHeartBeat())){
flag = true;
keyVal = key;
break;
}
}
if (flag) {
ServerSession serverSession = map.get(keyVal);
// 目前只有DTU,modbus方式,只创建modbus先
String controlCode = ModbusUtils.createControlCode(collectionParamsManage.getMtCode(),
changeValue.getType(),
collectionParamsManage.getRegisterAddr(),
changeValue.getParam());
if (StringUtils.isEmpty(controlCode)) {
log.error("创建控制码失败");
return false;
}
String requestId = UUID.randomUUID().toString(); // 唯一标识当前请求
String lockKey = "lock:order_send:" + gatewayManage.getHeartBeat(); // 按网关分锁
try {
if (!redisLock.tryLock(lockKey, requestId, 10, 10)) {
log.warn("获取锁失败,当前操作繁忙");
return false;
}
// 初始化发送指令
NettyTools.initReceiveMsg("order_wait");
// 设置缓存,方便在netty中判断发送的指令
redisCache.setCacheObject("order_send", controlCode, 10, TimeUnit.SECONDS);
redisCache.setCacheObject("order_send_register",
collectionParamsManage.getMtCode() + "_"
+ collectionParamsManage.getRegisterAddr() + "_"
+ collectionParamsManage.getRegisterSize() + "_"
+ collectionParamsManage.getParamType() + "_"
+ collectionParamsManage.getDataType() + "_"
+ collectionParamsManage.getOtherName()
);
Thread.sleep(500);
// 发送控制指令
serverSession.getChannel().writeAndFlush(ModbusUtils.createByteBuf(controlCode));
// 等待指令
if (NettyTools.waitReceiveMsg("order_wait")) {
// 初始化发送指令
Thread.sleep(3000);
return true;
// if (NettyTools.waitReceiveMsg("order_wait_read")) {
// return true;
// } else {
// log.error("读取指令异常,心跳包:{}", gatewayManage.getHeartBeat());
// return false;
// }
} else {
log.error("发送指令异常,心跳包:{}", gatewayManage.getHeartBeat());
return false;
}
} catch (InterruptedException e) {
log.error("发送指令异常", e);
} finally {
redisLock.unlock(lockKey, requestId);
}
}
log.error("当前设备不在线,心跳包:{}",gatewayManage.getHeartBeat());
return false;
}
return false;
}
}

33
mh-framework/src/main/java/com/mh/framework/netty/ServerChannelInitializer.java

@ -0,0 +1,33 @@
package com.mh.framework.netty;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
/* LineBasedFrameDecoder的工作原理是依次遍历ByteBuf中的可读字节
判断看其是否有\n \r\n 如果有就以此位置为结束位置
从可读索引到结束位置的区间的字节就组成了一行 它是以换行符为结束标志的解码器
支持携带结束符和不带结束符两种解码方式同时支持配置单行的最大长度
如果读到了最大长度之后仍然没有发现换行符则抛出异常同时忽略掉之前读到的异常码流*/
// pipeline.addLast(new LineBasedFrameDecoder(10010));
//字符串解码和编码
//LineBasedFrameDecoder + StringDecoder 就是一个按行切换的文本解码器。
// pipeline.addLast( new StringDecoder());
// pipeline.addLast( new StringEncoder());
// 设置读写超时操作
// 入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式
pipeline.addLast(new IdleStateHandler(40, 40, 40, TimeUnit.SECONDS));
//服务器的逻辑
pipeline.addLast("handler", new EchoServerHandler());
}
}

66
mh-framework/src/main/java/com/mh/framework/netty/session/ServerSession.java

@ -0,0 +1,66 @@
package com.mh.framework.netty.session;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class ServerSession {
public static final AttributeKey<ServerSession> SESSION_KEY =
AttributeKey.valueOf("SESSION_KEY");
//通道
private Channel channel;
private final String sessionId;
private boolean isLogin = false;
public ServerSession(Channel channel, String deviceCode){
this.channel = channel;
this.sessionId = deviceCode;
}
//session需要和通道进行一定的关联,他是在构造函数中关联上的;
//session还需要通过sessionkey和channel进行再次的关联;channel.attr方法.set当前的
// serverSession
//session需要被添加到我们的SessionMap中
public void bind(){
log.info("server Session 会话进行绑定 :" + channel.remoteAddress());
channel.attr(SESSION_KEY).set(this);
SessionMap.inst().addSession(sessionId, this);
this.isLogin = true;
}
//通过channel获取session
public static ServerSession getSession(ChannelHandlerContext ctx){
Channel channel = ctx.channel();
return channel.attr(SESSION_KEY).get();
}
//关闭session,新增返回一个meterNum用于纪录设备下线时间2024-05-08
public static String closeSession(ChannelHandlerContext ctx){
String meterNum = null;
ServerSession serverSession = ctx.channel().attr(SESSION_KEY).get();
if(serverSession != null && serverSession.getSessionId() != null) {
ChannelFuture future = serverSession.channel.close();
future.addListener((ChannelFutureListener) future1 -> {
if(!future1.isSuccess()) {
log.info("Channel close error!");
}
});
ctx.close();
meterNum = serverSession.sessionId;
SessionMap.inst().removeSession(serverSession.sessionId);
log.info(ctx.channel().remoteAddress()+" "+serverSession.sessionId + "==>移除会话");
}
return meterNum;
}
//写消息
public void writeAndFlush(Object msg) {
channel.writeAndFlush(msg);
}
}

96
mh-framework/src/main/java/com/mh/framework/netty/session/SessionMap.java

@ -0,0 +1,96 @@
package com.mh.framework.netty.session;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Data
@Slf4j
public class SessionMap {
private ThreadLocal<Boolean> sceneThreadLocal = new ThreadLocal<>();
//用单例模式进行sessionMap的创建
private SessionMap(){}
private static SessionMap singleInstance = new SessionMap();
public static SessionMap inst() {
return singleInstance;
}
//进行会话的保存
//key 我们使用 sessionId;value 需要是 serverSession
private ConcurrentHashMap<String, ServerSession> map = new ConcurrentHashMap<>(256);
//添加session
public void addSession(String sessionId, ServerSession s) {
map.put(sessionId, s);
log.info("IP地址:"+s.getChannel().remoteAddress()+" "+ sessionId + " 表具上线,总共表具:" + map.size());
}
//删除session
public void removeSession(String sessionId) {
if(map.containsKey(sessionId)) {
ServerSession s = map.get(sessionId);
map.remove(sessionId);
log.info("设备id下线:{},在线设备:{}", s.getSessionId(), map.size() );
}
return;
}
public boolean hasLogin(String sessionId) {
Iterator<Map.Entry<String, ServerSession>> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<String, ServerSession> next = iterator.next();
if(sessionId != null && sessionId.equalsIgnoreCase(next.getValue().getSessionId())) {
return true ;
}
}
return false;
}
//如果在线,肯定有sessionMap里保存的 serverSession
//如果不在线,serverSession也没有。用这个来判断是否在线
public List<ServerSession> getSessionBy(String sessionId) {
return map.values().stream().
filter(s -> s.getSessionId().equals(sessionId)).
collect(Collectors.toList());
}
public boolean getScene() {
return sceneThreadLocal.get();
}
public void initScene(Boolean status) {
if (sceneThreadLocal == null) {
log.info("======创建ThreadLocal======");
sceneThreadLocal = new ThreadLocal<>();
}
log.info("设置状态==>" + status);
sceneThreadLocal.set(status);
}
public void clearScene() {
initScene(null);
sceneThreadLocal.remove();
}
public void updateSession(String sessionId, ServerSession session, String meterNum) {
Iterator<Map.Entry<String, ServerSession>> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<String, ServerSession> next = iterator.next();
if (next.getKey().contains(meterNum)){
iterator.remove();
}
if(sessionId != null && sessionId.equalsIgnoreCase(next.getValue().getSessionId())) {
next.setValue(session);
}
}
}
}

20
mh-framework/src/main/java/com/mh/framework/netty/task/CallbackTask.java

@ -0,0 +1,20 @@
package com.mh.framework.netty.task;
/**
* @author LJF
* @version 1.0
* @project TAD_Server
* @description 回调任务
* @date 2023/7/3 15:34:11
*/
public interface CallbackTask<T> {
T execute() throws Exception;
/**
* // 执行没有 异常的情况下的 返回值
* @param t
*/
void onBack(T t);
void onException(Throwable t);
}

78
mh-framework/src/main/java/com/mh/framework/netty/task/CallbackTaskScheduler.java

@ -0,0 +1,78 @@
package com.mh.framework.netty.task;
import com.google.common.util.concurrent.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author LJF
* @version 1.0
* @project TAD_Server
* @description 回调任务
* @date 2023/7/3 15:34:11
*/
public class CallbackTaskScheduler extends Thread {
private final BlockingQueue<CallbackTask> executeTaskQueue =
new LinkedBlockingQueue<>();
private final ExecutorService pool = Executors.newCachedThreadPool();
private final ListeningExecutorService lpool = MoreExecutors.listeningDecorator(pool);
private static CallbackTaskScheduler inst = new CallbackTaskScheduler();
private final AtomicBoolean running = new AtomicBoolean(true);
private CallbackTaskScheduler() {
this.start();
}
//add task
public static <T> void add(CallbackTask<T> executeTask) {
inst.executeTaskQueue.offer(executeTask);
}
@Override
public void run() {
while (running.get()) {
handleTask();
}
}
/**
* 停止调度器
*/
public static void shutdown() {
inst.running.set(false);
inst.pool.shutdown();
}
//任务执行
private void handleTask() {
try {
// 使用 take() 阻塞等待,直到有任务
CallbackTask executeTask = executeTaskQueue.take();
handleTask(executeTask);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private <T> void handleTask(CallbackTask<T> executeTask) {
ListenableFuture<T> future = lpool.submit(new Callable<T>() {
public T call() throws Exception {
return executeTask.execute();
}
});
Futures.addCallback(future, new FutureCallback<T>() {
@Override
public void onSuccess(T t) {
executeTask.onBack(t);
}
@Override
public void onFailure(Throwable throwable) {
executeTask.onException(throwable);
}
}, lpool);
}
}

6
mh-framework/src/main/java/com/mh/framework/netty/task/ExecuteTask.java

@ -0,0 +1,6 @@
package com.mh.framework.netty.task;
//不需要知道异步线程的 返回值
public interface ExecuteTask {
void execute();
}

67
mh-framework/src/main/java/com/mh/framework/netty/task/FutureTaskScheduler.java

@ -0,0 +1,67 @@
package com.mh.framework.netty.task;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author LJF
* @version 1.0
* @project TAD_Server
* @description 任务定时
* @date 2023/7/3 15:34:11
*/
public class FutureTaskScheduler extends Thread{
private ConcurrentLinkedQueue<ExecuteTask> executeTaskQueue =
new ConcurrentLinkedQueue<>();
private long sleepTime = 200;
private ExecutorService pool = Executors.newFixedThreadPool(10);
private static FutureTaskScheduler inst = new FutureTaskScheduler();
public FutureTaskScheduler() {
this.start();
}
//任务添加
public static void add(ExecuteTask executeTask) {
inst.executeTaskQueue.add(executeTask);
}
@Override
public void run() {
while (true) {
handleTask();
//threadSleep(sleepTime);
}
}
private void threadSleep(long sleepTime) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//执行任务
private void handleTask() {
ExecuteTask executeTask;
while (executeTaskQueue.peek() != null) {
executeTask = executeTaskQueue.poll();
handleTask(executeTask);
}
//刷新心跳时间
}
private void handleTask(ExecuteTask executeTask) {
pool.execute(new ExecuteRunnable(executeTask));
}
class ExecuteRunnable implements Runnable {
ExecuteTask executeTask;
public ExecuteRunnable(ExecuteTask executeTask) {
this.executeTask = executeTask;
}
@Override
public void run() {
executeTask.execute();
}
}
}

291
mh-quartz/src/main/java/com/mh/quartz/task/HotWaterTask.java

@ -0,0 +1,291 @@
package com.mh.quartz.task;
import com.mh.common.constant.EnergyType;
import com.mh.common.core.domain.entity.DataMonth;
import com.mh.common.utils.StringUtils;
import com.mh.system.service.device.IDeviceLedgerService;
import com.mh.system.service.energy.IEnergyQueryService;
import com.mh.system.service.energy.IWaterLevelService;
import com.mh.system.service.energy.IWaterTempService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 生活热水供水系统定时器
* @date 2025-06-17 16:12:04
*/
@Slf4j
@Component("hotWaterTask")
public class HotWaterTask {
@Resource
private IDeviceLedgerService deviceLedgerService;
@Resource
private IEnergyQueryService energyQueryService;
@Resource
private IWaterTempService waterTempService;
@Resource
private IWaterLevelService waterLevelService;
private boolean createOrUpdateDeviceState = false;
// 计算能耗表
private boolean calcEnergyState = false;
// 计算楼层能耗数据
private boolean calcFloorEnergyState = false;
// 计算热水温度状态
private boolean calcWaterTempState = false;
// 计算水箱水位
private boolean calcWaterLevelState = false;
// 计算数据分析
private boolean calcAnalysisState = false;
/**
* 定时数据分析
* @param lastHourTime
*/
public void calcAnalysisData(String lastHourTime) {
try {
if (!calcAnalysisState) {
calcAnalysisState = true;
if (StringUtils.isEmpty(lastHourTime)) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
lastHourTime = lastHour.format(formatter);
}
energyQueryService.calcAnalysisData(lastHourTime);
}
} catch (Exception e) {
log.error("计算数据分析", e);
calcAnalysisState = false;
} finally {
calcAnalysisState = false;
}
}
/**
* 定时计算水箱水位插入到存储表中
*/
public void calcWaterLevel() {
try {
if (!calcWaterLevelState) {
calcWaterLevelState = true;
waterLevelService.calcWaterLevel();
}
} catch (Exception e) {
log.error("计算水箱水位失败", e);
calcWaterLevelState = false;
} finally {
calcWaterLevelState = false;
}
}
/**
* 新增或者更新设备状态表
*/
public void createOrUpdateDeviceState() {
try {
if (!createOrUpdateDeviceState) {
createOrUpdateDeviceState = true;
deviceLedgerService.createOrUpdateDeviceState();
}
} catch (Exception e) {
log.error("新增或者更新设备状态表失败", e);
createOrUpdateDeviceState = false;
} finally {
createOrUpdateDeviceState = false;
}
}
/**
* 定时计算水温度插入到存储表中
*/
public void calcWaterTemp() {
try {
if (!calcWaterTempState) {
calcWaterTempState = true;
waterTempService.calcWaterTemp();
}
} catch (Exception e) {
log.error("计算水温度失败", e);
calcWaterTempState = false;
} finally {
calcWaterTempState = false;
}
}
/**
* 定时计算楼层能耗数据
* @param lastHourTime
*/
public void calcFloorEnergyData(String lastHourTime) {
try {
if (!calcFloorEnergyState) {
calcFloorEnergyState = true;
if (StringUtils.isEmpty(lastHourTime)) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
lastHourTime = lastHour.format(formatter);
}
energyQueryService.calcFloorEnergyDataDetail(lastHourTime);
}
} catch (Exception e) {
log.error("计算楼层能耗数据失败", e);
calcFloorEnergyState = false;
} finally {
calcFloorEnergyState = false;
}
}
/**
* 定时计算能耗数据任务
* @param lastHourTime
*/
public void calcEnergyData(String lastHourTime) {
try {
if (!calcEnergyState) {
calcEnergyState = true;
calcEnergyDataDetail(lastHourTime);
}
} catch (Exception e) {
log.error("计算能耗表失败", e);
calcEnergyState = false;
} finally {
calcEnergyState = false;
}
}
/**
* 计算能耗表
*/
public void calcEnergyDataDetail(String lastHourTime) {
//TODO 1、查询sql获取对应计算的楼层id、楼层名称用来当作楼栋id和楼栋名称
List<Map<String, Object>> floorInfos = energyQueryService.queryFloorInfo();
// 开始遍历
if (StringUtils.isEmpty(lastHourTime)) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00:00");
lastHourTime = lastHour.format(formatter);
}
String tableName = "data_hour" + lastHourTime.substring(0, 4);
List<Map<String, Double>> hourList = new ArrayList<>();
List<Map<String, Double>> dayList = new ArrayList<>();
List<Map<String, Double>> monthList = new ArrayList<>();
List<Map<String, Double>> yearList = new ArrayList<>();
for (Map<String, Object> floorInfo : floorInfos) {
String buildingId = floorInfo.get("id").toString();
String buildingName = floorInfo.get("building_name").toString();
// 根据楼栋id查询对应楼层下的所有设备
//TODO 2、计算每小时用电量、用水量、单耗(用电量/用水量)
Map<String, Double> hourMap = processEnergy(buildingId, buildingName, lastHourTime, tableName, "hour", EnergyType.HOUR);
if (null != hourMap) {
hourList.add(hourMap);
}
//TODO 3、计算每日用用电量、用水量、单耗(用电量/用水量)
Map<String, Double> dayMap = processEnergy(buildingId, buildingName, lastHourTime, tableName, "day", EnergyType.DAY);
if (null != dayMap) {
dayList.add(dayMap);
}
//TODO 4、计算月用电量、用水量、单耗(用电量/用水量)
Map<String, Double> monthMap = processEnergy(buildingId, buildingName, lastHourTime, tableName, "month", EnergyType.MONTH);
if (null != monthMap) {
monthList.add(monthMap);
}
//TODO 5、计算年用电量、用水量、单耗(用电量/用水量)
Map<String, Double> yearMap = processEnergy(buildingId, buildingName, lastHourTime, tableName, "year", EnergyType.YEAR);
if (null != yearMap) {
yearList.add(yearMap);
}
}
// 更新插入所有楼栋的数据表
processAndInsertEnergyData("hour", hourList, lastHourTime);
processAndInsertEnergyData("day", dayList, lastHourTime);
processAndInsertEnergyData("month", monthList, lastHourTime);
processAndInsertEnergyData("year", yearList, lastHourTime);
}
private void processAndInsertEnergyData(String timeUnit, List<Map<String, Double>> dataList, String lastHourTime) {
if (dataList.isEmpty()) return;
double electricity = 0.0;
double water = 0.0;
for (Map<String, Double> map : dataList) {
electricity += map.getOrDefault("electricity", 0.0);
water += map.getOrDefault("water", 0.0);
}
double specificConsumption = water > 0 ? electricity / water : 0.0;
energyQueryService.insertOrUpdateEnergyData(timeUnit, "所有", "所有", lastHourTime, electricity, water, specificConsumption);
}
private Map<String, Double> processEnergy(String buildingId, String buildingName, String curDate, String tableName, String dateType, EnergyType energyType) {
List<DataMonth> datas = energyQueryService.queryEnergyDatas(tableName, buildingId, curDate, dateType);
Map<String, Double> result = new HashMap<>();
double electricity = 0.0;
double water = 0.0;
double specificConsumption = 0.0;
if (datas == null || datas.isEmpty()) {
log.warn("未找到 {} 类型的能耗数据,buildingId={}, curDate={}", energyType, buildingId, curDate);
result.put("electricity", electricity);
result.put("water", water);
} else {
Map<String, List<DataMonth>> grouped = datas.stream()
.collect(Collectors.groupingBy(DataMonth::getDeviceType));
electricity = grouped.getOrDefault("5", Collections.emptyList()).stream()
.mapToDouble(data -> Optional.ofNullable(data.getCalcValue()).map(BigDecimal::doubleValue).orElse(0.0))
.sum();
result.put("electricity", electricity);
water = grouped.getOrDefault("23", Collections.emptyList()).stream()
.mapToDouble(data -> Optional.ofNullable(data.getCalcValue()).map(BigDecimal::doubleValue).orElse(0.0))
.sum();
result.put("water", water);
specificConsumption = water > 0 ? electricity / water : 0.0;
log.info("楼栋: {}, {}电表总量: {}, 水表总量: {}, 单耗: {}", buildingName, energyType, electricity, water, specificConsumption);
}
energyQueryService.insertOrUpdateEnergyData(
energyType.getCode(), buildingId, buildingName, curDate,
electricity,
water,
specificConsumption
);
return result;
}
}

38
mh-system/src/main/java/com/mh/system/mapper/device/CollectionParamsManageMapper.java

@ -3,6 +3,7 @@ package com.mh.system.mapper.device;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.dto.TempHumidityDTO; import com.mh.common.core.domain.dto.TempHumidityDTO;
import com.mh.common.core.domain.entity.CollectionParamsManage; import com.mh.common.core.domain.entity.CollectionParamsManage;
import com.mh.common.core.domain.entity.FloorInfo;
import com.mh.common.core.domain.vo.CollectionParamsManageVO; import com.mh.common.core.domain.vo.CollectionParamsManageVO;
import com.mh.common.core.domain.vo.DeviceMonitorVO; import com.mh.common.core.domain.vo.DeviceMonitorVO;
import com.mh.common.core.domain.vo.HotWaterControlListVO; import com.mh.common.core.domain.vo.HotWaterControlListVO;
@ -218,9 +219,9 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
" order by dl.device_type ,dl.order_num ,cpm.order_num ") " order by dl.device_type ,dl.order_num ,cpm.order_num ")
List<CollectionParamsManageVO> selectBySystemType(@Param("systemType") String systemType); List<CollectionParamsManageVO> selectBySystemType(@Param("systemType") String systemType);
@Select("select " + @Select("<script>" +
" hi.house_name || right(cpm.other_name, " + "select " +
" 4) as name, " + " hi.house_name || right(cpm.other_name, 4) as name, " +
" cpm.cur_value as value, " + " cpm.cur_value as value, " +
" cpm.cur_time as \"curTime\" " + " cpm.cur_time as \"curTime\" " +
"from " + "from " +
@ -234,11 +235,17 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
"where " + "where " +
" (cpm.param_type = '12' " + " (cpm.param_type = '12' " +
" or cpm.param_type = '13') " + " or cpm.param_type = '13') " +
" and csr.floor_id = #{floorId} " +
" and cpm.system_type = #{systemType}" + " and cpm.system_type = #{systemType}" +
" order by hi.house_name, cpm.param_type ") " and hi.house_name is not null " +
" and csr.floor_id IN " +
" <foreach collection='floorIds' item='floorId' open='(' separator=',' close=')'>" +
" #{floorId}" +
" </foreach>" +
" order by hi.house_name, cpm.param_type " +
"</script>")
List<Map<String, Object>> selectBySystemTypeAndBuildingId(@Param("systemType") String systemType, List<Map<String, Object>> selectBySystemTypeAndBuildingId(@Param("systemType") String systemType,
@Param("floorId") String floor_id); @Param("floorIds") List<String> floorIds);
@Select("select " + @Select("select " +
" dl.id, " + " dl.id, " +
@ -297,6 +304,7 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
" csr.floor_id = #{floorId} " + " csr.floor_id = #{floorId} " +
" and cpm.system_type = #{systemType} " + " and cpm.system_type = #{systemType} " +
" and cpm.is_use = 0 " + " and cpm.is_use = 0 " +
" and hi.house_name is not null " +
" order by dl.order_num ") " order by dl.order_num ")
List<HotWaterControlListVO> selectHotWaterBySystemTypeAndBuildingId(@Param("systemType") String systemType, List<HotWaterControlListVO> selectHotWaterBySystemTypeAndBuildingId(@Param("systemType") String systemType,
@Param("floorId") String floorId); @Param("floorId") String floorId);
@ -309,7 +317,8 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
" cpm.other_name, " + " cpm.other_name, " +
" cpm.cur_value, " + " cpm.cur_value, " +
" cpm.cur_time, " + " cpm.cur_time, " +
" cpm.param_type " + " cpm.param_type," +
" cpm.quality " +
"from " + "from " +
" collection_params_manage cpm " + " collection_params_manage cpm " +
"left join device_ledger dl on " + "left join device_ledger dl on " +
@ -320,7 +329,8 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
" csr.house_id = hi.id " + " csr.house_id = hi.id " +
"where " + "where " +
" csr.house_id = #{houseId} " + " csr.house_id = #{houseId} " +
" and cpm.system_type = #{systemType} " + " and cpm.system_type = #{systemType}" +
" and cpm.is_use = 0 " +
" order by dl.order_num ") " order by dl.order_num ")
List<CollectionParamsManageVO> selectBySystemTypeAndHouseId(@Param("systemType") String systemType, List<CollectionParamsManageVO> selectBySystemTypeAndHouseId(@Param("systemType") String systemType,
@Param("houseId") String houseId); @Param("houseId") String houseId);
@ -338,4 +348,16 @@ public interface CollectionParamsManageMapper extends BaseMapper<CollectionParam
" and device_ledger_id is not null " + " and device_ledger_id is not null " +
" group by device_ledger_id;") " group by device_ledger_id;")
List<String> OffLine(); List<String> OffLine();
@Select("select * from collection_params_manage cpm " +
" where (cpm.system_type = '1' or cpm.system_type = '6') and is_use = 0 " +
" and (param_type= '16' " +
" or param_type='18' " +
" or param_type = '5' " +
" or param_type = '2' " +
" or param_type = '12' " +
" or param_type = '14' " +
" or param_type = '11' " +
" or param_type = '48')")
List<CollectionParamsManage> createOrderList();
} }

13
mh-system/src/main/java/com/mh/system/mapper/device/DeviceLedgerMapper.java

@ -2,9 +2,11 @@ package com.mh.system.mapper.device;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.DeviceLedger; import com.mh.common.core.domain.entity.DeviceLedger;
import org.apache.ibatis.annotations.Mapper; import com.mh.common.core.domain.entity.DeviceState;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Update; import org.apache.ibatis.mapping.StatementType;
import java.util.List;
/** /**
* @author LJF * @author LJF
@ -21,4 +23,9 @@ public interface DeviceLedgerMapper extends BaseMapper<DeviceLedger> {
@Update("update device_ledger set status = #{status}, update_time = current_timestamp where id = #{id}") @Update("update device_ledger set status = #{status}, update_time = current_timestamp where id = #{id}")
void updateOnlineOrOfflineStatus(@Param("id") String deviceLedgerId, @Param("status") int integer); void updateOnlineOrOfflineStatus(@Param("id") String deviceLedgerId, @Param("status") int integer);
@Update("select pro_device_state(#{curDate})")
@Options(statementType = StatementType.CALLABLE)
void createOrUpdateDeviceState(@Param("curDate") String curDate);
} }

22
mh-system/src/main/java/com/mh/system/mapper/device/DeviceStateMapper.java

@ -0,0 +1,22 @@
package com.mh.system.mapper.device;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.DeviceState;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 设备状态mapper类
* @date 2025-06-17 17:40:14
*/
@Mapper
public interface DeviceStateMapper extends BaseMapper<DeviceState> {
@Select("select * from device_state where system_type = #{systemType} and date(cur_date) = date(now()) limit 1")
List<DeviceState> deviceState(String systemType);
}

2
mh-system/src/main/java/com/mh/system/mapper/device/GatewayManageMapper.java

@ -19,4 +19,6 @@ public interface GatewayManageMapper extends BaseMapper<GatewayManage> {
@Update("update gateway_manage set status = 0, connect_time = CURRENT_TIMESTAMP where id = #{gatewayId}") @Update("update gateway_manage set status = 0, connect_time = CURRENT_TIMESTAMP where id = #{gatewayId}")
void updateOnlineStatus(@Param("gatewayId") String gatewayId); void updateOnlineStatus(@Param("gatewayId") String gatewayId);
@Update("update gateway_manage set status = 0, connect_time = CURRENT_TIMESTAMP where heart_beat = #{heartBeat}")
void updateOnlineStatusByHeartBeat(@Param("heartBeat") String heartBeat);
} }

56
mh-system/src/main/java/com/mh/system/mapper/energy/AnalysisMapper.java

@ -0,0 +1,56 @@
package com.mh.system.mapper.energy;
import com.mh.common.core.domain.entity.AnalysisMonth;
import com.mh.common.core.domain.entity.AnalysisYear;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 用能分析
* @date 2025-06-24 15:10:04
*/
@Mapper
public interface AnalysisMapper {
/**
* 分析查询
* 根据日期楼栋查询
* @param curDate
* @param buildingId
* @return
*/
@Select("select * from analysis_elect_year where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisYear> queryAnalysisElectYear(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_Water_year where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisYear> queryAnalysisWaterYear(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_Energy_year where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisYear> queryAnalysisEnergyYear(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_Maintain_year where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisYear> queryAnalysisMaintainYear(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_runtime_year where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisYear> queryAnalysisRuntimeYear(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_elect_month where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisMonth> queryAnalysisElectMonth(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_Water_month where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisMonth> queryAnalysisWaterMonth(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_Energy_month where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisMonth> queryAnalysisEnergyMonth(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_maintain_month where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisMonth> queryAnalysisMaintainMonth(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
@Select("select * from analysis_runtime_month where cur_date=#{curDate} and building_id=#{buildingId} order by id ")
List<AnalysisMonth> queryAnalysisRuntimeMonth(@Param("curDate") String curDate, @Param("buildingId") String buildingId);
}

28
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyDayMapper.java

@ -0,0 +1,28 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyDay;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.poi.ss.formula.functions.T;
import java.math.BigDecimal;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyDayMapper extends BaseMapper<EnergyDay> {
@Update("update energy_day set elect_value = #{electricity}, use_hot_water = #{water}, elect_water = #{consumption} where building_id = #{buildingId} and cur_date = #{curDate}")
void updateByOther(String buildingId, String curDate, BigDecimal electricity, BigDecimal water, BigDecimal consumption);
@Select("select * from energy_day where building_id = #{buildingId} and cur_date >= #{startDate} and cur_date <= #{endDate} order by cur_date desc ")
List<EnergyDay> queryEnergyDay(String buildingId, String startDate, String endDate);
}

22
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyDaySumMapper.java

@ -0,0 +1,22 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyDaySum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyDaySumMapper extends BaseMapper<EnergyDaySum> {
@Select("select * from energy_day_sum where building_id = #{buildingId} and cur_date = #{startDate} ")
List<EnergyDaySum> queryEnergyDaySum(String buildingId, String startDate);
}

27
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyHourMapper.java

@ -0,0 +1,27 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyHour;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.math.BigDecimal;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyHourMapper extends BaseMapper<EnergyHour> {
@Update("update energy_hour set elect_value = #{electricity}, use_hot_water = #{water}, elect_water = #{consumption} where building_id = #{buildingId} and cur_date = #{curDate}")
void updateByOther(String buildingId, String curDate, BigDecimal electricity, BigDecimal water, BigDecimal consumption);
@Select("select * from energy_hour where building_id = #{buildingId} and cur_date >= #{startDate} and cur_date <= #{endDate} order by cur_date desc ")
List<EnergyHour> queryEnergyHour(String buildingId, String startDate, String endDate);
}

28
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyMonthMapper.java

@ -0,0 +1,28 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyMonth;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.poi.ss.formula.functions.T;
import java.math.BigDecimal;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyMonthMapper extends BaseMapper<EnergyMonth> {
@Update("update energy_month set elect_value = #{electricity}, use_hot_water = #{water}, elect_water = #{consumption} where building_id = #{buildingId} and cur_date = #{curDate}")
void updateByOther(String buildingId, String curDate, BigDecimal electricity, BigDecimal water, BigDecimal consumption);
@Select("select * from energy_month where building_id = #{buildingId} and cur_date >= #{startDate} and cur_date <= #{endDate} order by cur_date desc ")
List<EnergyMonth> queryEnergyMonth(String buildingId, String startDate, String endDate);
}

23
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyMonthSumMapper.java

@ -0,0 +1,23 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyMonthSum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyMonthSumMapper extends BaseMapper<EnergyMonthSum> {
@Select("select * from energy_month_sum where building_id = #{buildingId} and cur_date = #{startDate} ")
List<EnergyMonthSum> queryEnergyMonthSum(String buildingId, String startDate);
}

27
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyYearMapper.java

@ -0,0 +1,27 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyYear;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.math.BigDecimal;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyYearMapper extends BaseMapper<EnergyYear> {
@Update("update energy_year set elect_value = #{electricity}, use_hot_water = #{water}, elect_water = #{consumption} where building_id = #{buildingId} and cur_date = #{curDate}")
void updateByOther(String buildingId, String curDate, BigDecimal electricity, BigDecimal water, BigDecimal consumption);
@Select("select * from energy_year where building_id = #{buildingId} and cur_date >= #{startDate} and cur_date <= #{endDate} order by cur_date desc ")
List<EnergyYear> queryEnergyYear(String buildingId, String startDate, String endDate);
}

24
mh-system/src/main/java/com/mh/system/mapper/energy/EnergyYearSumMapper.java

@ -0,0 +1,24 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.EnergyMonthSum;
import com.mh.common.core.domain.entity.EnergyYearSum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水小时
* @date 2025-06-18 15:37:04
*/
@Mapper
public interface EnergyYearSumMapper extends BaseMapper<EnergyYearSum> {
@Select("select * from energy_year_sum where building_id = #{buildingId} and cur_date = #{startDate} ")
List<EnergyYearSum> queryEnergyYearSum(String buildingId, String startDate);
}

125
mh-system/src/main/java/com/mh/system/mapper/energy/HotEnergyQueryMapper.java

@ -0,0 +1,125 @@
package com.mh.system.mapper.energy;
import com.mh.common.core.domain.dto.DataResultDTO;
import com.mh.common.core.domain.entity.DataMonth;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* @author LJF
* @version 1.0
* @project NewZhujiang_Server
* @description 热水能耗查询
* @date 2023-12-13 16:00:01
*/
@Mapper
public interface HotEnergyQueryMapper {
@Select("select " +
" t1.id, t1.floor_name as building_name " +
"from " +
" ( " +
" select " +
" distinct fi.id,fi.floor_name " +
" from " +
" floor_info fi " +
" join " +
"building_info bi " +
"on " +
" fi.building_id = bi.id " +
" join area_info ai on " +
" bi.area_id = ai.id " +
" where " +
" ai.system_type = '1' " +
" ) t1 " +
"join cpm_space_relation csr on " +
" csr.floor_id = t1.id " +
"where " +
" csr.house_id = '' " +
"group by " +
" t1.id,t1.floor_name order by building_name")
List<Map<String, Object>> queryFloorInfo();
@Select("<script>" +
"select " +
" dh.* " +
"from " +
" ${tableName} dh " +
"join ( " +
" select " +
" mt_num " +
" from " +
" collection_params_manage cpm " +
" where " +
" id in( " +
" select " +
" cpm_id " +
" from " +
" cpm_space_relation csr " +
" where " +
" floor_id = #{buildingId} " +
" and house_id = '' " +
")) t1 on " +
" dh.device_num = t1.mt_num " +
"where " +
" date_trunc(#{dateType}, dh.cur_time) = date_trunc(#{dateType},#{lastHour}::timestamp) " +
"order by " +
" cur_time; " +
"</script>")
List<DataMonth> queryEnergyDatas(@Param("tableName") String tableName,
@Param("buildingId") String buildingId,
@Param("lastHour") String lastHourTime,
@Param("dateType") String dateType);
@Select("select count(1) from ${tableName} where building_id = #{buildingId} and cur_date = #{curDate}")
int haveRecord(String tableName, String buildingId, String curDate);
@Select("SELECT pro_energy_sum(#{lastHourTime}); ")
Map<String, Object> calcFloorEnergyDataDetail(@Param("lastHourTime") String lastHourTime);
@Select("<script>" +
"select " +
" fi.id as building_id, " +
" SUBSTRING(fi.floor_name from '(-?\\d+楼)') as building_name, " +
" cpm.other_name as device_name, " +
" dm.* " +
"from " +
" ${tableName} dm " +
"join " +
"collection_params_manage cpm " +
"on " +
" dm.device_num = cpm.mt_num " +
" and dm.device_code = cpm.mt_code " +
"join cpm_space_relation csr on " +
" cpm.id = csr.cpm_id " +
"join floor_info fi on " +
" fi.id = csr.floor_id " +
"where " +
" date(dm.cur_time) >= date(#{startDate}) " +
" and date(dm.cur_time) &lt;= date(#{endDate}) " +
" and cpm.param_type = #{deviceType} " +
" and cpm.grade = 40 " +
" and csr.house_id = '' " +
"<if test='buildingId != null and buildingId != \"所有\" and buildingId != \"\" '>" +
" and csr.floor_id = #{buildingId} " +
"</if>" +
"order by " +
" dm.cur_time desc " +
"</script>")
List<DataResultDTO> queryDeviceDatas(@Param("buildingId") String buildingId,
@Param("startDate") String startDate,
@Param("endDate") String endDate,
@Param("deviceType") String deviceType,
@Param("tableName") String tableName);
@Select("SELECT pro_analysis_month(#{lastHourTime}); ")
Map<String, Object> calcAnalysisDataMonth(String lastHourTime);
@Select("SELECT pro_analysis_year(#{lastHourTime}); ")
Map<String, Object> calcAnalysisDataYear(String lastHourTime);
}

102
mh-system/src/main/java/com/mh/system/mapper/energy/WaterLevelMapper.java

@ -0,0 +1,102 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.WaterLevel;
import org.apache.ibatis.annotations.*;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度记录
* @date 2025-06-19 16:24:31
*/
@Mapper
public interface WaterLevelMapper extends BaseMapper<WaterLevel> {
@Select("select " +
" t1.*, " +
" csr.floor_id " +
"from " +
" ( " +
" select " +
" cpm.id, " +
" cpm.cur_value, " +
" cpm.cur_time, " +
" cpm.mt_num, " +
" dl.device_name " +
" from " +
" collection_params_manage cpm " +
" join device_ledger dl on " +
" cpm.device_ledger_id = dl.id " +
" where " +
" dl.system_type = '1' " +
" and device_type = '16' " +
" and cpm.param_type = '11' " +
" ) t1 " +
"join cpm_space_relation csr on " +
" t1.id = csr.cpm_id " +
"where " +
" csr.house_id = '' " +
"order by " +
" t1.device_name ")
List<Map<String, Object>> getNowWaterLevel();
@Select("select count(1) from water_level where date(cur_date) = date(#{date}::timestamp) and building_id = #{buildingId} and device_num = #{pumpId}")
int isExits(@Param("date") String date,
@Param("buildingId") String buildingId,
@Param("pumpId") String pumpId);
@Insert("insert into water_level(cur_date,building_id,device_num,device_name, ${tempTime}) values(#{date}::timestamp,#{buildingId},#{pumpId},#{pumpName},#{curValue})")
void insertWaterLevel(String date, String buildingId, String pumpId, String pumpName, BigDecimal curValue, String tempTime);
@Update("update water_level set ${tempTime} = #{curValue} where date(cur_date) = date(#{date}::timestamp) and building_id = #{buildingId} and device_num = #{pumpId}")
void updateWaterLevel(String date, String buildingId, String pumpId, String pumpName, BigDecimal curValue, String tempTime);
@Select("select " +
" wt.building_id, " +
" SUBSTRING(fi.floor_name FROM '(-?\\d+楼)') as building_name, " +
" ROUND(avg(temp00::numeric(24, 1)),1) as temp00, " +
" ROUND(avg(temp01::numeric(24, 1)),1) as temp01, " +
" ROUND(avg(temp02::numeric(24, 1)),1) as temp02, " +
" ROUND(avg(temp03::numeric(24, 1)),1) as temp03, " +
" ROUND(avg(temp04::numeric(24, 1)),1) as temp04, " +
" ROUND(avg(temp05::numeric(24, 1)),1) as temp05, " +
" ROUND(avg(temp06::numeric(24, 1)),1) as temp06, " +
" ROUND(avg(temp07::numeric(24, 1)),1) as temp07, " +
" ROUND(avg(temp08::numeric(24, 1)),1) as temp08, " +
" ROUND(avg(temp09::numeric(24, 1)),1) as temp09, " +
" ROUND(avg(temp10::numeric(24, 1)),1) as temp10, " +
" ROUND(avg(temp11::numeric(24, 1)),1) as temp11, " +
" ROUND(avg(temp12::numeric(24, 1)),1) as temp12, " +
" ROUND(avg(temp13::numeric(24, 1)),1) as temp13, " +
" ROUND(avg(temp14::numeric(24, 1)),1) as temp14, " +
" ROUND(avg(temp15::numeric(24, 1)),1) as temp15, " +
" ROUND(avg(temp16::numeric(24, 1)),1) as temp16, " +
" ROUND(avg(temp17::numeric(24, 1)),1) as temp17, " +
" ROUND(avg(temp18::numeric(24, 1)),1) as temp18, " +
" ROUND(avg(temp19::numeric(24, 1)),1) as temp19, " +
" ROUND(avg(temp20::numeric(24, 1)),1) as temp20, " +
" ROUND(avg(temp21::numeric(24, 1)),1) as temp21, " +
" ROUND(avg(temp22::numeric(24, 1)),1) as temp22, " +
" ROUND(avg(temp23::numeric(24, 1)),1) as temp23 " +
"from " +
" water_level wt " +
"join floor_info fi on wt.building_id = fi.id " +
"where " +
" date(wt.cur_date) = date(#{curDate}) " +
"group by " +
" wt.building_id, fi.floor_name " +
"order by SUBSTRING(fi.floor_name FROM '(-?\\d)') ")
List<WaterLevel> queryAvgWaterTemp(String curDate);
@Select("select wt.*, SUBSTRING(fi.floor_name FROM '(-?\\d+楼)') as building_name from water_level wt " +
" join floor_info fi on wt.building_id = fi.id " +
" where wt.building_id = #{buildingId} and date(wt.cur_date) = date(#{curDate}) order by wt.device_name ")
List<WaterLevel> queryWaterTemp(String buildingId, String curDate);
}

103
mh-system/src/main/java/com/mh/system/mapper/energy/WaterTempMapper.java

@ -0,0 +1,103 @@
package com.mh.system.mapper.energy;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.WaterTemp;
import org.apache.ibatis.annotations.*;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度记录
* @date 2025-06-19 16:24:31
*/
@Mapper
public interface WaterTempMapper extends BaseMapper<WaterTemp> {
@Select("select " +
" t1.*, " +
" csr.floor_id, " +
" csr.house_id " +
"from " +
" ( " +
" select " +
" cpm.id, " +
" cpm.cur_value, " +
" cpm.cur_time, " +
" cpm.mt_num, " +
" dl.device_name " +
" from " +
" collection_params_manage cpm " +
" join device_ledger dl on " +
" cpm.device_ledger_id = dl.id " +
" where " +
" dl.system_type = '1' " +
" and dl.device_type = '11' " +
" and cpm.param_type = '12' " +
" ) t1 " +
"join cpm_space_relation csr on " +
" t1.id = csr.cpm_id " +
"where " +
" csr.house_id = '' " +
"order by " +
" t1.device_name ")
List<Map<String, Object>> getNowWaterTemp();
@Select("select count(1) from water_temp where date(cur_date) = date(#{date}::timestamp) and building_id = #{buildingId} and device_num = #{pumpId}")
int isExits(@Param("date") String date,
@Param("buildingId") String buildingId,
@Param("pumpId") String pumpId);
@Insert("insert into water_temp(cur_date,building_id, device_num, device_name, ${tempTime}) values(#{date}::timestamp,#{buildingId},#{pumpId},#{pumpName},#{curValue})")
void insertWaterTemp(String date, String buildingId, String pumpId, String pumpName, BigDecimal curValue, String tempTime);
@Update("update water_temp set ${tempTime} = #{curValue} where date(cur_date) = date(#{date}::timestamp) and building_id = #{buildingId} and device_num = #{pumpId}")
void updateWaterTemp(String date, String buildingId, String pumpId, String pumpName, BigDecimal curValue, String tempTime);
@Select("select " +
" wt.building_id, " +
" SUBSTRING(fi.floor_name FROM '(-?\\d+楼)') as building_name, " +
" ROUND(avg(temp00::numeric(24, 1)),1) as temp00, " +
" ROUND(avg(temp01::numeric(24, 1)),1) as temp01, " +
" ROUND(avg(temp02::numeric(24, 1)),1) as temp02, " +
" ROUND(avg(temp03::numeric(24, 1)),1) as temp03, " +
" ROUND(avg(temp04::numeric(24, 1)),1) as temp04, " +
" ROUND(avg(temp05::numeric(24, 1)),1) as temp05, " +
" ROUND(avg(temp06::numeric(24, 1)),1) as temp06, " +
" ROUND(avg(temp07::numeric(24, 1)),1) as temp07, " +
" ROUND(avg(temp08::numeric(24, 1)),1) as temp08, " +
" ROUND(avg(temp09::numeric(24, 1)),1) as temp09, " +
" ROUND(avg(temp10::numeric(24, 1)),1) as temp10, " +
" ROUND(avg(temp11::numeric(24, 1)),1) as temp11, " +
" ROUND(avg(temp12::numeric(24, 1)),1) as temp12, " +
" ROUND(avg(temp13::numeric(24, 1)),1) as temp13, " +
" ROUND(avg(temp14::numeric(24, 1)),1) as temp14, " +
" ROUND(avg(temp15::numeric(24, 1)),1) as temp15, " +
" ROUND(avg(temp16::numeric(24, 1)),1) as temp16, " +
" ROUND(avg(temp17::numeric(24, 1)),1) as temp17, " +
" ROUND(avg(temp18::numeric(24, 1)),1) as temp18, " +
" ROUND(avg(temp19::numeric(24, 1)),1) as temp19, " +
" ROUND(avg(temp20::numeric(24, 1)),1) as temp20, " +
" ROUND(avg(temp21::numeric(24, 1)),1) as temp21, " +
" ROUND(avg(temp22::numeric(24, 1)),1) as temp22, " +
" ROUND(avg(temp23::numeric(24, 1)),1) as temp23 " +
"from " +
" water_temp wt " +
"join floor_info fi on wt.building_id = fi.id " +
"where " +
" date(wt.cur_date) = date(#{curDate}) " +
"group by " +
" wt.building_id, fi.floor_name " +
"order by SUBSTRING(fi.floor_name FROM '(-?\\d)') ")
List<WaterTemp> queryAvgWaterTemp(String curDate);
@Select("select wt.*, SUBSTRING(fi.floor_name FROM '(-?\\d+楼)') as building_name from water_temp wt " +
" join floor_info fi on wt.building_id = fi.id " +
" where wt.building_id = #{buildingId} and date(wt.cur_date) = date(#{curDate}) order by wt.device_name ")
List<WaterTemp> queryWaterTemp(String buildingId, String curDate);
}

11
mh-system/src/main/java/com/mh/system/mapper/space/CpmSpaceRelationMapper.java

@ -3,6 +3,11 @@ package com.mh.system.mapper.space;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.CpmSpaceRelation; import com.mh.common.core.domain.entity.CpmSpaceRelation;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/** /**
* @author LJF * @author LJF
@ -13,4 +18,10 @@ import org.apache.ibatis.annotations.Mapper;
*/ */
@Mapper @Mapper
public interface CpmSpaceRelationMapper extends BaseMapper<CpmSpaceRelation> { public interface CpmSpaceRelationMapper extends BaseMapper<CpmSpaceRelation> {
@Select("select * from cpm_space_relation where house_id = #{houseId} ")
List<CpmSpaceRelation> selectListByHouseId(@Param("houseId") String houseId);
@Update("update cpm_space_relation set del_flag = #{delFlag} where house_id = #{houseId}")
void updateByHouseId(@Param("houseId") String houseId, @Param("delFlag") String delFlag);
} }

15
mh-system/src/main/java/com/mh/system/service/device/ICollectionParamsManageService.java

@ -10,6 +10,7 @@ import com.mh.common.core.domain.entity.CollectionParamsManage;
import com.mh.common.core.domain.vo.DeviceOperateMonitorVO; import com.mh.common.core.domain.vo.DeviceOperateMonitorVO;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
@ -76,4 +77,18 @@ public interface ICollectionParamsManageService {
* @return * @return
*/ */
List<DeviceMonitorDTO> selectMonitorListBySystemTypeAndHouseId(String systemType, String houseId); List<DeviceMonitorDTO> selectMonitorListBySystemTypeAndHouseId(String systemType, String houseId);
List<CollectionParamsManage> selectListByParams(HashMap<String, Object> queryMap);
void createDtuCollectionParams();
List<CollectionParamsManage> selectSteamBoilerListByParams(String systemType, String type);
List<DeviceMonitorDTO> selectHotWaterBoilerListByParams(String systemType, String type, String mtType);
List<?> selectCollectionParamsManageListByIds(String[] cpmIds);
List<?> selectHeatPumpAlarmListByParams(String systemType, String type, String mtType, String sysParamType);
List<?> selectHeatPumpOnlineByParams(String systemType, String type);
} }

5
mh-system/src/main/java/com/mh/system/service/device/IDeviceLedgerService.java

@ -1,5 +1,6 @@
package com.mh.system.service.device; package com.mh.system.service.device;
import com.mh.common.core.domain.entity.DeviceState;
import com.mh.common.core.domain.entity.DeviceLedger; import com.mh.common.core.domain.entity.DeviceLedger;
import java.util.List; import java.util.List;
@ -23,4 +24,8 @@ public interface IDeviceLedgerService {
int deleteDeviceLedgerByIds(String[] ledgerIds); int deleteDeviceLedgerByIds(String[] ledgerIds);
void updateDeviceLedgerStatus(); void updateDeviceLedgerStatus();
List<DeviceState> deviceState(String systemType);
void createOrUpdateDeviceState();
} }

2
mh-system/src/main/java/com/mh/system/service/device/IGatewayManageService.java

@ -22,4 +22,6 @@ public interface IGatewayManageService {
int updateGateway(GatewayManage gatewayManage); int updateGateway(GatewayManage gatewayManage);
int deleteGatewayByIds(String[] gatewayIds); int deleteGatewayByIds(String[] gatewayIds);
void updateGatewayStatus(String heartBeat);
} }

451
mh-system/src/main/java/com/mh/system/service/device/impl/CollectionParamsManageServiceImpl.java

@ -9,13 +9,16 @@ import com.mh.common.core.domain.dto.PumpInfoDTO;
import com.mh.common.core.domain.entity.ChillersEntity; import com.mh.common.core.domain.entity.ChillersEntity;
import com.mh.common.core.domain.entity.CollectionParamsManage; import com.mh.common.core.domain.entity.CollectionParamsManage;
import com.mh.common.core.domain.entity.DeviceLedger; import com.mh.common.core.domain.entity.DeviceLedger;
import com.mh.common.core.domain.entity.GatewayManage;
import com.mh.common.core.domain.vo.*; import com.mh.common.core.domain.vo.*;
import com.mh.common.core.redis.RedisCache;
import com.mh.common.utils.DateUtils; import com.mh.common.utils.DateUtils;
import com.mh.common.utils.StringUtils; import com.mh.common.utils.StringUtils;
import com.mh.system.mapper.device.CollectionParamsManageMapper; import com.mh.system.mapper.device.CollectionParamsManageMapper;
import com.mh.system.mapper.device.DataProcessMapper; import com.mh.system.mapper.device.DataProcessMapper;
import com.mh.system.mapper.device.DeviceLedgerMapper; import com.mh.system.mapper.device.DeviceLedgerMapper;
import com.mh.system.mapper.device.GatewayManageMapper; import com.mh.system.mapper.device.GatewayManageMapper;
import com.mh.system.mapper.space.FloorInfoMapper;
import com.mh.system.service.device.ICollectionParamsManageService; import com.mh.system.service.device.ICollectionParamsManageService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -27,6 +30,7 @@ import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -52,6 +56,273 @@ public class CollectionParamsManageServiceImpl implements ICollectionParamsManag
@Resource @Resource
private DataProcessMapper dataProcessMapper; private DataProcessMapper dataProcessMapper;
@Resource
private RedisCache redisCache;
@Resource
private FloorInfoMapper floorInfoMapper;
private static final List<String> steamBoilerRunningParams = List.of("DB8296", // 运行时常
"DB611658", // 当前工作状态
"DB611724",// 火焰强度
"DBB611629",// 燃气开关
"DBB611639",// 主阀
"DBB611640",// 副阀
"DBB611634",// 风机电源
"DB611514", // 风机实际速度
"DB611514_1", // 转速百分比
"DB611496", // 烟气温度
"DB611736", // 水位
"DBB611635",// 主水泵
"DBB611637",// 辅助水泵
"DB611500", // 当前压力
"DBW611598",// 设定压力
"DBW611600",// 启动压差
"DBW611602", // 停止压差
"PLC1500_DB8300", // 温度瞬时值
"PLC1500_DB8304", // 压力瞬时值
"PLC1500_DB8308", // 流量瞬时值
"PLC1500_DB8320" //流量累积值
);
private static final List<String> steamBoilerAO = List.of("DB611566", // 锅炉1-工作最小转速
"DB611550",// 锅炉1-工作最大转速
"DB611560",// 锅炉1-风机额定转速
"DB611514",// 锅炉1-风机实际速度
"DB611724",// 锅炉1-火焰强度
"DB611492",// 锅炉1-蒸汽温度
"DB611496", // 锅炉1-烟气温度
"DB611500", // 锅炉1-蒸汽压力
"DB611716", // 锅炉1-PT100-2温度
"DB611596"// 锅炉1-用户温度设定值
);
@Override
public List<?> selectHeatPumpOnlineByParams(String systemType, String type) {
if (StringUtils.isEmpty(systemType)) {
return List.of();
}
// 获取运行情况
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageMapper.selectList(new QueryWrapper<CollectionParamsManage>()
.eq("system_type", systemType).eq("mt_type", "14").eq("param_type", "1"));
// quality为0的参数,就是正常采集
List<CollectionParamsManage> runningParams = collectionParamsManages.stream().filter(collectionParamsManage -> collectionParamsManage.getQuality().equals("0")).toList();
Map<String, Integer> map = new HashMap<>();
map.put("online", runningParams.size());
map.put("total", collectionParamsManages.size());
map.put("offline", collectionParamsManages.size() - runningParams.size());
return List.of(map);
}
@Override
public List<?> selectHeatPumpAlarmListByParams(String systemType, String type, String mtType, String sysParamType) {
if (StringUtils.isEmpty(systemType)) {
return List.of();
}
return collectionParamsManageMapper.selectList(new QueryWrapper<CollectionParamsManage>()
.eq("system_type", systemType)
.eq("mt_type", mtType)
.eq("param_type", sysParamType)
.eq("cur_value", 1)
.orderByDesc("cur_time"));
}
@Override
public List<?> selectCollectionParamsManageListByIds(String[] cpmIds) {
if (cpmIds.length == 0) return List.of();
List<CollectionParamsManage> collectionParamsManages = new ArrayList<>();
for (String cpmId : cpmIds) {
List<CollectionParamsManage> list = collectionParamsManageMapper.selectList(
new QueryWrapper<CollectionParamsManage>()
.eq("device_ledger_id", cpmId));
collectionParamsManages.addAll(list);
}
return processOtherNameFields(collectionParamsManages);
}
@Override
public List<DeviceMonitorDTO> selectHotWaterBoilerListByParams(String systemType, String type, String mtType) {
if (StringUtils.isEmpty(systemType)) {
return List.of();
}
HashMap<String, Object> map = new HashMap<>();
map.put("systemType", systemType);
// 13热水锅炉
map.put("mtType", mtType);
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
// 根据deviceLedgerId查询设备名称进行分组
Map<String, List<CollectionParamsManage>> groupedByDeviceLedgerId = collectionParamsManages.stream()
.collect(Collectors.groupingBy(CollectionParamsManage::getDeviceLedgerId));
// 开始遍历分组
List<DeviceMonitorDTO> result = new ArrayList<>();
for (Map.Entry<String, List<CollectionParamsManage>> entry : groupedByDeviceLedgerId.entrySet()) {
DeviceMonitorDTO deviceMonitorDTO = new DeviceMonitorDTO();
String key = entry.getKey();
// 根据deviceLedgerId查询设备名称
DeviceLedger deviceLedger = deviceLedgerMapper.selectById(key);
deviceMonitorDTO.setName(deviceLedger.getDeviceName());
List<CollectionParamsManage> value = entry.getValue();
// 增加一个排序
value.sort(Comparator.comparingInt(CollectionParamsManage::getOrderNum));
deviceMonitorDTO.setValues(value);
result.add(deviceMonitorDTO);
}
return result.stream().sorted(Comparator.comparing(DeviceMonitorDTO::getName)).toList();
}
@Override
public List<CollectionParamsManage> selectSteamBoilerListByParams(String systemType, String type) {
HashMap<String, Object> map = new HashMap<>();
map.put("systemType", systemType);
// 12蒸汽锅炉
map.put("mtType", "12");
return switch (type) {
case "0" -> {
// 0:代表查询动画界面数据
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
yield collectionParamsManages.stream()
.filter(collectionParamsManage -> steamBoilerRunningParams.contains(collectionParamsManage.getMtNum()))
.toList();
}
case "1" -> {
// 1:代表查询模拟量监测数据
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
List<CollectionParamsManage> list = collectionParamsManages.stream()
.filter(collectionParamsManage -> steamBoilerAO.contains(collectionParamsManage.getMtNum()))
.toList();
yield processOtherNameFields(list);
}
case "2" -> {
// 2:代表查询继电器数据
map.put("otherName", "继电器输出");
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
yield processOtherNameFields(collectionParamsManages);
}
case "3" -> {
// 3:查询端口输入数据
map.put("otherName", "数字量");
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
yield processOtherNameFields(collectionParamsManages);
}
case "4" -> {
// 4:代表查询报警数据
map.put("paramType", "5");
List<CollectionParamsManage> collectionParamsManages = selectListByParams(map);
yield processOtherNameFields(collectionParamsManages);
}
default -> List.of();
};
}
/**
* 处理otherName字段"-"分割并取最后一部分
* @param collectionParamsManages 待处理的集合
* @return 处理后的集合
*/
private List<CollectionParamsManage> processOtherNameFields(List<CollectionParamsManage> collectionParamsManages) {
return collectionParamsManages.stream()
.peek(collectionParamsManage -> {
String otherName = collectionParamsManage.getOtherName();
if (otherName != null && otherName.contains("-")) {
String[] parts = otherName.split("-");
collectionParamsManage.setOtherName(parts[parts.length - 1]);
}
})
.sorted(Comparator.comparing(CollectionParamsManage::getOrderNum))
.toList();
}
@Override
public void createDtuCollectionParams() {
List<CollectionParamsManage> paramsManages = collectionParamsManageMapper.createOrderList();
// 根据网关类型分组
Map<String, List<CollectionParamsManage>> map = paramsManages.stream().collect(Collectors.groupingBy(CollectionParamsManage::getGatewayId));
// 查询全部的网关
List<GatewayManage> gatewayManages = gatewayManageMapper.selectList(new QueryWrapper<GatewayManage>());
if (gatewayManages.isEmpty()) {
return;
}
for (GatewayManage gatewayManage : gatewayManages) {
String gatewayId = gatewayManage.getId();
String heartBeat = gatewayManage.getHeartBeat();
if (map.containsKey(gatewayId)) {
List<CollectionParamsManage> paramsManages1 = map.get(gatewayId);
// 删除缓存数据
if (redisCache.hasKey(heartBeat)) {
redisCache.deleteObject(heartBeat);
}
// List<String> sendOrder = new ArrayList<>();
// for (CollectionParamsManage paramsManage : paramsManages1) {
// // 开始创建指令
// String mtCode = paramsManage.getMtCode(); // 采集编号
// String funCode = paramsManage.getMtCode(); // 功能码
// String registerAddr = paramsManage.getRegisterAddr(); // 寄存器地址
// String registerNum = String.valueOf(paramsManage.getRegisterSize()); // 寄存器数量
// // 拼接指令
// String sendOrderStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.intToHexString(Integer.parseInt(mtCode), true), 2)
// + ExchangeStringUtil.addZeroForNum(funCode, 2)
// + ExchangeStringUtil.addZeroForNum(registerAddr, 4)
// + ExchangeStringUtil.addZeroForNum(registerNum, 4);
// byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(sendOrderStr);
// int checkNum = CRC16.CRC16_MODBUS(strOrder);
// String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
// checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
// sendOrderStr = sendOrderStr + checkWord;
// sendOrder.add(sendOrderStr);
// }
redisCache.setCacheObject(heartBeat, paramsManages1);
redisCache.expire(heartBeat, 30, TimeUnit.MINUTES);
}
}
}
@Override
public List<CollectionParamsManage> selectListByParams(HashMap<String, Object> queryMap) {
if (queryMap == null || queryMap.isEmpty()) {
return List.of();
}
QueryWrapper<CollectionParamsManage> queryWrapper = new QueryWrapper<>();
if (queryMap.containsKey("systemType")) {
String systemType = (String) queryMap.get("systemType");
queryWrapper.eq("system_type", systemType);
}
if (queryMap.containsKey("paramType")) {
String paramType = (String) queryMap.get("paramType");
queryWrapper.eq("param_type", paramType);
}
if (queryMap.containsKey("mtType")) {
String paramType = (String) queryMap.get("mtType");
queryWrapper.eq("mt_type", paramType);
}
if (queryMap.containsKey("curValue")) {
BigDecimal curValue = (BigDecimal) queryMap.get("curValue");
queryWrapper.eq("cur_value", curValue);
}
if (queryMap.containsKey("isUse")) {
int isUse = (int) queryMap.get("isUse");
queryWrapper.eq("is_use", isUse);
}
if (queryMap.containsKey("deviceLedgerId")) {
String deviceLedgerId = (String) queryMap.get("deviceLedgerId");
queryWrapper.eq("device_ledger_id", deviceLedgerId);
}
if (queryMap.containsKey("otherName")) {
String otherName = (String) queryMap.get("otherName");
queryWrapper.like("other_name", otherName);
}
if (queryMap.containsKey("curTime")) {
// 判断时间在今天
Date curTime = (Date) queryMap.get("curTime");
queryWrapper.ge("cur_time", DateUtils.getStartOfDay(curTime));
queryWrapper.le("cur_time", DateUtils.getEndOfDay(curTime));
}
queryWrapper.orderByDesc("order_num");
return collectionParamsManageMapper.selectList(queryWrapper);
}
@Override @Override
public List<CollectionParamsManage> selectCollectionParamsManageList(CollectionParamsManage communicationParams) { public List<CollectionParamsManage> selectCollectionParamsManageList(CollectionParamsManage communicationParams) {
if (communicationParams == null) { if (communicationParams == null) {
@ -336,11 +607,12 @@ public class CollectionParamsManageServiceImpl implements ICollectionParamsManag
@Override @Override
public List<ColumnFilter> monitorPublic(String systemType, String floorId) { public List<ColumnFilter> monitorPublic(String systemType, String floorId) {
List<Map<String, Object>> mapList = collectionParamsManageMapper.selectBySystemTypeAndBuildingId(systemType, floorId); List<Map<String, Object>> mapList = collectionParamsManageMapper.selectBySystemTypeAndBuildingId(systemType, Collections.singletonList(floorId));
// stream流判断mapList中的数据curTime是否为今天日期,假如不是今天日期,则重新赋值value为"采集失败",然后响应赋值给List<ColumnFilter> // stream流判断mapList中的数据curTime是否为今天日期,假如不是今天日期,则重新赋值value为"采集失败",然后响应赋值给List<ColumnFilter>
return mapList.stream() return mapList.stream()
.filter(map -> { .filter(map -> {
String name = map.get("name").toString(); String name = map.get("name").toString();
return !name.contains("热泵"); return !name.contains("热泵");
}) })
.map(map -> { .map(map -> {
@ -418,101 +690,110 @@ public class CollectionParamsManageServiceImpl implements ICollectionParamsManag
// 处理供水泵状态(deviceType=10) // 处理供水泵状态(deviceType=10)
List<DeviceMonitorVO> waterPumps = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "10"); List<DeviceMonitorVO> waterPumps = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "10");
// 判断是否存在collectValue>0的记录 if (!waterPumps.isEmpty()) {
boolean hasValidCollectValue1 = waterPumps.stream() // 判断是否存在collectValue>0的记录
.anyMatch(vo -> "1".equals(vo.getParamType()) boolean hasValidCollectValue1 = waterPumps.stream()
&& vo.getCollectValue() != null .anyMatch(vo -> "1".equals(vo.getParamType())
&& new BigDecimal(vo.getCollectValue()).intValue() > 0 && vo.getCollectValue() != null
&& vo.getCollectName().contains("供水泵1")); && new BigDecimal(vo.getCollectValue()).intValue() > 0
// 根据判断结果设置状态值 && vo.getCollectName().contains("供水泵1"));
result.forEach(dto -> dto.setUpWaterState1(hasValidCollectValue1 ? "1" : "0")); // 根据判断结果设置状态值
// 判断是否存在collectValue>0的记录 result.forEach(dto -> dto.setUpWaterState1(hasValidCollectValue1 ? "1" : "0"));
boolean hasValidCollectValue2 = waterPumps.stream() // 判断是否存在collectValue>0的记录
.anyMatch(vo -> "1".equals(vo.getParamType()) boolean hasValidCollectValue2 = waterPumps.stream()
&& vo.getCollectValue() != null .anyMatch(vo -> "1".equals(vo.getParamType())
&& new BigDecimal(vo.getCollectValue()).intValue() > 0 && vo.getCollectValue() != null
&& vo.getCollectName().contains("供水泵2")); && new BigDecimal(vo.getCollectValue()).intValue() > 0
// 根据判断结果设置状态值 && vo.getCollectName().contains("供水泵2"));
result.forEach(dto -> dto.setUpWaterState2(hasValidCollectValue2 ? "1" : "0")); // 根据判断结果设置状态值
// 频率反馈1 result.forEach(dto -> dto.setUpWaterState2(hasValidCollectValue2 ? "1" : "0"));
DeviceMonitorVO freq1 = waterPumps.stream() // 频率反馈1
.filter(vo -> "4".equals(vo.getParamType()) DeviceMonitorVO freq1 = waterPumps.stream()
&& vo.getCollectValue() != null .filter(vo -> "4".equals(vo.getParamType())
&& vo.getCollectName().contains("供水泵1")) && vo.getCollectValue() != null
.collect(Collectors.toList()).getFirst(); && vo.getCollectName().contains("供水泵1"))
// 根据判断结果设置状态值 .collect(Collectors.toList()).getFirst();
if (StringUtils.isEmpty(freq1.getCollectValue())) { // 根据判断结果设置状态值
freq1.setCollectValue("0"); if (StringUtils.isEmpty(freq1.getCollectValue())) {
} freq1.setCollectValue("0");
result.forEach(dto -> dto.setFreq1(new BigDecimal(freq1.getCollectValue()).setScale(2, RoundingMode.HALF_UP).toString())); }
// 频率反馈2 result.forEach(dto -> dto.setFreq1(new BigDecimal(freq1.getCollectValue()).setScale(2, RoundingMode.HALF_UP).toString()));
DeviceMonitorVO freq2 = waterPumps.stream() // 频率反馈2
.filter(vo -> "4".equals(vo.getParamType()) DeviceMonitorVO freq2 = waterPumps.stream()
&& vo.getCollectValue() != null .filter(vo -> "4".equals(vo.getParamType())
&& vo.getCollectName().contains("供水泵2")) && vo.getCollectValue() != null
.collect(Collectors.toList()).getFirst(); && vo.getCollectName().contains("供水泵2"))
if (StringUtils.isEmpty(freq2.getCollectValue())) { .collect(Collectors.toList()).getFirst();
freq2.setCollectValue("0"); if (StringUtils.isEmpty(freq2.getCollectValue())) {
} freq2.setCollectValue("0");
// 根据判断结果设置状态值 }
result.forEach(dto -> dto.setFreq2(new BigDecimal(freq2.getCollectValue()).setScale(2, RoundingMode.HALF_UP).toString())); // 根据判断结果设置状态值
result.forEach(dto -> dto.setFreq2(new BigDecimal(freq2.getCollectValue()).setScale(2, RoundingMode.HALF_UP).toString()));
}
// 处理水箱,水箱绑定了补水阀参数(deviceType=16) // 处理水箱,水箱绑定了补水阀参数(deviceType=16)
List<DeviceMonitorVO> waterValves = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "16"); List<DeviceMonitorVO> waterValves = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "16");
// 判断是否存在collectValue>0的记录 if (!waterValves.isEmpty()) {
boolean useWaterState = waterValves.stream() // 判断是否存在collectValue>0的记录
.anyMatch(vo -> "2".equals(vo.getParamType()) boolean useWaterState = waterValves.stream()
&& vo.getCollectValue() != null .anyMatch(vo -> "2".equals(vo.getParamType())
&& new BigDecimal(vo.getCollectValue()).intValue() > 0); && vo.getCollectValue() != null
// 根据判断结果设置状态值 && new BigDecimal(vo.getCollectValue()).intValue() > 0);
result.forEach(dto -> dto.setUseWaterState(useWaterState ? "1" : "0")); // 根据判断结果设置状态值
result.forEach(dto -> dto.setUseWaterState(useWaterState ? "1" : "0"));
}
// 处理回水阀(deviceType=22) // 处理回水阀(deviceType=22)
List<DeviceMonitorVO> waterBackValves = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "22"); List<DeviceMonitorVO> waterBackValves = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "22");
// 判断是否存在collectValue>0的记录 if (!waterBackValves.isEmpty()) {
boolean backWaterState = waterBackValves.stream() // 判断是否存在collectValue>0的记录
.anyMatch(vo -> "2".equals(vo.getParamType()) boolean backWaterState = waterBackValves.stream()
&& vo.getCollectValue() != null .anyMatch(vo -> "2".equals(vo.getParamType())
&& new BigDecimal(vo.getCollectValue()).intValue() > 0); && vo.getCollectValue() != null
// 根据判断结果设置状态值 && new BigDecimal(vo.getCollectValue()).intValue() > 0);
result.forEach(dto -> dto.setBackWaterState(backWaterState ? "1" : "0")); // 根据判断结果设置状态值
result.forEach(dto -> dto.setBackWaterState(backWaterState ? "1" : "0"));
}
// 处理水箱液位(deviceType=16) // 处理水箱液位(deviceType=16)
List<DeviceMonitorVO> waterLevels = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "16"); List<DeviceMonitorVO> waterLevels = collectionParamsManageMapper.selectHotWaterBySystemTypeAndBuildingIdAndDeviceType(systemType, floorId, "16");
if (!waterLevels.isEmpty()) {
// 计算levelSet平均值(paramType=10)
Double levelSetAvg = waterLevels.stream()
.filter(vo -> vo.getParamType().equals("10"))
.mapToDouble(vo -> {
try {
return Double.parseDouble(vo.getCollectValue());
} catch (NumberFormatException e) {
log.error("数值转换失败:设备ID={} 值={}", vo.getId(), vo.getCollectValue());
return 0.0; // 返回默认值
}
})
.average()
.orElse(0.0);
// 计算waterLevel平均值(paramType=11)
Double waterLevelAvg = waterLevels.stream()
.filter(vo -> vo.getParamType().equals("11"))
.mapToDouble(vo -> {
try {
return Double.parseDouble(vo.getCollectValue());
} catch (NumberFormatException e) {
log.error("数值转换失败:设备ID={} 值={}", vo.getId(), vo.getCollectValue());
return 0.0; // 返回默认值
}
})
.average()
.orElse(0.0);
// 计算levelSet平均值(paramType=10) // 设置平均值到所有DTO(根据业务需求调整)
Double levelSetAvg = waterLevels.stream() result.forEach(dto -> {
.filter(vo -> vo.getParamType().equals("10")) dto.setLevelSet(String.format("%.2f", levelSetAvg));
.mapToDouble(vo -> { dto.setWaterLevel(String.format("%.2f", waterLevelAvg));
try { });
return Double.parseDouble(vo.getCollectValue()); }
} catch (NumberFormatException e) {
log.error("数值转换失败:设备ID={} 值={}", vo.getId(), vo.getCollectValue());
return 0.0; // 返回默认值
}
})
.average()
.orElse(0.0);
// 计算waterLevel平均值(paramType=11)
Double waterLevelAvg = waterLevels.stream()
.filter(vo -> vo.getParamType().equals("11"))
.mapToDouble(vo -> {
try {
return Double.parseDouble(vo.getCollectValue());
} catch (NumberFormatException e) {
log.error("数值转换失败:设备ID={} 值={}", vo.getId(), vo.getCollectValue());
return 0.0; // 返回默认值
}
})
.average()
.orElse(0.0);
// 设置平均值到所有DTO(根据业务需求调整)
result.forEach(dto -> {
dto.setLevelSet(String.format("%.2f", levelSetAvg));
dto.setWaterLevel(String.format("%.2f", waterLevelAvg));
});
// result再根据orderNum排序 // result再根据orderNum排序
return result.stream() return result.stream()
.sorted(Comparator.comparingInt(HotWaterNowDataDTO::getOrderNum)) .sorted(Comparator.comparingInt(HotWaterNowDataDTO::getOrderNum))

20
mh-system/src/main/java/com/mh/system/service/device/impl/DeviceLedgerServiceImpl.java

@ -1,11 +1,12 @@
package com.mh.system.service.device.impl; package com.mh.system.service.device.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mh.common.core.domain.entity.CollectionParamsManage; import com.mh.common.core.domain.entity.DeviceState;
import com.mh.common.core.domain.entity.DeviceLedger; import com.mh.common.core.domain.entity.DeviceLedger;
import com.mh.common.utils.StringUtils; import com.mh.common.utils.StringUtils;
import com.mh.system.mapper.device.CollectionParamsManageMapper; import com.mh.system.mapper.device.CollectionParamsManageMapper;
import com.mh.system.mapper.device.DeviceLedgerMapper; import com.mh.system.mapper.device.DeviceLedgerMapper;
import com.mh.system.mapper.device.DeviceStateMapper;
import com.mh.system.service.device.IDeviceLedgerService; import com.mh.system.service.device.IDeviceLedgerService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -27,9 +28,26 @@ public class DeviceLedgerServiceImpl implements IDeviceLedgerService {
@Resource @Resource
private DeviceLedgerMapper deviceLedgerMapper; private DeviceLedgerMapper deviceLedgerMapper;
@Resource
private DeviceStateMapper deviceStateMapper;
@Resource @Resource
private CollectionParamsManageMapper collectionParamsManageMapper; private CollectionParamsManageMapper collectionParamsManageMapper;
@Override
public List<DeviceState> deviceState(String systemType) {
if (StringUtils.isEmpty(systemType)) {
return List.of();
}
return deviceStateMapper.deviceState(systemType);
}
@Override
public void createOrUpdateDeviceState() {
String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
deviceLedgerMapper.createOrUpdateDeviceState(currentDate);
}
@Override @Override
public void updateDeviceLedgerStatus() { public void updateDeviceLedgerStatus() {
// 先从采集点为中查询,看看当天是否有数据上来 // 先从采集点为中查询,看看当天是否有数据上来

5
mh-system/src/main/java/com/mh/system/service/device/impl/GatewayManageServiceImpl.java

@ -23,6 +23,11 @@ public class GatewayManageServiceImpl implements IGatewayManageService {
@Resource @Resource
private GatewayManageMapper gatewayManageMapper; private GatewayManageMapper gatewayManageMapper;
@Override
public void updateGatewayStatus(String heartBeat) {
gatewayManageMapper.updateOnlineStatusByHeartBeat(heartBeat);
}
@Override @Override
public List<GatewayManage> selectGwManageList(GatewayManage gatewayManage) { public List<GatewayManage> selectGwManageList(GatewayManage gatewayManage) {
QueryWrapper<GatewayManage> queryWrapper = new QueryWrapper<>(); QueryWrapper<GatewayManage> queryWrapper = new QueryWrapper<>();

33
mh-system/src/main/java/com/mh/system/service/energy/IEnergyQueryService.java

@ -1,7 +1,14 @@
package com.mh.system.service.energy; package com.mh.system.service.energy;
import com.mh.common.core.domain.AjaxResult; import com.mh.common.core.domain.AjaxResult;
import com.mh.common.core.domain.entity.DataMonth;
import com.mh.common.core.domain.entity.WaterLevel;
import com.mh.common.core.domain.entity.WaterTemp;
import com.mh.common.core.domain.vo.EnergyQueryVO; import com.mh.common.core.domain.vo.EnergyQueryVO;
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
import java.util.Map;
/** /**
* @author LJF * @author LJF
@ -20,4 +27,30 @@ public interface IEnergyQueryService {
AjaxResult sysQuery(EnergyQueryVO page); AjaxResult sysQuery(EnergyQueryVO page);
AjaxResult deviceTypeQuery(EnergyQueryVO page); AjaxResult deviceTypeQuery(EnergyQueryVO page);
List<Map<String, Object>> queryFloorInfo();
List<DataMonth> queryEnergyDatas(String tableName, String buildingId, String lastHourTime, String dateType);
int haveRecord(String buildingId, String lastHourTime, String dateType);
void insertOrUpdateEnergyData(String hour, String buildingId, String buildingName, String lastHourTime, double totalElectricity, double totalWater, double specificConsumption);
List<?> queryEnergyDataList(String buildingId, String startDate, String endDate, int type);
List<?> queryEnergyDataSumList(String buildingId, String curDate, Integer type);
void calcFloorEnergyDataDetail(String lastHourTime);
List<WaterTemp> queryWaterTemp(String buildingId, String curDate);
List<WaterLevel> queryWaterLevel(String buildingId, String curDate);
List<?> queryDeviceDatas(String buildingId, String startDate, String endDate, String deviceType);
List<?> queryAnalysisYear(String curDate, String buildingId, int type);
List<?> queryAnalysisMonth(String curDate, String buildingId, int type);
void calcAnalysisData(String lastHourTime);
} }

14
mh-system/src/main/java/com/mh/system/service/energy/IWaterLevelService.java

@ -0,0 +1,14 @@
package com.mh.system.service.energy;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度服务类
* @date 2025-06-19 16:26:10
*/
public interface IWaterLevelService {
void calcWaterLevel();
}

14
mh-system/src/main/java/com/mh/system/service/energy/IWaterTempService.java

@ -0,0 +1,14 @@
package com.mh.system.service.energy;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度服务类
* @date 2025-06-19 16:26:10
*/
public interface IWaterTempService {
void calcWaterTemp();
}

3
mh-system/src/main/java/com/mh/system/service/energy/impl/EnergyAnalyzeServiceImpl.java

@ -245,6 +245,7 @@ public class EnergyAnalyzeServiceImpl implements EnergyAnalyzeService {
map.put("timeStr", timeStr.subList(startIndex, endIndex)); map.put("timeStr", timeStr.subList(startIndex, endIndex));
map.put("dataList", columnData); map.put("dataList", columnData);
} }
map.put("total", timeStr.size());
return new ArrayList<>(map.entrySet()); return new ArrayList<>(map.entrySet());
} }
@ -267,7 +268,7 @@ public class EnergyAnalyzeServiceImpl implements EnergyAnalyzeService {
.sorted(Comparator.comparing(DeviceTypeEnergy::getGrade)) .sorted(Comparator.comparing(DeviceTypeEnergy::getGrade))
.map(val -> { .map(val -> {
ColumnFilter data = new ColumnFilter(); ColumnFilter data = new ColumnFilter();
data.setName(val.getRemark()); data.setName(val.getRemark().replace("累计读数", ""));
BigDecimal calcValue = new BigDecimal(val.getCalcValue()).setScale(2, RoundingMode.HALF_UP); BigDecimal calcValue = new BigDecimal(val.getCalcValue()).setScale(2, RoundingMode.HALF_UP);
data.setValue(String.valueOf(calcValue)); data.setValue(String.valueOf(calcValue));
return data; return data;

275
mh-system/src/main/java/com/mh/system/service/energy/impl/EnergyQueryServiceImpl.java

@ -1,16 +1,18 @@
package com.mh.system.service.energy.impl; package com.mh.system.service.energy.impl;
import com.mh.common.core.domain.AjaxResult; import com.mh.common.core.domain.AjaxResult;
import com.mh.common.core.domain.entity.ConsumptionAnalyze; import com.mh.common.core.domain.entity.*;
import com.mh.common.core.domain.vo.EnergyQueryVO; import com.mh.common.core.domain.vo.EnergyQueryVO;
import com.mh.common.utils.DateUtils; import com.mh.common.utils.DateUtils;
import com.mh.common.utils.StringUtils;
import com.mh.system.mapper.device.CollectionParamsManageMapper; import com.mh.system.mapper.device.CollectionParamsManageMapper;
import com.mh.system.mapper.energy.EnergyQueryMapper; import com.mh.system.mapper.energy.*;
import com.mh.system.service.energy.IEnergyQueryService; import com.mh.system.service.energy.IEnergyQueryService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -29,9 +31,147 @@ public class EnergyQueryServiceImpl implements IEnergyQueryService {
@Resource @Resource
private EnergyQueryMapper energyQueryMapper; private EnergyQueryMapper energyQueryMapper;
@Resource
private HotEnergyQueryMapper hotEnergyQueryMapper;
@Resource @Resource
private CollectionParamsManageMapper collectionParamsManageMapper; private CollectionParamsManageMapper collectionParamsManageMapper;
@Resource
private EnergyHourMapper energyHourMapper;
@Resource
private EnergyDayMapper energyDayMapper;
@Resource
private EnergyMonthMapper energyMonthMapper;
@Resource
private EnergyYearMapper energyYearMapper;
@Resource
private EnergyDaySumMapper energyDaySumMapper;
@Resource
private EnergyMonthSumMapper energyMonthSumMapper;
@Resource
private EnergyYearSumMapper energyYearSumMapper;
@Resource
private WaterTempMapper waterTempMapper;
@Resource
private WaterLevelMapper waterLevelMapper;
@Resource
AnalysisMapper analysisMapper;
@Override
public void calcAnalysisData(String lastHourTime) {
try {
// 月数据分析
hotEnergyQueryMapper.calcAnalysisDataMonth(lastHourTime);
} catch (Exception e) {
throw new RuntimeException(e);
}
// 年数据分析
hotEnergyQueryMapper.calcAnalysisDataYear(lastHourTime);
}
@Override
public List<?> queryAnalysisYear(String curDate, String buildingId, int type) {
if (type==1){
return analysisMapper.queryAnalysisWaterYear(curDate,buildingId);
}else if (type==2){
return analysisMapper.queryAnalysisElectYear(curDate,buildingId);
}else if(type==3){
return analysisMapper.queryAnalysisEnergyYear(curDate,buildingId);
}else if (type==4){
return analysisMapper.queryAnalysisMaintainYear(curDate,buildingId);
} else {
return analysisMapper.queryAnalysisRuntimeYear(curDate,buildingId);
}
}
@Override
public List<?> queryAnalysisMonth(String curDate, String buildingId, int type) {
if (type==1){
return analysisMapper.queryAnalysisWaterMonth(curDate,buildingId);
}else if (type==2){
return analysisMapper.queryAnalysisElectMonth(curDate,buildingId);
}else if (type==3){
return analysisMapper.queryAnalysisEnergyMonth(curDate,buildingId);
}else if (type==4){
return analysisMapper.queryAnalysisMaintainMonth(curDate,buildingId);
} else {
return analysisMapper.queryAnalysisRuntimeMonth(curDate,buildingId);
}
}
@Override
public List<?> queryDeviceDatas(String buildingId, String startDate, String endDate, String deviceType) {
if (StringUtils.isEmpty(buildingId)) {
return List.of();
}
String tableName = "data_min" + startDate.substring(0, 4);
return hotEnergyQueryMapper.queryDeviceDatas(buildingId, startDate, endDate, deviceType, tableName);
}
@Override
public List<WaterLevel> queryWaterLevel(String buildingId, String curDate) {
if (StringUtils.isEmpty(buildingId) || buildingId.equals("所有")) {
// 返回所有楼栋的平均值
return waterLevelMapper.queryAvgWaterTemp(curDate);
}
return waterLevelMapper.queryWaterTemp(buildingId, curDate);
}
@Override
public List<WaterTemp> queryWaterTemp(String buildingId, String curDate) {
if (StringUtils.isEmpty(buildingId) || buildingId.equals("所有")) {
// 返回所有楼栋的平均值
return waterTempMapper.queryAvgWaterTemp(curDate);
}
return waterTempMapper.queryWaterTemp(buildingId, curDate);
}
@Override
public void calcFloorEnergyDataDetail(String lastHourTime) {
hotEnergyQueryMapper.calcFloorEnergyDataDetail(lastHourTime);
}
@Override
public List<?> queryEnergyDataSumList(String buildingId, String curDate, Integer type) {
if (StringUtils.isEmpty(buildingId)) {
return List.of();
}
if (type==1){
return energyDaySumMapper.queryEnergyDaySum(buildingId,curDate); //日
}else if (type==2){
return energyMonthSumMapper.queryEnergyMonthSum(buildingId,curDate); //月
}else {
return energyYearSumMapper.queryEnergyYearSum(buildingId,curDate); //年
}
}
@Override
public List<?> queryEnergyDataList(String buildingId, String startDate, String endDate, int type) {
if (StringUtils.isEmpty(buildingId)) {
return List.of();
}
if (type == 0) {
return energyHourMapper.queryEnergyHour(buildingId,startDate + " 00",endDate + " 23");
} else if(type==1) {
return energyDayMapper.queryEnergyDay(buildingId,startDate,endDate);
} else if (type==2){
return energyMonthMapper.queryEnergyMonth(buildingId,startDate,endDate);
} else if (type==3){
return energyYearMapper.queryEnergyYear(buildingId,startDate,endDate);
}
return null;
}
@Override @Override
public AjaxResult sysQuery(EnergyQueryVO vo) { public AjaxResult sysQuery(EnergyQueryVO vo) {
DateUtils.sysEnergyDateChange(vo); DateUtils.sysEnergyDateChange(vo);
@ -92,10 +232,10 @@ public class EnergyQueryServiceImpl implements IEnergyQueryService {
try { try {
double cold = Math.round(Double.parseDouble(coldArr[i]) * 100) / 100.0; double cold = Math.round(Double.parseDouble(coldArr[i]) * 100) / 100.0;
double meter = Math.round(Double.parseDouble(meterArr[i]) * 100) / 100.0; double meter = Math.round(Double.parseDouble(meterArr[i]) * 100) / 100.0;
double cop = Math.round((meter==0 ? 0.00 : cold/ meter) * 100) / 100.0; double cop = Math.round((meter == 0 ? 0.00 : cold / meter) * 100) / 100.0;
copArr[i] = String.valueOf(cop); copArr[i] = String.valueOf(cop);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
log.error("处理累计能耗异常==>",e); log.error("处理累计能耗异常==>", e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -109,16 +249,17 @@ public class EnergyQueryServiceImpl implements IEnergyQueryService {
map.put("copArr", copArr); map.put("copArr", copArr);
map.put("timeStrArr", timeStrArr); map.put("timeStrArr", timeStrArr);
} else { } else {
int startIndex = (pageNum-1)*pageSize; int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(pageNum * pageSize, coldArr.length); int endIndex = Math.min(pageNum * pageSize, coldArr.length);
if (startIndex > endIndex) { if (startIndex > endIndex) {
return AjaxResult.success(); return AjaxResult.success();
} }
map.put("coldArr", Arrays.copyOfRange(coldArr, startIndex , endIndex)); map.put("coldArr", Arrays.copyOfRange(coldArr, startIndex, endIndex));
map.put("meterArr", Arrays.copyOfRange(meterArr, startIndex , endIndex)); map.put("meterArr", Arrays.copyOfRange(meterArr, startIndex, endIndex));
map.put("copArr", Arrays.copyOfRange(copArr, startIndex , endIndex)); map.put("copArr", Arrays.copyOfRange(copArr, startIndex, endIndex));
map.put("timeStrArr", Arrays.copyOfRange(timeStrArr, startIndex , endIndex)); map.put("timeStrArr", Arrays.copyOfRange(timeStrArr, startIndex, endIndex));
} }
map.put("total", timeStrArr.length);
// 组装赋值 // 组装赋值
List<Map<String, Object>> listData = new ArrayList<>(); List<Map<String, Object>> listData = new ArrayList<>();
@ -138,6 +279,9 @@ public class EnergyQueryServiceImpl implements IEnergyQueryService {
Map<String, Object> timeStr = new HashMap<>(); Map<String, Object> timeStr = new HashMap<>();
timeStr.put("timeStrArr", map.get("timeStrArr")); timeStr.put("timeStrArr", map.get("timeStrArr"));
listData.add(timeStr); listData.add(timeStr);
Map<String, Object> total = new HashMap<>();
total.put("total", map.get("total"));
listData.add(total);
return AjaxResult.success(listData); return AjaxResult.success(listData);
} }
@ -159,4 +303,117 @@ public class EnergyQueryServiceImpl implements IEnergyQueryService {
public AjaxResult deviceTypeQuery(EnergyQueryVO page) { public AjaxResult deviceTypeQuery(EnergyQueryVO page) {
return null; return null;
} }
@Override
public List<Map<String, Object>> queryFloorInfo() {
return hotEnergyQueryMapper.queryFloorInfo();
}
@Override
public List<DataMonth> queryEnergyDatas(String tableName, String buildingId, String lastHourTime, String dateType) {
return hotEnergyQueryMapper.queryEnergyDatas(tableName, buildingId, lastHourTime, dateType);
}
@Override
public int haveRecord(String buildingId, String lastHourTime, String dateType) {
String tableName = "energy_hour";
switch (dateType) {
case "hour":
tableName = "energy_hour";
break;
case "day":
tableName = "energy_day";
break;
case "month":
tableName = "energy_month";
break;
case "year":
tableName = "energy_year";
break;
default:
break;
}
return hotEnergyQueryMapper.haveRecord(tableName, buildingId, lastHourTime);
}
@Override
public void insertOrUpdateEnergyData(String dateType, String buildingId, String buildingName, String curDate,
double totalElectricity, double totalWater, double specificConsumption) {
// 统一转换为 BigDecimal
BigDecimal electricity = BigDecimal.valueOf(totalElectricity);
BigDecimal water = BigDecimal.valueOf(totalWater);
BigDecimal consumption = BigDecimal.valueOf(specificConsumption);
int count = 0;
switch (dateType) {
case "hour":
curDate = curDate.substring(0, 13);
count = haveRecord(buildingId, curDate, dateType);
if (count > 0) {
energyHourMapper.updateByOther(buildingId, curDate, electricity, water, consumption);
} else {
EnergyHour energyHour = new EnergyHour();
energyHour.setCurDate(curDate);
energyHour.setBuildingId(buildingId);
energyHour.setBuildingName(buildingName);
energyHour.setUseHotWater(water);
energyHour.setElectValue(electricity);
energyHour.setElectWater(consumption);
energyHourMapper.insert(energyHour);
}
break;
case "day":
curDate = curDate.substring(0, 10);
count = haveRecord(buildingId, curDate, dateType);
if (count > 0) {
energyDayMapper.updateByOther(buildingId, curDate, electricity, water, consumption);
} else {
EnergyDay energyDay = new EnergyDay();
energyDay.setCurDate(curDate);
energyDay.setBuildingId(buildingId);
energyDay.setBuildingName(buildingName);
energyDay.setUseHotWater(water);
energyDay.setElectValue(electricity);
energyDay.setElectWater(consumption);
energyDayMapper.insert(energyDay);
}
break;
case "month":
curDate = curDate.substring(0, 7);
count = haveRecord(buildingId, curDate, dateType);
if (count > 0) {
energyMonthMapper.updateByOther(buildingId, curDate, electricity, water, consumption);
} else {
EnergyMonth energyMonth = new EnergyMonth();
energyMonth.setCurDate(curDate);
energyMonth.setBuildingId(buildingId);
energyMonth.setBuildingName(buildingName);
energyMonth.setUseHotWater(water);
energyMonth.setElectValue(electricity);
energyMonth.setElectWater(consumption);
energyMonthMapper.insert(energyMonth);
}
break;
case "year":
curDate = curDate.substring(0, 4);
count = haveRecord(buildingId, curDate, dateType);
if (count > 0) {
energyYearMapper.updateByOther(buildingId, curDate, electricity, water, consumption);
} else {
EnergyYear energyYear = new EnergyYear();
energyYear.setCurDate(curDate);
energyYear.setBuildingId(buildingId);
energyYear.setBuildingName(buildingName);
energyYear.setUseHotWater(water);
energyYear.setElectValue(electricity);
energyYear.setElectWater(consumption);
energyYearMapper.insert(energyYear);
}
break;
default:
log.warn("未知的时间类型: {}", dateType);
}
}
} }

60
mh-system/src/main/java/com/mh/system/service/energy/impl/WaterLevelServiceImpl.java

@ -0,0 +1,60 @@
package com.mh.system.service.energy.impl;
import com.mh.system.mapper.energy.WaterLevelMapper;
import com.mh.system.mapper.energy.WaterTempMapper;
import com.mh.system.service.energy.IWaterLevelService;
import com.mh.system.service.energy.IWaterTempService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度服务类实现类
* @date 2025-06-19 16:26:36
*/
@Service
public class WaterLevelServiceImpl implements IWaterLevelService {
@Resource
private WaterLevelMapper waterLevelMapper;
@Override
public void calcWaterLevel() {
// todo 1、获取到多少个水箱,以及水位对应的实时水位
// todo 2、根据对应的水箱id查询水箱对应的液位
// todo 3、再根据绑定关系表查询到热泵对应的楼层id
List<Map<String, Object>> list = waterLevelMapper.getNowWaterLevel();
// 开始遍历数据
for (Map<String, Object> map : list) {
// todo 5、拼接sql语句,插入到存储表中(id,楼栋id,水箱id,水箱名称,temp00至temp23)
String cpmId = map.get("id").toString();
BigDecimal curValue = new BigDecimal(map.get("cur_value").toString()).setScale(1, BigDecimal.ROUND_HALF_UP);
String buildingId = map.get("floor_id").toString();
String pumpId = map.get("mt_num").toString();
String pumpName = map.get("device_name").toString();
String curDate = map.get("cur_time").toString();
String tempTime = "temp" + curDate.substring(11, 13);
// 格式化时间
String date = curDate.substring(0,10) + " 00:00:00";
// 判断是否存在值
int count = waterLevelMapper.isExits(date, buildingId, pumpId);
if (count == 0) {
// todo 6、插入数据
waterLevelMapper.insertWaterLevel(date, buildingId, pumpId, pumpName, curValue, tempTime);
} else {
// todo 7、更新数据
waterLevelMapper.updateWaterLevel(date, buildingId, pumpId, pumpName, curValue, tempTime);
}
}
}
}

60
mh-system/src/main/java/com/mh/system/service/energy/impl/WaterTempServiceImpl.java

@ -0,0 +1,60 @@
package com.mh.system.service.energy.impl;
import com.mh.common.utils.DateUtils;
import com.mh.system.mapper.energy.WaterTempMapper;
import com.mh.system.service.energy.IWaterTempService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author LJF
* @version 1.0
* @project EEMCS
* @description 热水温度服务类实现类
* @date 2025-06-19 16:26:36
*/
@Service
public class WaterTempServiceImpl implements IWaterTempService {
@Resource
private WaterTempMapper waterTempMapper;
@Override
public void calcWaterTemp() {
// todo 1、获取到多少个热泵,以及热泵对应的实时温度
// todo 2、根据热泵id查询热泵对应的实时温度
// todo 3、再根据绑定关系表查询到热泵对应的楼层id
List<Map<String, Object>> list = waterTempMapper.getNowWaterTemp();
// 开始遍历数据
for (Map<String, Object> map : list) {
// todo 5、拼接sql语句,插入到存储表中(id,楼栋id,热泵采集id,热泵名称,temp00至temp23)
String cpmId = map.get("id").toString();
BigDecimal curValue = new BigDecimal(map.get("cur_value").toString()).setScale(1, BigDecimal.ROUND_HALF_UP);
String buildingId = map.get("floor_id").toString();
String pumpId = map.get("mt_num").toString();
String pumpName = map.get("device_name").toString();
String curDate = map.get("cur_time").toString();
String tempTime = "temp" + curDate.substring(11, 13);
// 格式化时间
String date = curDate.substring(0,10) + " 00:00:00";
// 判断是否存在值
int count = waterTempMapper.isExits(date, buildingId, pumpId);
if (count == 0) {
// todo 6、插入数据
waterTempMapper.insertWaterTemp(date, buildingId, pumpId, pumpName, curValue, tempTime);
} else {
// todo 7、更新数据
waterTempMapper.updateWaterTemp(date, buildingId, pumpId, pumpName, curValue, tempTime);
}
}
}
}

2
mh-system/src/main/java/com/mh/system/service/operation/IOperationDeviceService.java

@ -16,4 +16,6 @@ public interface IOperationDeviceService {
String operationDevice(List<OrderEntity> changeValues); String operationDevice(List<OrderEntity> changeValues);
boolean isAdvanTech(List<OrderEntity> changeValues);
} }

17
mh-system/src/main/java/com/mh/system/service/operation/impl/OperationDeviceServiceImpl.java

@ -37,6 +37,23 @@ public class OperationDeviceServiceImpl implements IOperationDeviceService {
@Resource @Resource
private PolicyManageMapper policyManageMapper; private PolicyManageMapper policyManageMapper;
@Override
public boolean isAdvanTech(List<OrderEntity> changeValues) {
// 判断是否存在非研华网关设备
if (!changeValues.isEmpty()) {
for (OrderEntity changeValue : changeValues) {
String cpmId = changeValue.getId();
CollectionParamsManage collectionParamsManage = collectionParamsManageMapper.selectById(cpmId);
if (null != collectionParamsManage) {
if (!collectionParamsManage.getGatewayId().contains("99")) {
return true;
}
}
}
}
return false;
}
@Override @Override
public String operationDevice(List<OrderEntity> changeValues) { public String operationDevice(List<OrderEntity> changeValues) {
// 拼接发送的报文 // 拼接发送的报文

2
mh-system/src/main/java/com/mh/system/service/space/IHouseInfoService.java

@ -26,4 +26,6 @@ public interface IHouseInfoService {
List<SpaceTreeSelect> buildTree(String systemType); List<SpaceTreeSelect> buildTree(String systemType);
List<SpaceTreeSelect> buildFloorTree(String systemType);
} }

299
mh-system/src/main/java/com/mh/system/service/space/impl/HouseInfoServiceImpl.java

@ -6,18 +6,14 @@ import com.mh.common.core.domain.TreeSelect;
import com.mh.common.core.domain.entity.*; import com.mh.common.core.domain.entity.*;
import com.mh.common.utils.StringUtils; import com.mh.common.utils.StringUtils;
import com.mh.system.mapper.SysParamsMapper; import com.mh.system.mapper.SysParamsMapper;
import com.mh.system.mapper.space.AreaInfoMapper; import com.mh.system.mapper.device.CollectionParamsManageMapper;
import com.mh.system.mapper.space.BuildingInfoMapper; import com.mh.system.mapper.space.*;
import com.mh.system.mapper.space.FloorInfoMapper;
import com.mh.system.mapper.space.HouseInfoMapper;
import com.mh.system.service.space.IHouseInfoService; import com.mh.system.service.space.IHouseInfoService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -45,6 +41,12 @@ public class HouseInfoServiceImpl implements IHouseInfoService {
@Resource @Resource
private SysParamsMapper sysParamsMapper; private SysParamsMapper sysParamsMapper;
@Resource
private CpmSpaceRelationMapper cpmSpaceRelationMapper;
@Resource
private CollectionParamsManageMapper collectionParamsManageMapper;
@Override @Override
public List<HouseInfo> selectHouseInfoList(HouseInfo houseInfo) { public List<HouseInfo> selectHouseInfoList(HouseInfo houseInfo) {
if (houseInfo == null) { if (houseInfo == null) {
@ -72,18 +74,82 @@ public class HouseInfoServiceImpl implements IHouseInfoService {
queryWrapper.like("remark", houseInfo.getRemark()); queryWrapper.like("remark", houseInfo.getRemark());
} }
queryWrapper.orderByAsc("order_num"); queryWrapper.orderByAsc("order_num");
return houseInfoMapper.selectList(queryWrapper); List<HouseInfo> houseInfos = houseInfoMapper.selectList(queryWrapper);
for (HouseInfo val : houseInfos) {
// 根据houseId查询对应的cpmId关联
List<String> cpmIds = new ArrayList<>();
List<String> ledgerIds = new ArrayList<>();
List<String> finalLedgerIds = ledgerIds;
cpmSpaceRelationMapper.selectList(new QueryWrapper<CpmSpaceRelation>().eq("house_id", val.getId())).forEach(cpmSpaceRelation -> {
if (StringUtils.isNotEmpty(cpmSpaceRelation.getDelFlag()) && cpmSpaceRelation.getDelFlag().equals("0")) {
cpmIds.add(cpmSpaceRelation.getCpmId());
if (StringUtils.isNotEmpty(cpmSpaceRelation.getLedgerId())) {
finalLedgerIds.add(cpmSpaceRelation.getLedgerId());
}
}
});
val.setCpmId(cpmIds);
// ledgerIds去掉重复值
ledgerIds = finalLedgerIds.stream().distinct().collect(Collectors.toList());
val.setLedgerId(ledgerIds);
}
return houseInfos;
} }
@Override @Override
public HouseInfo selectHouseInfoById(String buildingId) { public HouseInfo selectHouseInfoById(String buildingId) {
return houseInfoMapper.selectById(buildingId); HouseInfo houseInfo = houseInfoMapper.selectById(buildingId);
// 根据houseId查询对应的cpmId关联
List<String> cpmIds = new ArrayList<>();
List<String> ledgerIds = new ArrayList<>();
List<String> finalLedgerIds = ledgerIds;
cpmSpaceRelationMapper.selectList(new QueryWrapper<CpmSpaceRelation>().eq("house_id", houseInfo.getId())).forEach(cpmSpaceRelation -> {
if (StringUtils.isNotEmpty(cpmSpaceRelation.getDelFlag()) && cpmSpaceRelation.getDelFlag().equals("0")) {
cpmIds.add(cpmSpaceRelation.getCpmId());
if (StringUtils.isNotEmpty(cpmSpaceRelation.getLedgerId())) {
finalLedgerIds.add(cpmSpaceRelation.getLedgerId());
}
}
});
houseInfo.setCpmId(cpmIds);
// ledgerIds去掉重复值
ledgerIds = finalLedgerIds.stream().distinct().collect(Collectors.toList());
houseInfo.setLedgerId(ledgerIds);
return houseInfo;
} }
@Override @Override
public int insertHouseInfo(HouseInfo houseInfo) { public int insertHouseInfo(HouseInfo houseInfo) {
getAreaIdAndBuildingId(houseInfo); getAreaIdAndBuildingId(houseInfo);
return houseInfoMapper.insert(houseInfo); int insert = houseInfoMapper.insert(houseInfo);
List<String> ledgerIds = houseInfo.getLedgerId();
if (ledgerIds != null && !ledgerIds.isEmpty()) {
for (String ledgerId : ledgerIds) {
List<String> cpmIds = houseInfo.getCpmId();
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageMapper.selectList(new QueryWrapper<CollectionParamsManage>().eq("device_ledger_id", ledgerId));
// 根据ledgerId查询对应的cpmId,判断当前houseIfo中的List<String> cpmId包含了哪几个cpmId,就插入哪几个
if (collectionParamsManages != null && !collectionParamsManages.isEmpty()) {
for (CollectionParamsManage cpm : collectionParamsManages) {
if (cpmIds != null && cpmIds.contains(cpm.getId())) {
// 插入关联的区域关联表
CpmSpaceRelation cpmSpaceRelation = new CpmSpaceRelation();
cpmSpaceRelation.setAreaId(houseInfo.getAreaId());
cpmSpaceRelation.setBuildingId(houseInfo.getBuildingId());
cpmSpaceRelation.setHouseId(houseInfo.getId());
cpmSpaceRelation.setFloorId(houseInfo.getFloorId());
cpmSpaceRelation.setLedgerId(ledgerId);
cpmSpaceRelation.setCpmId(cpm.getId());
cpmSpaceRelation.setCreateBy(houseInfo.getCreateBy());
cpmSpaceRelation.setCreateTime(houseInfo.getCreateTime());
cpmSpaceRelation.setDelFlag("0");
cpmSpaceRelationMapper.insert(cpmSpaceRelation);
}
}
}
}
}
return insert;
} }
// 递归查找楼栋节点方法 // 递归查找楼栋节点方法
@ -105,7 +171,53 @@ public class HouseInfoServiceImpl implements IHouseInfoService {
@Override @Override
public int updateHouseInfo(HouseInfo houseInfo) { public int updateHouseInfo(HouseInfo houseInfo) {
getAreaIdAndBuildingId(houseInfo); getAreaIdAndBuildingId(houseInfo);
return houseInfoMapper.updateById(houseInfo); int updateById = houseInfoMapper.updateById(houseInfo);
if (updateById > 0) {
List<String> ledgerIds = houseInfo.getLedgerId();
List<String> cpmIds = houseInfo.getCpmId();
// if (cpmIds != null && !cpmIds.isEmpty()) {
// for (String cpmId : cpmIds) {
// // 删除对应的cpmId关联
// cpmSpaceRelationMapper.delete(new QueryWrapper<CpmSpaceRelation>().eq("cpm_id", cpmId).eq("house_id", houseInfo.getId()));
// }
// }
// 更新delFlag为2
cpmSpaceRelationMapper.updateByHouseId(houseInfo.getId(), "2");
if (ledgerIds != null && !ledgerIds.isEmpty()) {
for (String ledgerId : ledgerIds) {
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageMapper.selectList(new QueryWrapper<CollectionParamsManage>().eq("device_ledger_id", ledgerId));
// 根据ledgerId查询对应的cpmId,判断当前houseIfo中的List<String> cpmId包含了哪几个cpmId,就插入哪几个
if (collectionParamsManages != null && !collectionParamsManages.isEmpty()) {
for (CollectionParamsManage cpm : collectionParamsManages) {
if (cpmIds != null && cpmIds.contains(cpm.getId())) {
// 判断关联表是否已经存在对应的cpmId
CpmSpaceRelation cpmSpaceRelation = cpmSpaceRelationMapper.selectOne(new QueryWrapper<CpmSpaceRelation>()
.eq("house_id", houseInfo.getId()).eq("cpm_id", cpm.getId()));
if (cpmSpaceRelation == null) {
cpmSpaceRelation = new CpmSpaceRelation();
cpmSpaceRelation.setAreaId(houseInfo.getAreaId());
cpmSpaceRelation.setBuildingId(houseInfo.getBuildingId());
cpmSpaceRelation.setFloorId(houseInfo.getFloorId());
cpmSpaceRelation.setHouseId(houseInfo.getId());
cpmSpaceRelation.setLedgerId(ledgerId);
cpmSpaceRelation.setCpmId(cpm.getId());
cpmSpaceRelation.setCreateTime(new Date());
cpmSpaceRelation.setCreateBy(houseInfo.getUpdateBy());
cpmSpaceRelation.setDelFlag("0");
cpmSpaceRelationMapper.insert(cpmSpaceRelation);
} else {
cpmSpaceRelation.setUpdateTime(new Date());
cpmSpaceRelation.setUpdateBy(houseInfo.getUpdateBy());
cpmSpaceRelation.setDelFlag("0");
cpmSpaceRelationMapper.updateById(cpmSpaceRelation);
}
}
}
}
}
}
}
return updateById;
} }
private void getAreaIdAndBuildingId(HouseInfo houseInfo) { private void getAreaIdAndBuildingId(HouseInfo houseInfo) {
@ -168,10 +280,169 @@ public class HouseInfoServiceImpl implements IHouseInfoService {
return List.of(); return List.of();
} }
@Override
public List<SpaceTreeSelect> buildFloorTree(String systemType) {
QueryWrapper<AreaInfo> areaInfoQueryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(systemType)) {
if ("1".equals(systemType)) {
areaInfoQueryWrapper.in("system_type", "1", "6");
} else {
areaInfoQueryWrapper.eq("system_type", systemType);
}
}
areaInfoQueryWrapper.orderByAsc("order_num");
List<AreaInfo> areaInfos = areaInfoMapper.selectList(areaInfoQueryWrapper);
if (areaInfos != null && !areaInfos.isEmpty()) {
List<BuildingInfo> buildingInfos = buildingInfoMapper.selectList(new QueryWrapper<BuildingInfo>().orderByAsc("order_num"));
List<FloorInfo> floorInfos = floorInfoMapper.selectList(new QueryWrapper<FloorInfo>().orderByAsc("order_num"));
return buildFloorTree(areaInfos, buildingInfos, floorInfos);
}
return List.of();
}
public List<SpaceTreeSelect> buildFloorTree(List<AreaInfo> areaInfos,
List<BuildingInfo> buildingInfos,
List<FloorInfo> floorInfos) {
// 创建合并后的楼层节点
Map<String, List<SpaceTreeSelect>> buildingMap = new HashMap<>();
// 遍历每个楼栋下的楼层信息
Map<String, List<FloorInfo>> floorsByBuilding = floorInfos.stream()
.collect(Collectors.groupingBy(FloorInfo::getBuildingId));
for (Map.Entry<String, List<FloorInfo>> entry : floorsByBuilding.entrySet()) {
String buildingId = entry.getKey();
List<FloorInfo> floorsInBuilding = entry.getValue();
// 提取楼层名称的前缀部分(例如从"-1楼裙楼"提取"-1楼")
Map<String, List<FloorInfo>> groupedByPrefix = new HashMap<>();
for (FloorInfo floor : floorsInBuilding) {
String floorName = floor.getFloorName();
// 提取前缀,例如"-1楼"
String prefix = extractFloorPrefix(floorName);
groupedByPrefix.computeIfAbsent(prefix, k -> new ArrayList<>()).add(floor);
}
// 为每个前缀创建节点结构
List<SpaceTreeSelect> mergedFloorNodes = new ArrayList<>();
for (Map.Entry<String, List<FloorInfo>> prefixEntry : groupedByPrefix.entrySet()) {
String prefix = prefixEntry.getKey();
List<FloorInfo> floorsWithSamePrefix = prefixEntry.getValue();
if (floorsWithSamePrefix.size() > 1) {
// 如果有多个同前缀楼层,创建父节点并添加子节点
SpaceTreeSelect parentNode = new SpaceTreeSelect(buildingId + "_" + prefix, prefix, false, buildingId, 3);
List<SpaceTreeSelect> children = floorsWithSamePrefix.stream()
.map(f -> {
// 子节点显示完整名称
return new SpaceTreeSelect(f.getId(), f.getFloorName(), false, buildingId + "_" + prefix, 3);
})
.sorted(Comparator.comparing(SpaceTreeSelect::getLabel)) // 子节点按名称排序
.collect(Collectors.toList());
parentNode.setChildren(null);
mergedFloorNodes.add(parentNode);
} else {
// 如果只有一个楼层,直接创建节点
FloorInfo floor = floorsWithSamePrefix.get(0);
SpaceTreeSelect node = new SpaceTreeSelect(floor.getId(), floor.getFloorName(), false, buildingId, 3);
node.setChildren(null);
mergedFloorNodes.add(node);
}
}
// 按楼层数字顺序排序(-1楼、1楼、2楼等)
mergedFloorNodes.sort((node1, node2) -> {
String label1 = node1.getLabel();
String label2 = node2.getLabel();
return compareFloorLabels(label1, label2);
});
buildingMap.put(buildingId, mergedFloorNodes);
}
// 楼栋 -> 区域映射
Map<String, List<SpaceTreeSelect>> areaMap = buildingInfos.stream()
.map(b -> {
SpaceTreeSelect node = new SpaceTreeSelect(b.getId(), b.getBuildingName(), false, b.getAreaId(), 2);
node.setChildren(buildingMap.getOrDefault(b.getId(), Collections.emptyList()));
return node;
})
.collect(Collectors.groupingBy(SpaceTreeSelect::getParentId));
// 区域 -> 根节点映射
Map<String, List<SpaceTreeSelect>> map = areaInfos.stream()
.map(a -> {
SpaceTreeSelect node = new SpaceTreeSelect(a.getId(), a.getAreaName(), false, "0", 1);
node.setChildren(areaMap.getOrDefault(a.getId(), Collections.emptyList()));
return node;
})
.collect(Collectors.groupingBy(SpaceTreeSelect::getParentId));
List<SysParams> sysParams = sysParamsMapper.selectSysParamsList();
return sysParams.stream().map(r -> {
SpaceTreeSelect node = new SpaceTreeSelect(r.getId(), r.getProName(), false, null, 0);
node.setChildren(map.getOrDefault(r.getId(), Collections.emptyList()));
return node;
}).collect(Collectors.toList());
}
// 提取楼层名称前缀的辅助方法
private String extractFloorPrefix(String floorName) {
// 匹配类似"-1楼"、"1楼"、"B1楼"等前缀
if (floorName.contains("楼")) {
int index = floorName.indexOf("楼");
return floorName.substring(0, index + 1);
}
// 如果没有找到"楼"字,返回原名称
return floorName;
}
// 比较楼层标签的辅助方法
private int compareFloorLabels(String label1, String label2) {
Integer floorNum1 = extractFloorNumber(label1);
Integer floorNum2 = extractFloorNumber(label2);
// 如果都能提取到楼层号,则按楼层号排序
if (floorNum1 != null && floorNum2 != null) {
return floorNum1.compareTo(floorNum2);
}
// 如果其中一个能提取到楼层号,则能提取到的排在前面
if (floorNum1 != null) {
return -1;
}
if (floorNum2 != null) {
return 1;
}
// 都不能提取到楼层号,则按字典序排序
return label1.compareTo(label2);
}
// 从楼层标签中提取楼层号
private Integer extractFloorNumber(String label) {
// 匹配模式如 "-1楼", "1楼", "B1楼" 等
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(-?\\d+)楼");
java.util.regex.Matcher matcher = pattern.matcher(label);
if (matcher.find()) {
try {
return Integer.parseInt(matcher.group(1));
} catch (NumberFormatException e) {
return null;
}
}
return null;
}
public List<SpaceTreeSelect> buildTree(List<AreaInfo> areaInfos, public List<SpaceTreeSelect> buildTree(List<AreaInfo> areaInfos,
List<BuildingInfo> buildingInfos, List<BuildingInfo> buildingInfos,
List<FloorInfo> floorInfos, List<FloorInfo> floorInfos,
List<HouseInfo> houseInfos) { List<HouseInfo> houseInfos) {
// 房间 -> 楼层映射 // 房间 -> 楼层映射
Map<String, List<SpaceTreeSelect>> floorMap = houseInfos.stream() Map<String, List<SpaceTreeSelect>> floorMap = houseInfos.stream()
.map(r -> new SpaceTreeSelect(r.getId(), r.getHouseName(), false, r.getFloorId(), 4)) .map(r -> new SpaceTreeSelect(r.getId(), r.getHouseName(), false, r.getFloorId(), 4))

Loading…
Cancel
Save