Compare commits

..

2 Commits

Author SHA1 Message Date
44baca6c45 revert 2025-08-06 22:26:04 +08:00
f59eeab0d0 本地ems不订阅mqtt 2025-08-06 22:23:48 +08:00
289 changed files with 1822 additions and 37257 deletions

View File

@ -39,9 +39,8 @@
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 核心模块-->

View File

@ -1,82 +0,0 @@
package com.xzzn.web.controller.ems;
import java.util.List;
import com.xzzn.ems.domain.vo.EnergyPriceVo;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.xzzn.common.annotation.Log;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.BusinessType;
import com.xzzn.ems.service.IEmsEnergyPriceConfigService;
import com.xzzn.common.core.page.TableDataInfo;
/**
* 电价配置Controller
*
* @author xzzn
* @date 2025-09-28
*/
@RestController
@RequestMapping("/ems/energyPriceConfig")
public class EmsEnergyPriceConfigController extends BaseController
{
@Autowired
private IEmsEnergyPriceConfigService emsEnergyPriceConfigService;
/**
* 查询电价配置列表
*/
@PreAuthorize("@ss.hasPermi('system:config:list')")
@GetMapping("/list")
public TableDataInfo list(String siteId, String startTime,String endTime)
{
List<EnergyPriceVo> list = emsEnergyPriceConfigService.selectEmsEnergyPriceConfigList(siteId,startTime,endTime);
return getDataTable2(list);
}
/**
* 获取电价配置详细信息
*/
@PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(emsEnergyPriceConfigService.selectEmsEnergyPriceConfigById(id));
}
/**
* 新增电价配置
*/
@PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "电价配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EnergyPriceVo priceVo)
{
return toAjax(emsEnergyPriceConfigService.insertEmsEnergyPriceConfig(priceVo));
}
/**
* 修改电价配置
*/
@PreAuthorize("@ss.hasPermi('system:config:edit')")
@Log(title = "电价配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EnergyPriceVo priceVo)
{
return toAjax(emsEnergyPriceConfigService.updateEmsEnergyPriceConfig(priceVo));
}
/**
* 删除电价配置
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "电价配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(emsEnergyPriceConfigService.deleteEmsEnergyPriceConfigByIds(ids));
}
}

View File

@ -1,107 +0,0 @@
package com.xzzn.web.controller.ems;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.xzzn.ems.service.IEmsFaultProtectionPlanService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xzzn.common.annotation.Log;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.BusinessType;
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
import com.xzzn.common.utils.poi.ExcelUtil;
import com.xzzn.common.core.page.TableDataInfo;
/**
* 故障告警保护方案Controller
*
* @author xzzn
* @date 2025-10-22
*/
@RestController
@RequestMapping("/ems/protectPlan")
public class EmsFaultProtectionPlanController extends BaseController
{
@Autowired
private IEmsFaultProtectionPlanService emsFaultProtectionPlanService;
/**
* 查询故障告警保护方案列表
*/
@PreAuthorize("@ss.hasPermi('system:plan:list')")
@GetMapping("/list")
public TableDataInfo list(EmsFaultProtectionPlan emsFaultProtectionPlan)
{
startPage();
List<EmsFaultProtectionPlan> list = emsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(emsFaultProtectionPlan);
return getDataTable(list);
}
/**
* 导出故障告警保护方案列表
*/
@PreAuthorize("@ss.hasPermi('system:plan:export')")
@Log(title = "故障告警保护方案", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, EmsFaultProtectionPlan emsFaultProtectionPlan)
{
List<EmsFaultProtectionPlan> list = emsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(emsFaultProtectionPlan);
ExcelUtil<EmsFaultProtectionPlan> util = new ExcelUtil<EmsFaultProtectionPlan>(EmsFaultProtectionPlan.class);
util.exportExcel(response, list, "故障告警保护方案数据");
}
/**
* 获取故障告警保护方案详细信息
*/
@PreAuthorize("@ss.hasPermi('system:plan:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(emsFaultProtectionPlanService.selectEmsFaultProtectionPlanById(id));
}
/**
* 新增故障告警保护方案
*/
@PreAuthorize("@ss.hasPermi('system:plan:add')")
@Log(title = "故障告警保护方案", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EmsFaultProtectionPlan emsFaultProtectionPlan)
{
emsFaultProtectionPlan.setCreateBy(getUsername());
return toAjax(emsFaultProtectionPlanService.insertEmsFaultProtectionPlan(emsFaultProtectionPlan));
}
/**
* 修改故障告警保护方案
*/
@PreAuthorize("@ss.hasPermi('system:plan:edit')")
@Log(title = "故障告警保护方案", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EmsFaultProtectionPlan emsFaultProtectionPlan)
{
emsFaultProtectionPlan.setUpdateBy(getUsername());
return toAjax(emsFaultProtectionPlanService.updateEmsFaultProtectionPlan(emsFaultProtectionPlan));
}
/**
* 删除故障告警保护方案
*/
@PreAuthorize("@ss.hasPermi('system:plan:remove')")
@Log(title = "故障告警保护方案", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(emsFaultProtectionPlanService.deleteEmsFaultProtectionPlanByIds(ids));
}
}

View File

@ -1,78 +0,0 @@
package com.xzzn.web.controller.ems;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.DeviceCategory;
import com.xzzn.ems.domain.vo.*;
import com.xzzn.ems.service.IGeneralQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* 综合查询
*
*/
@RestController
@RequestMapping("/ems/generalQuery")
public class EmsGeneralQueryController extends BaseController{
@Autowired
private IGeneralQueryService iGeneralQueryService;
/**
* 获取设备枚举
*/
@GetMapping("/getAllDeviceCategory")
public AjaxResult getDeviceCategory()
{
// 获取所有枚举的信息
List<Map<String, String>> deviceCategoryList = new ArrayList<>();
for (DeviceCategory category : DeviceCategory.values()) {
Map<String, String> categoryMap = new HashMap<>();
categoryMap.put("name", category.getInfo());
categoryMap.put("code", category.getCode());
deviceCategoryList.add(categoryMap);
}
return success(deviceCategoryList);
}
/**
* 点位模糊查询
*/
@PostMapping("/pointFuzzyQuery")
public AjaxResult pointFuzzyQuery(@RequestBody PointNameRequest request)
{
return success(iGeneralQueryService.getPointNameList(request));
}
/**
* 根据点位查询点位数据变化
*/
@PostMapping("/getPointValueList")
public AjaxResult getPointValueList(@RequestBody PointNameRequest request)
{
List<GeneralQueryResponse> result = new ArrayList<>();
try {
result = iGeneralQueryService.getPointValueList(request);
} catch (Exception e) {
logger.error("<UNK>",e);
return error("报错请重试!");
}
return success(result);
}
/**
* 获取设备枚举
*/
@GetMapping("/getAllBatteryIdsBySites/{siteIds}")
public AjaxResult getAllBatteryIdsBySites(@PathVariable String[] siteIds)
{
return success(iGeneralQueryService.getAllBatteryIdsBySites(siteIds));
}
}

View File

@ -1,106 +0,0 @@
package com.xzzn.web.controller.ems;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xzzn.common.annotation.Log;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.BusinessType;
import com.xzzn.ems.domain.EmsMqttTopicConfig;
import com.xzzn.ems.service.IEmsMqttTopicConfigService;
import com.xzzn.common.utils.poi.ExcelUtil;
import com.xzzn.common.core.page.TableDataInfo;
/**
* 站点topic配置Controller
*
* @author xzzn
* @date 2025-11-06
*/
@RestController
@RequestMapping("/ems/mqttConfig")
public class EmsMqttTopicConfigController extends BaseController
{
@Autowired
private IEmsMqttTopicConfigService emsMqttTopicConfigService;
/**
* 查询站点topic配置列表
*/
@PreAuthorize("@ss.hasPermi('system:config:list')")
@GetMapping("/list")
public TableDataInfo list(EmsMqttTopicConfig emsMqttTopicConfig)
{
startPage();
List<EmsMqttTopicConfig> list = emsMqttTopicConfigService.selectEmsMqttTopicConfigList(emsMqttTopicConfig);
return getDataTable(list);
}
/**
* 导出站点topic配置列表
*/
@PreAuthorize("@ss.hasPermi('system:config:export')")
@Log(title = "站点topic配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, EmsMqttTopicConfig emsMqttTopicConfig)
{
List<EmsMqttTopicConfig> list = emsMqttTopicConfigService.selectEmsMqttTopicConfigList(emsMqttTopicConfig);
ExcelUtil<EmsMqttTopicConfig> util = new ExcelUtil<EmsMqttTopicConfig>(EmsMqttTopicConfig.class);
util.exportExcel(response, list, "站点topic配置数据");
}
/**
* 获取站点topic配置详细信息
*/
@PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(emsMqttTopicConfigService.selectEmsMqttTopicConfigById(id));
}
/**
* 新增站点topic配置
*/
@PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "站点topic配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EmsMqttTopicConfig emsMqttTopicConfig)
{
emsMqttTopicConfig.setCreateBy(getUsername());
return toAjax(emsMqttTopicConfigService.insertEmsMqttTopicConfig(emsMqttTopicConfig));
}
/**
* 修改站点topic配置
*/
@PreAuthorize("@ss.hasPermi('system:config:edit')")
@Log(title = "站点topic配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EmsMqttTopicConfig emsMqttTopicConfig)
{
emsMqttTopicConfig.setUpdateBy(getUsername());
return toAjax(emsMqttTopicConfigService.updateEmsMqttTopicConfig(emsMqttTopicConfig));
}
/**
* 删除站点topic配置
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "站点topic配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(emsMqttTopicConfigService.deleteEmsMqttTopicConfigByIds(ids));
}
}

View File

@ -1,88 +0,0 @@
package com.xzzn.web.controller.ems;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xzzn.common.annotation.Log;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.BusinessType;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.DevicePointMatchExportVo;
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
import com.xzzn.ems.service.IEmsPointMatchService;
import com.xzzn.common.utils.poi.ExcelUtil;
import org.springframework.web.multipart.MultipartFile;
/**
* 点位匹配Controller
*
* @author xzzn
* @date 2025-11-04
*/
@RestController
@RequestMapping("/ems/pointMatch")
public class EmsPointMatchController extends BaseController
{
@Autowired
private IEmsPointMatchService emsPointMatchService;
/**
* 导出点位匹配列表
*/
@PreAuthorize("@ss.hasPermi('system:match:export')")
@Log(title = "点位匹配", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, EmsPointMatch emsPointMatch)
{
List<DevicePointMatchExportVo> list = emsPointMatchService.selectEmsPointMatchList(emsPointMatch);
ExcelUtil<DevicePointMatchExportVo> util = new ExcelUtil<>(DevicePointMatchExportVo.class);
util.exportExcel(response, list, "点位匹配数据");
}
/**
* 上传点位清单
* @param file
* @param updateSupport
* @return
* @throws Exception
*/
@PreAuthorize("@ss.hasPermi('system:user:import')")
@Log(title = "点位匹配", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
{
ExcelUtil<EmsPointMatch> util = new ExcelUtil<EmsPointMatch>(EmsPointMatch.class);
List<EmsPointMatch> pointMatcheList = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = emsPointMatchService.importPoint(pointMatcheList, updateSupport, operName);
return success(message);
}
/**
* 上传设备的点位清单
* @param request
* @return
* @throws Exception
*/
@PreAuthorize("@ss.hasPermi('system:user:import')")
@Log(title = "点位匹配", businessType = BusinessType.IMPORT)
@PostMapping("/importDataByDevice")
public void importDataByDevice(@Valid ImportPointDataRequest request, HttpServletResponse response) {
List<DevicePointMatchVo> list = emsPointMatchService.importDataByDevice(request, getUsername());
if (CollectionUtils.isNotEmpty(list)) {
ExcelUtil<DevicePointMatchVo> util = new ExcelUtil<>(DevicePointMatchVo.class);
util.exportExcel(response, list, "点位匹配数据");
}
}
}

View File

@ -1,38 +1,22 @@
package com.xzzn.web.controller.ems;
import com.xzzn.common.annotation.Log;
import com.xzzn.common.config.RuoYiConfig;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.core.page.TableDataInfo;
import com.xzzn.common.enums.BusinessType;
import com.xzzn.common.utils.file.FileUploadUtils;
import com.xzzn.common.utils.file.MimeTypeUtils;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.EmsSiteSetting;
import com.xzzn.ems.domain.vo.DeviceUpdateRequest;
import com.xzzn.ems.domain.vo.DevicesSettingVo;
import com.xzzn.ems.domain.vo.PointDataRequest;
import com.xzzn.ems.domain.vo.PointQueryResponse;
import com.xzzn.ems.domain.vo.SiteDeviceListVo;
import com.xzzn.ems.service.IEmsDeviceSettingService;
import com.xzzn.ems.service.IEmsSiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
*
* 站点配置
@ -63,12 +47,10 @@ public class EmsSiteConfigController extends BaseController{
* 获取设备列表-分页
*/
@GetMapping("/getDeviceInfoList")
public TableDataInfo getDeviceInfoList(@RequestParam(value = "siteId", required = false) String siteId,
@RequestParam(value = "deviceCategory", required = false) String deviceCategory)
public TableDataInfo getDeviceInfoList(@RequestParam String siteId)
{
startPage();
List<SiteDeviceListVo> list = iEmsSiteService.getAllDeviceListNoDisp(siteId, deviceCategory);
List<SiteDeviceListVo> list = iEmsSiteService.getAllDeviceList(siteId);
return getDataTable(list);
}
@ -87,7 +69,7 @@ public class EmsSiteConfigController extends BaseController{
@GetMapping("/getDeviceList")
public AjaxResult getDeviceInfoList2(@RequestParam String siteId)
{
return success(iEmsSiteService.getAllDeviceList(siteId, null));
return success(iEmsSiteService.getAllDeviceList(siteId));
}
/**
@ -103,7 +85,7 @@ public class EmsSiteConfigController extends BaseController{
* 新增设备
*/
@PostMapping("/addDevice")
public AjaxResult addDevice(@RequestBody DevicesSettingVo devicesSetting)
public AjaxResult addDevice(@RequestBody EmsDevicesSetting devicesSetting)
{
int result = iEmsDeviceSettingService.addDevice(devicesSetting);
if (result > 0) {
@ -133,7 +115,7 @@ public class EmsSiteConfigController extends BaseController{
* 修改Modbus设备配置
*/
@PostMapping("/updateDevice")
public AjaxResult updateDevice(@RequestBody DevicesSettingVo emsDevicesSetting)
public AjaxResult updateDevice(@RequestBody EmsDevicesSetting emsDevicesSetting)
{
int result = iEmsDeviceSettingService.updateDevice(emsDevicesSetting);
if (result > 0) {
@ -154,52 +136,4 @@ public class EmsSiteConfigController extends BaseController{
{
return toAjax(iEmsDeviceSettingService.deleteEmsDevicesSettingById(id));
}
/**
* 单个站点单个设备点位查询-点位清单
*/
@GetMapping("/getDevicePointList")
public TableDataInfo getDevicePointList(@Validated PointDataRequest request)
{
List<PointQueryResponse> result = iEmsDeviceSettingService.getSingleSiteDevicePoints(request);
return getDataTable2(result);
}
/**
* 获取指定站点下的所有设备类别
*/
@GetMapping("/getSiteAllDeviceCategory")
public AjaxResult getSiteAllDeviceCategory(String siteId)
{
return success(iEmsDeviceSettingService.getSiteAllDeviceCategory(siteId));
}
/**
* 根据设备类别获取父类的设备id
*/
@GetMapping("/getParentDeviceId")
public AjaxResult getParentDeviceId(@RequestParam String siteId, @RequestParam String deviceCategory)
{
return success(iEmsSiteService.getParentCategoryDeviceId(siteId, deviceCategory));
}
/**
* 获取指定站点下的指定设备类型的设备
*/
@GetMapping("/getDeviceListBySiteAndCategory")
public AjaxResult getDeviceListBySiteAndCategory(String siteId,String deviceCategory)
{
return success(iEmsDeviceSettingService.getDeviceListBySiteAndCategory(siteId, deviceCategory));
}
/**
* PCS设备开关机
*/
// @PreAuthorize("@ss.hasPermi('system:device:onAndOff')")
@Log(title = "开关机", businessType = BusinessType.UPDATE)
@PostMapping("/updateDeviceStatus")
public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request)
{
return success(iEmsDeviceSettingService.updateDeviceStatus(request));
}
}

View File

@ -2,7 +2,7 @@ package com.xzzn.web.controller.ems;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.ems.domain.vo.DateSearchRequest;
import com.xzzn.ems.service.IEmsSiteService;
import com.xzzn.ems.service.IHomePageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
/**
*
* 站点地图
// * 站点地图
*
*/
@RestController
@ -31,17 +31,4 @@ public class EmsSiteMapController extends BaseController{
return success(homePageService.getSingleSiteBaseInfo(siteId));
}
/**
* 获取某个站点7天充放电数据
*/
@GetMapping("/getSevenChargeData")
public AjaxResult getSevenChargeData(DateSearchRequest request)
{
String siteId = request.getSiteId();
if(siteId == null || siteId.isEmpty()) {
return error("站点必传");
}
return success(homePageService.getSevenChargeData(request));
}
}

View File

@ -3,19 +3,14 @@ package com.xzzn.web.controller.ems;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.core.page.TableDataInfo;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.vo.BMSBatteryDataList;
import com.xzzn.ems.domain.vo.BatteryDataStatsListVo;
import com.xzzn.ems.domain.vo.DateSearchRequest;
import com.xzzn.ems.domain.vo.RunningGraphRequest;
import com.xzzn.ems.domain.vo.SiteBatteryDataList;
import com.xzzn.ems.service.IEmsSiteService;
import com.xzzn.ems.service.IEmsStatsReportService;
import com.xzzn.ems.service.ISingleSiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
@ -56,27 +51,27 @@ public class EmsSiteMonitorController extends BaseController{
* 单站监控-设备监控-实时运行曲线图数据
*/
@GetMapping("/runningGraph/storagePower")
public AjaxResult getRunningGraphStorage(RunningGraphRequest request)
public AjaxResult getRunningGraphStorage(@RequestParam String siteId)
{
return success(iSingleSiteService.getRunningGraphStorage(request));
return success(iSingleSiteService.getRunningGraphStorage(siteId));
}
@GetMapping("/runningGraph/pcsMaxTemp")
public AjaxResult getRunningGraphPcsMaxTemp(RunningGraphRequest request)
@GetMapping("/runningGraph/stackAveTemp")
public AjaxResult getRunningGraphStackTemp(@RequestParam String siteId)
{
return success(iSingleSiteService.getRunningGraphPcsMaxTemp(request));
return success(iSingleSiteService.getRunningGraphStackTemp(siteId));
}
@GetMapping("/runningGraph/batteryAveSoc")
public AjaxResult getRunningGraphBatterySoc(RunningGraphRequest request)
public AjaxResult getRunningGraphBatterySoc(@RequestParam String siteId)
{
return success(iSingleSiteService.getRunningGraphBatterySoc(request));
return success(iSingleSiteService.getRunningGraphBatterySoc(siteId));
}
@GetMapping("/runningGraph/batteryAveTemp")
public AjaxResult getRunningGraphBatteryTemp(RunningGraphRequest request)
public AjaxResult getRunningGraphBatteryTemp(@RequestParam String siteId)
{
return success(iSingleSiteService.getRunningGraphBatteryTemp(request));
return success(iSingleSiteService.getRunningGraphBatteryTemp(siteId));
}
/**
@ -146,27 +141,11 @@ public class EmsSiteMonitorController extends BaseController{
* 获取电池簇下面的单体电池数据
*/
@GetMapping("/getClusterDataInfoList")
public TableDataInfo getClusterDataInfoList(@RequestParam String clusterDeviceId,@RequestParam String siteId,
@RequestParam String stackDeviceId,@RequestParam String batteryId)
public TableDataInfo getClusterDataInfoList(@RequestParam String clusterDeviceId,@RequestParam String siteId)
{
startPage();
SiteBatteryDataList siteBatteryDataList = new SiteBatteryDataList();
// 簇最大最小单体id数据
List<BMSBatteryDataList> clusterBatteryDataList = iSingleSiteService.getClusterBatteryList(siteId,stackDeviceId,clusterDeviceId);
siteBatteryDataList.setClusterList(clusterBatteryDataList);
// 单体电池数据
List<BatteryDataStatsListVo> List = iSingleSiteService.getClusterDataInfoList(clusterDeviceId,siteId,stackDeviceId,batteryId);
// 对batteryList进行分页处理
List<BatteryDataStatsListVo> batteryList = paginateList(List);
siteBatteryDataList.setBatteryList(batteryList);
// 封装分页信息
TableDataInfo pageInfo = new TableDataInfo();
pageInfo.setTotal(List.size());
pageInfo.setRows(Arrays.asList(siteBatteryDataList));
pageInfo.setCode(0);
pageInfo.setMsg("查询成功");
return pageInfo;
List<BatteryDataStatsListVo> list = iSingleSiteService.getClusterDataInfoList(clusterDeviceId,siteId);
return getDataTable2(list);
}
/**
@ -186,46 +165,4 @@ public class EmsSiteMonitorController extends BaseController{
{
return success(iSingleSiteService.getAmmeterDataList(siteId));
}
/**
* 动环数据
*/
@GetMapping("/getDhDataList")
public AjaxResult getDhDataList(@RequestParam String siteId)
{
return success(iSingleSiteService.getDhDataList(siteId));
}
/**
* 消防数据
*/
@GetMapping("/getXfDataList")
public AjaxResult getXfDataList(@RequestParam String siteId)
{
return success(iSingleSiteService.getXfDataList(siteId));
}
/**
* EMS数据
*/
@GetMapping("/getEmsDataList")
public AjaxResult getEmsDataList(@RequestParam String siteId)
{
return success(iSingleSiteService.getEmsDataList(siteId));
}
/**
* 单站监控-首页-点位展示
* 储能功率、电网功率、负荷功率、光伏功率
* SOC、SOH、电池平均温度
*/
@GetMapping("/getPointData")
public AjaxResult getPointData(DateSearchRequest requestVo)
{
if (!StringUtils.isEmpty(requestVo.getSiteId())) {
return success(iSingleSiteService.getPointData(requestVo));
} else {
return error("缺少必传项");
}
}
}

View File

@ -4,7 +4,10 @@ import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.core.page.TableDataInfo;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.vo.*;
import com.xzzn.ems.domain.vo.ClusterStatisListVo;
import com.xzzn.ems.domain.vo.DateSearchRequest;
import com.xzzn.ems.domain.vo.StatisAmmeterDateRequest;
import com.xzzn.ems.domain.vo.StatisClusterDateRequest;
import com.xzzn.ems.service.IEmsStatsReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -55,7 +58,8 @@ public class EmsStatisticalReportController extends BaseController
@GetMapping("/getPCSData")
public AjaxResult getPCSData(DateSearchRequest requestVo)
{
if (!StringUtils.isEmpty(requestVo.getSiteId())&&
if (!StringUtils.isEmpty(requestVo.getSiteId()) &&
!StringUtils.isEmpty(requestVo.getDeviceId()) &&
!StringUtils.isEmpty(requestVo.getDataType())) {
return success(ieEmsStatsReportService.getPCSDataResult(requestVo));
} else {
@ -70,6 +74,7 @@ public class EmsStatisticalReportController extends BaseController
public AjaxResult getStackData(DateSearchRequest requestVo)
{
if (!StringUtils.isEmpty(requestVo.getSiteId()) &&
!StringUtils.isEmpty(requestVo.getDeviceId()) &&
!StringUtils.isEmpty(requestVo.getDataType())) {
return success(ieEmsStatsReportService.getStackDataResult(requestVo));
} else {
@ -95,7 +100,7 @@ public class EmsStatisticalReportController extends BaseController
}
/**
* 概率统计-获取站点下所有电
* 概率统计-获取
*/
@GetMapping("/getLoadNameList")
public AjaxResult getLoadNameList(String siteId)
@ -111,22 +116,13 @@ public class EmsStatisticalReportController extends BaseController
* 概率统计-电表报表
*/
@GetMapping("/getAmmeterData")
public TableDataInfo getAmmeterData(StatisAmmeterDateRequest requestVo)
public AjaxResult getAmmeterData(StatisAmmeterDateRequest requestVo)
{
startPage();
List<AmmeterStatisListVo> dataList = ieEmsStatsReportService.getAmmeterDataResult(requestVo);
return getDataTable(dataList);
}
/**
* 概率统计-电表收益报表
*/
@GetMapping("/getAmmeterRevenueData")
public TableDataInfo getAmmeterRevenueData(StatisAmmeterDateRequest requestVo)
{
startPage();
List<AmmeterRevenueStatisListVo> dataList = ieEmsStatsReportService.getAmmeterRevenueDataResult(requestVo);
return getDataTable(dataList);
if (!StringUtils.isEmpty(requestVo.getDeviceId())) {
return success(ieEmsStatsReportService.getAmmeterDataResult(requestVo));
} else {
return error("缺少必传项");
}
}
/**
@ -135,7 +131,9 @@ public class EmsStatisticalReportController extends BaseController
@GetMapping("/getPowerData")
public AjaxResult getPowerData(DateSearchRequest requestVo)
{
if (!StringUtils.isEmpty(requestVo.getSiteId())) {
if (!StringUtils.isEmpty(requestVo.getSiteId())
&& !StringUtils.isEmpty(requestVo.getDeviceId())
&& !StringUtils.isEmpty(requestVo.getDataType())) {
return success(ieEmsStatsReportService.getPowerDataList(requestVo));
} else {
return error("缺少必传项");

View File

@ -1,39 +1,27 @@
package com.xzzn.web.controller.ems;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.TopicHandleType;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsMqttTopicConfig;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.domain.EmsMqttMessage;
import com.xzzn.ems.service.IDDSDataProcessService;
import com.xzzn.ems.service.IDeviceDataProcessService;
import com.xzzn.ems.service.IEmsMqttMessageService;
import com.xzzn.ems.service.IEmsStrategyService;
import com.xzzn.ems.service.IFXXAlarmDataProcessService;
import com.xzzn.ems.service.IFXXDataProcessService;
import com.xzzn.ems.service.IMqttSyncLogService;
import com.xzzn.framework.manager.MqttLifecycleManager;
import com.xzzn.framework.web.service.MqttPublisher;
import com.xzzn.framework.web.service.MqttSubscriber;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class MqttMessageController implements MqttPublisher, MqttSubscriber {
private static final Logger log = LoggerFactory.getLogger(MqttMessageController.class);
private static final Log log = LogFactory.getLog(MqttMessageController.class);
private final MqttLifecycleManager mqttLifecycleManager;
@ -46,22 +34,6 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
@Autowired
private IDDSDataProcessService dDSDataProcessService;
@Autowired
private IDeviceDataProcessService deviceDataProcessService;
@Autowired
private IFXXAlarmDataProcessService fXXAlarmDataProcessService;
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private IEmsStrategyService emsStrategyService;
@Autowired
private IMqttSyncLogService iMqttSyncLogService;
@Autowired
private RedisCache redisCache;
@Autowired
public MqttMessageController(MqttLifecycleManager mqttLifecycleManager) {
this.mqttLifecycleManager = mqttLifecycleManager;
@ -69,69 +41,20 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
@PostConstruct
public void init() {
List<EmsMqttTopicConfig> topicConfigList = emsMqttTopicConfigMapper.selectEmsMqttTopicConfigList(null);
if (CollectionUtils.isEmpty (topicConfigList)) {
log.info ("未查询到任何 MQTT 主题配置,跳过订阅");
return;
}
for (EmsMqttTopicConfig topicConfig : topicConfigList) {
String topic = topicConfig.getMqttTopic();
if (StringUtils.isEmpty(topic)) {
log.info ("主题配置 ID:" +topicConfig.getId() +"的 mqttTopic 为空,跳过订阅");
continue;
}
int qos = topicConfig.getQos() == null ? 1 : topicConfig.getQos();
if (qos < 0 || qos > 2) {
log.info ("主题:" + topic +"的 QoS值"+ qos + "不合法自动调整为1");
qos = 1;
}
IMqttMessageListener listener = getMqttListenerByTopic(topic, topicConfig.getHandleType());
subscribe(topic, qos, listener);
}
// 订阅奉贤系统状态主题
/*subscribe("021_FXX_01_UP", 1, this::handleDeviceData);
subscribe("021_FXX_01_UP", 1, this::handleDeviceData);
subscribe("021_FXX_01_RECALL", 1, this::handleDeviceData);
subscribe("021_FXX_01_DOWN", 1, this::handleDeviceData);
subscribe("021_FXX_01", 1, this::handleSystemStatus);
subscribe("021_FXX_01_ALARM_UP", 1, this::handleAlarmData);
// 订阅电动所系统状态主题
subscribe("021_DDS_01_UP", 1, this::handleDeviceData);
subscribe("021_DDS_01_RECALL", 1, this::handleDeviceData);
subscribe("021_DDS_01_DOWN", 1, this::handleDeviceData);
subscribe("021_DDS_01", 1, this::handleSystemStatus);*/
subscribe("021_DDS_01", 1, this::handleSystemStatus);
}
private IMqttMessageListener getMqttListenerByTopic(String topic, String handleType) {
TopicHandleType topicHandleType = TopicHandleType.getEnumByCode(handleType);
switch (topicHandleType) {
case DEVICE:
return this::handleDeviceData;
case DEVICE_ALARM:
return this::handleAlarmData;
case STRATEGY:
if (topic.equals("FAULT_PROTECTION_PLAN_UP")) {
return this::handleFaultProtPlanData;
} else if (topic.equals("FAULT_ALARM_RECORD_UP")) {
return this::handleFaultAlarmData;
} else if (topic.equals("FAULT_PLAN_ISSUE_UP")) {
return this::handleFaultPlanIssueData;
} else if (topic.equals("DEVICE_CHANGE_LOG_UP")) {
return this::handleDeviceChangeLogData;
} else {
return this::handleStrategyData;
}
default:
log.warn("Unknown handle type: " + handleType + ", using default handler");
return this::handleSystemStatus;
}
}
// 处理系统状态消息
private void handleSystemStatus(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
@ -147,122 +70,21 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
// 处理设备数据
private void handleDeviceData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
log.info("[DEVICE] data: " + payload);
try {
// 业务处理逻辑
// if (topic.startsWith("021_DDS")) {
// dDSDataProcessService.handleDdsData(payload);
// } else if (topic.startsWith("021_FXX")) {
// fXXDataProcessService.handleFxData(payload);
// }
deviceDataProcessService.handleDeviceData(payload, getSiteIdByTopic(topic));
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
} catch (Exception e) {
log.error("Failed to process device data message: " + e.getMessage(), e);
}
}
// 处理告警数据
private void handleAlarmData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[DEVICE] data: " + payload);
try {
// 业务处理逻辑
// if (topic.startsWith("021_FXX")) {
// fXXAlarmDataProcessService.handleFxAlarmData(payload);
// }
deviceDataProcessService.handleAlarmData(payload, getSiteIdByTopic(topic));
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
} catch (Exception e) {
e.printStackTrace();
log.error("Failed to process device alarm data message: " + e.getMessage(), e);
}
}
private String getSiteIdByTopic(String topic) {
String siteId = redisCache.getCacheObject(RedisKeyConstants.SITE_ID + topic);
if (StringUtils.isEmpty(siteId)) {
EmsMqttTopicConfig topicConfig = emsMqttTopicConfigMapper.selectOneByTopic(topic);
siteId = topicConfig.getSiteId();
redisCache.setCacheObject(RedisKeyConstants.SITE_ID + topic, siteId);
}
log.info("当前处理数据站点:" + siteId + ",topic: " + topic);
return siteId;
}
// 处理运行策略数据:云端-本地
private void handleStrategyData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[处理运行策略数据] data: " + payload);
try {
// 业务处理逻辑
iMqttSyncLogService.handleMqttStrategyData(payload);
if (topic.startsWith("021_DDS")) {
dDSDataProcessService.handleDdsData(payload);
} else if (topic.startsWith("021_FXX")) {
fXXDataProcessService.handleFxData(payload);
}
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
} catch (Exception e) {
log.error("Failed to process strategy data message: " + e.getMessage(), e);
log.error("Failed to process system status message: " + e.getMessage(), e);
}
}
// 处理设备保护告警策略数据:云端-本地
private void handleFaultProtPlanData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[处理设备保护告警策略数据] data: " + payload);
try {
// 业务处理逻辑
iMqttSyncLogService.handleMqttPlanData(payload);
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
} catch (Exception e) {
log.error("Failed to process fault plan data message: " + e.getMessage(), e);
}
}
// 处理保护策略告警信息:本地-云端
private void handleFaultAlarmData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[处理本地保护策略告警信息到云端] data: " + payload);
try {
// 业务处理逻辑
iMqttSyncLogService.handleFaultAlarmData(payload);
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
} catch (Exception e) {
log.error("Failed to process fault plan alarm data message: " + e.getMessage(), e);
}
}
// 处理保护策略下发日志:本地-云端
private void handleFaultPlanIssueData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[处理本地保护策略下发日志到云端] data: " + payload);
try {
// 业务处理逻辑
iMqttSyncLogService.handleFaultPlanIssueData(payload);
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
} catch (Exception e) {
log.error("Failed to process fault plan issue log message: " + e.getMessage(), e);
}
}
// 处理设备状态变更日志:本地-云端
private void handleDeviceChangeLogData(String topic, MqttMessage message) {
String payload = new String(message.getPayload());
System.out.println("[处理本地的保护策略告警信息到云端] data: " + payload);
try {
// 业务处理逻辑
iMqttSyncLogService.handleDeviceChangeLogData(payload);
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
} catch (Exception e) {
log.error("Failed to process device change log message: " + e.getMessage(), e);
}
}
@Override
@ -292,4 +114,6 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
}
}
}

View File

@ -1,61 +1,61 @@
## 数据源配置
#spring:
# datasource:
# type: com.alibaba.druid.pool.DruidDataSource
# driverClassName: com.mysql.cj.jdbc.Driver
# druid:
# # 主库数据源
# master:
# url: jdbc:mysql://122.51.194.184:13306/setri_ems?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: ems
# password: 12345678
# # 从库数据源
# slave:
# # 从数据源开关/默认关闭
# enabled: false
# url:
# username:
# password:
# # 初始连接数
# initialSize: 5
# # 最小连接池数量
# minIdle: 10
# # 最大连接池数量
# maxActive: 20
# # 配置获取连接等待超时的时间
# maxWait: 60000
# # 配置连接超时时间
# connectTimeout: 30000
# # 配置网络超时时间
# socketTimeout: 60000
# # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
# timeBetweenEvictionRunsMillis: 60000
# # 配置一个连接在池中最小生存的时间,单位是毫秒
# minEvictableIdleTimeMillis: 300000
# # 配置一个连接在池中最大生存的时间,单位是毫秒
# maxEvictableIdleTimeMillis: 900000
# # 配置检测连接是否有效
# validationQuery: SELECT 1 FROM DUAL
# testWhileIdle: true
# testOnBorrow: false
# testOnReturn: false
# webStatFilter:
# enabled: true
# statViewServlet:
# enabled: true
# # 设置白名单,不填则允许所有访问
# allow:
# url-pattern: /druid/*
# # 控制台管理用户名和密码
# login-username: xzzn
# login-password: 123456
# filter:
# stat:
# enabled: true
# # 慢SQL记录
# log-slow-sql: true
# slow-sql-millis: 1000
# merge-sql: true
# wall:
# config:
# multi-statement-allow: true
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://122.51.194.184:13306/setri_ems?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ems
password: 12345678
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: xzzn
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true

View File

@ -1,207 +0,0 @@
# 项目相关配置
xzzn:
# 名称
name: EMS
# 版本
version: 0.0.1
# 版权年份
copyrightYear: 2025
# 文件路径 示例( Windows配置D:/xzzn/uploadPathLinux配置 /home/xzzn/uploadPath
profile: ../uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8089
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数默认为100
accept-count: 1000
threads:
# tomcat最大线程数默认为200
max: 800
# Tomcat启动初始化的线程数默认值10
min-spare: 100
# 日志配置
logging:
level:
com.xzzn: info
org.springframework: warn
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间默认10分钟
lockTime: 10
# Spring配置
spring:
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
# 服务模块
devtools:
restart:
# 热部署开关
enabled: true
# redis 配置
redis:
# 地址
host: 127.0.0.1
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password: 12345678
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://127.0.0.1:3306/setri_ems?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ems
password: Aa112211!
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: xzzn
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟
expireTime: 30
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.xzzn.**.domain
# 配置mapper的扫描找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
helperDialect: mysql
supportMethodsArguments: true
params: count=countSql
# Swagger配置
swagger:
# 是否开启swagger
enabled: true
# 请求前缀
pathMapping: /dev-api
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
mqtt:
broker.url: tcp://121.5.164.6:1883
client.id: ems-cloud
username: dmbroker
password: qwer1234
connection-timeout: 15
keep-alive-interval: 30
automatic-reconnect: true
topic: 021_DDS_01_UP
siteId: 021_DDS_01
modbus:
pool:
max-total: 20
max-idle: 10
min-idle: 3
poll:
interval: "0 */5 * * * *" # 5分钟间隔
timeout: 30000 # 30秒超时

View File

@ -1,207 +0,0 @@
# 项目相关配置
xzzn:
# 名称
name: EMS
# 版本
version: 0.0.1
# 版权年份
copyrightYear: 2025
# 文件路径 示例( Windows配置D:/xzzn/uploadPathLinux配置 /home/xzzn/uploadPath
profile: /home/xzzn/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8089
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数默认为100
accept-count: 1000
threads:
# tomcat最大线程数默认为200
max: 800
# Tomcat启动初始化的线程数默认值10
min-spare: 100
# 日志配置
logging:
level:
com.xzzn: info
org.springframework: warn
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间默认10分钟
lockTime: 10
# Spring配置
spring:
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
# 服务模块
devtools:
restart:
# 热部署开关
enabled: true
# redis 配置
redis:
# 地址
host: 172.17.0.9
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password: 12345678
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://172.17.0.13:3306/setri_ems?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ems
password: Aa112211!
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: xzzn
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟
expireTime: 30
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.xzzn.**.domain
# 配置mapper的扫描找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
helperDialect: mysql
supportMethodsArguments: true
params: count=countSql
# Swagger配置
swagger:
# 是否开启swagger
enabled: true
# 请求前缀
pathMapping: /dev-api
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
mqtt:
broker.url: tcp://121.5.164.6:1883
client.id: ems-cloud
username: dmbroker
password: qwer1234
connection-timeout: 15
keep-alive-interval: 30
automatic-reconnect: true
topic:
siteId:
modbus:
pool:
max-total: 20
max-idle: 10
min-idle: 3
poll:
interval: "0 */5 * * * *" # 5分钟间隔
timeout: 30000 # 30秒超时

View File

@ -87,66 +87,6 @@ spring:
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://122.51.194.184:13306/setri_ems?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ems
password: 12345678
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: xzzn
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# token配置
token:
@ -196,8 +136,6 @@ mqtt:
connection-timeout: 15
keep-alive-interval: 30
automatic-reconnect: true
topic:
siteId:
modbus:
pool:

View File

@ -119,12 +119,6 @@
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- modbus4j (保留兼容) -->
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
</dependency>
</dependencies>
</project>
</project>

View File

@ -1,11 +0,0 @@
package com.xzzn.common.annotation;
import java.lang.annotation.*;
/**
* 标记调用insert后需要同步数据到其他服务器
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SyncAfterInsert {
}

View File

@ -170,9 +170,4 @@ public class Constants
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.xzzn.common.utils.file", "com.xzzn.common.config", "com.xzzn.generator" };
/**
* 昨日充放电最晚数据有效期
*/
public static final Integer DATE_VALID_TIME = 1;
}

View File

@ -42,11 +42,6 @@ public class RedisKeyConstants
*/
public static final String DH = "DH_";
/**
* 消防数据 redis key
*/
public static final String XF = "XF_";
/**
* 电池组 redis key
*/
@ -56,70 +51,4 @@ public class RedisKeyConstants
* BMSD原始数据 redis key
*/
public static final String ORIGINAL_BMSD = "BMSD_";
/**
* 冷却数据 redis key
*/
public static final String COOLING = "COOLING_";
/**
* EMS数据 redis key
*/
public static final String EMS = "EMS_";
/**
* 点位匹配数据 redis key
*/
public static final String POINT_MATCH = "POINT_MATCH_";
/**
* 点位枚举匹配数据 redis key
*/
public static final String POINT_ENUM_MATCH = "POINT_ENUM_MATCH_";
/**
* topic对应站点ID redis key
*/
public static final String SITE_ID = "SITE_ID_";
/**
* 存放单个设备同步过来的原始数据-最晚一次数据
*/
public static final String ORIGINAL_MQTT_DATA = "MQTT_";
/**
* 存放单个设备同步过来的告警点位原始数据-最晚一次数据
*/
public static final String ORIGINAL_MQTT_DATA_ALARM = "MQTT_ALARM_";
/** 存放订阅失败告警信息 */
public static final String TOPIC_FAILED_ALRAM_RECORD = "topic_failed_";
/** topic 内没有数据设备维度告警 */
public static final String TOPIC_EMPTY_ALARM_RECORD = "topic_empty_";
/** modbus读取 没有数据设备维度告警 */
public static final String MODBUS_EMPTY_ALARM_RECORD = "modbus_empty_";
/** modbus读取 设备离线告警 */
public static final String MODBUS_OFFLINE_ALARM_RECORD = "modbus_offline_";
/** 设备信息初始化 */
public static final String INIT_DEVICE_INFO = "init_device_info";
/** 告警匹配信息 */
public static final String ALARM_MATCH_INFO = "alarm_message_info";
/** 现有的告警数据 */
public static final String LATEST_ALARM_RECORD = "LATEST_ALARM_RECORD";
/** 预存电价时间配置 */
public static final String ENERGY_PRICE_TIME = "energy_price_time_";
/** dds昨日累计总收益 */
public static final String DDS_TOTAL_REVENUE = "total_revenue_";
/** fx实时总收益和当日实时收益 */
public static final String FXX_REALTIME_REVENUE = "realtime_revenue_";
/** 每个设备最新数据-设置失效时间-判断是否正常同步数据 */
public static final String SYNC_DATA= "SYNC_DATA_";
/** 每个设备最新数据-设置失效时间-判断是否正常同步数据 */
public static final String SYNC_DATA_ALARM = "SYNC_DATA_ALARM_";
}

View File

@ -208,69 +208,28 @@ public class BaseController
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable2(List<?> list)
{
// 1. 处理原列表为null的情况避免空指针
List<?> targetList = (list == null) ? Collections.emptyList() : list;
List<?> subList;
// 2. 获取分页参数
PageDomain pageDomain = TableSupport.buildPageRequest();
int pageNum = pageDomain.getPageNum();
int pageSize = pageDomain.getPageSize();
// 3. 判断分页参数是否有效pageNum和pageSize均为正数时才分页
if (pageNum > 0 && pageSize > 0) {
// 计算起始索引确保不小于0
int startIndex = Math.max((pageNum - 1) * pageSize, 0);
// 关键修复:若起始索引已超出列表大小,直接返回空列表
if (startIndex >= targetList.size()) {
subList = Collections.emptyList();
} else {
// 计算结束索引(不超过列表大小,且不小于起始索引)
int endIndex = Math.min(startIndex + pageSize, targetList.size());
endIndex = Math.max(endIndex, startIndex); // 防止endIndex < startIndex
// 截取子列表转换为新ArrayList避免视图依赖
subList = new ArrayList<>(targetList.subList(startIndex, endIndex));
}
} else {
// 分页参数无效时,返回全部数据
subList = new ArrayList<>(targetList);
}
// 4. 封装返回结果
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(subList);
rspData.setTotal(targetList.size());
return rspData;
}
/**
* 通用分页工具方法
*/
protected <T> List<T> paginateList(List<T> sourceList) {
if (sourceList == null || sourceList.isEmpty()) {
return new ArrayList<>();
}
List<?> subList = new ArrayList<>();
// 分页梳理
PageDomain pageDomain = TableSupport.buildPageRequest();
int pageNum = pageDomain.getPageNum();
int pageSize = pageDomain.getPageSize();
int startIndex = 0;
int endIndex = sourceList.size();
if (pageNum > 0 && pageSize > 0) {
// 计算起始索引处理页码小于1的情况
startIndex = Math.max((pageNum - 1) * pageSize, 0);
// 计算结束索引(处理超出列表长度的情况)
endIndex = Math.min(startIndex + pageSize, sourceList.size());
// 计算分页起始和结束索引
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, list.size());
// 防止越界
if (startIndex >= list.size()) {
subList = Collections.emptyList();
}
// 截取当前页数据
subList = list.subList(startIndex, endIndex);
}
// 防止越界
if (startIndex >= sourceList.size()) {
return Collections.emptyList();
}
// 截取分页数据
return sourceList.subList(startIndex, endIndex);
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(subList);
rspData.setTotal(list.size());
return rspData;
}
}

View File

@ -92,8 +92,6 @@ public class SysUser extends BaseEntity
/** 角色ID */
private Long roleId;
private String belongSite;
public SysUser()
{
@ -312,14 +310,6 @@ public class SysUser extends BaseEntity
this.roleId = roleId;
}
public String getBelongSite() {
return belongSite;
}
public void setBelongSite(String belongSite) {
this.belongSite = belongSite;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -342,7 +332,7 @@ public class SysUser extends BaseEntity
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("belongSite", getBelongSite())
.append("dept", getDept())
.toString();
}
}

View File

@ -1,111 +0,0 @@
package com.xzzn.common.core.modbus;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.ip.IpParameters;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Modbus连接管理器
* 使用长连接模式,维护连接缓存,复用已有连接
*/
@Component
public class Modbus4jConnectionManager {
private static final Logger logger = LoggerFactory.getLogger(Modbus4jConnectionManager.class);
private final ModbusFactory modbusFactory = new ModbusFactory();
private final Map<String, ModbusMaster> connectionCache = new ConcurrentHashMap<>();
/**
* 获取或创建连接(长连接模式)
*/
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
String key = buildConnectionKey(config);
ModbusMaster master = connectionCache.get(key);
if (master == null) {
synchronized (this) {
master = connectionCache.get(key);
if (master == null) {
master = createNewConnection(config);
connectionCache.put(key, master);
logger.info("创建新Modbus长连接: {}:{}", config.getHost(), config.getPort());
}
}
}
return master;
}
/**
* 归还连接(长连接模式,不关闭)
*/
public void returnMaster(DeviceConfig config, ModbusMaster master) {
}
/**
* 废弃连接(发生异常时关闭并移除)
*/
public void invalidateMaster(DeviceConfig config, ModbusMaster master) {
String key = buildConnectionKey(config);
connectionCache.remove(key);
destroyMaster(master, config);
logger.warn("废弃并移除Modbus连接: {}:{}", config.getHost(), config.getPort());
}
private ModbusMaster createNewConnection(DeviceConfig config) throws Exception {
IpParameters params = new IpParameters();
params.setHost(config.getHost());
params.setPort(config.getPort());
params.setEncapsulated(false);
ModbusMaster master = modbusFactory.createTcpMaster(params, true);
master.init();
return master;
}
private void destroyMaster(ModbusMaster master, DeviceConfig config) {
if (master != null) {
try {
master.destroy();
logger.debug("已关闭Modbus连接: {}:{}", config.getHost(), config.getPort());
} catch (Exception e) {
logger.warn("关闭Modbus连接异常: {}:{}", config.getHost(), config.getPort(), e);
}
}
}
private String buildConnectionKey(DeviceConfig config) {
return config.getHost() + ":" + config.getPort();
}
/**
* 关闭所有连接
*/
public void closeAllConnections() {
for (Map.Entry<String, ModbusMaster> entry : connectionCache.entrySet()) {
try {
if (entry.getValue() != null) {
entry.getValue().destroy();
}
} catch (Exception e) {
logger.warn("关闭Modbus连接异常: {}", entry.getKey(), e);
}
}
connectionCache.clear();
logger.info("已关闭所有Modbus连接");
}
}

View File

@ -1,486 +0,0 @@
package com.xzzn.common.core.modbus;
import com.alibaba.fastjson2.JSON;
import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.WriteCoilRequest;
import com.serotonin.modbus4j.msg.WriteCoilResponse;
import com.serotonin.modbus4j.msg.WriteCoilsRequest;
import com.serotonin.modbus4j.msg.WriteCoilsResponse;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import com.xzzn.common.core.modbus.domain.TagConfig;
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.ModBusType;
import com.xzzn.common.enums.RegisterType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import static com.xzzn.common.enums.RegisterType.COIL;
import static com.xzzn.common.enums.RegisterType.DISCRETE_INPUT;
@Service
public class ModbusProcessor {
private static final Logger logger = LoggerFactory.getLogger(ModbusProcessor.class);
@Value("${modbus.read-timeout:8000}")
private int readTimeout;
@Value("${modbus.write-timeout:5000}")
private int writeTimeout;
@Value("${modbus.read-retries:1}")
private int readRetries;
@Value("${modbus.write-retries:1}")
private int writeRetries;
@Autowired
private RedisCache redisCache;
@Autowired
private Modbus4jConnectionManager connectionManager;
public boolean writeDataToDevice(DeviceConfig config) {
logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
ModbusMaster master = null;
boolean result = false;
boolean hasError = false;
try {
master = connectionManager.borrowMaster(config);
master.setTimeout(writeTimeout);
master.setRetries(0);
result = writeTagValue(master, config, config.getWriteTags());
} catch (Exception e) {
logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e);
hasError = true;
}
finally {
if (master != null) {
if (hasError) {
// 发生异常时废弃连接,下次重新创建
connectionManager.invalidateMaster(config, master);
} else {
// 正常时归还连接
connectionManager.returnMaster(config, master);
}
}
}
return result;
}
public boolean writeDataToDeviceWithRetry(DeviceConfig config) {
logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
ModbusMaster master = null;
boolean result;
try {
master = connectionManager.borrowMaster(config);
master.setTimeout(writeTimeout); // 设置超时时间
master.setRetries(0);
// 使用重试装饰器
ModbusMaster finalMaster = master;
result = RetryableModbusOperation.executeWithRetry(() -> {
return writeTagValue(finalMaster, config, config.getWriteTags());
}, writeRetries); // 最大重试次数由配置控制
} catch (Exception e) {
logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e);
result = false;
} finally {
if (master != null) {
connectionManager.returnMaster(config, master);
}
}
return result;
}
public boolean writeTagValue(ModbusMaster master, DeviceConfig config, List<WriteTagConfig> tags) {
tags.forEach(tag -> {
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = convertAddress(tag.getAddress());
RegisterType registerType = type.get(firstDigit);
logger.info("Register type: {}, address: {}, firstDigit: {}", registerType, tag.getAddress(), firstDigit);
switch (registerType) {
case COIL: {
boolean result = writeCoilRequest(master, config.getSlaveId(), address, Boolean.parseBoolean(String.valueOf(tag.getValue())));
tag.setWrite(result);
break;
}
case HOLDING_REGISTER: {
Number value = Double.parseDouble(String.valueOf(tag.getValue()));
double doubleValue = value.doubleValue();
// 检查是否在16位有符号整数范围内
if (doubleValue < -32768 || doubleValue > 32767) {
logger.warn("Value {} out of range for 16-bit signed register at address {}", doubleValue, address);
}
boolean result = writeRegisterRequest(master, config.getSlaveId(), address, (int) doubleValue);
tag.setWrite(result);
break;
}
default:
logger.error("Unsupported register type: {}", registerType);
break;
}
});
List<WriteTagConfig> collect = tags.stream().filter(tag -> !Objects.equals(tag.isWrite(), true)).collect(Collectors.toList());
if (!collect.isEmpty()) {
return false;
}
return true;
}
public static boolean writeCoilRequest(ModbusMaster master, int slaveId, int address, boolean value) {
try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value);
WriteCoilResponse response = (WriteCoilResponse)master.send(request);
if (response.isException()) {
logger.info("Write coil failed: " + response.getExceptionMessage());
} else {
logger.info("Write coil successful");
return true;
}
} catch (Exception e) {
logger.error("Failed to write coil value '{}' to address '{}'", value, address, e);
}
return false;
}
public static void writeCoilsRequest(ModbusMaster master, int slaveId, int address, boolean[] values) {
try {
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, address, values);
WriteCoilsResponse response = (WriteCoilsResponse)master.send(request);
if (response.isException()) {
logger.info("Write coils failed: " + response.getExceptionMessage());
} else {
logger.info("Write coils successful");
}
} catch (Exception e) {
logger.error("Failed to write coils value '{}' to address '{}'", values, address, e);
}
}
public static boolean writeRegisterRequest(ModbusMaster master, int slaveId, int address, int value) {
try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
WriteRegisterResponse response = (WriteRegisterResponse)master.send(request);
if (response.isException()) {
logger.info("Write register failed: " + response.getExceptionMessage());
} else {
logger.info("Write register successful");
return true;
}
} catch (Exception e) {
logger.error("Failed to write register value '{}' to address '{}'", value, address, e);
}
return false;
}
public static void writeRegistersRequest(ModbusMaster master, int slaveId, int address, short[] values) {
try {
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, address, values);
WriteRegistersResponse response = (WriteRegistersResponse)master.send(request);
if (response.isException()) {
logger.info("Write registers failed: " + response.getExceptionMessage());
} else {
logger.info("Write registers successful");
}
} catch (Exception e) {
logger.error("Failed to write registers value '{}' to address '{}'", values, address, e);
}
}
public static void setCoilValue(ModbusMaster master, int slaveId, int address, int value) {
// 写入单个线圈(从站ID, 地址, 布尔值)
BaseLocator<Boolean> coilLocator = BaseLocator.coilStatus(slaveId, address);
try {
// 写入布尔值到线圈
master.setValue(coilLocator, value);
logger.info("set coil successful");
} catch (ModbusTransportException | ErrorResponseException e) {
logger.error("Failed to set coil value '{}' to address '{}'", value, address, e);
}
}
public static void setRegisterValue(ModbusMaster master, int slaveId, int address, int value) {
// 写入单个保持寄存器(从站, 地址, 16位整数)
BaseLocator<Number> holdingLocator = BaseLocator.holdingRegister(slaveId, address, DataType.TWO_BYTE_INT_SIGNED);
try {
// 写入整数值到保持寄存器
master.setValue(holdingLocator, value);
logger.info("set register successful");
} catch (ModbusTransportException | ErrorResponseException e) {
logger.error("Failed to set register value '{}' to address '{}'", value, address, e);
}
}
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
ModbusMaster master = connectionManager.borrowMaster(config);
// 设置了Modbus通信的超时时间为5000毫秒5秒。当主设备与从设备通信时若在5秒内未收到响应则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
master.setTimeout(readTimeout);
master.setRetries(readRetries);
return master;
}
public Map<String, Object> readDataFromDevice(DeviceConfig config, ModbusMaster master) {
Map<String, Object> deviceData = new HashMap<>();
boolean hasError = false;
try {
BatchResults<String> results = readTagValues(master, config.getSlaveId(), config.getTags());
for (TagConfig tag : config.getTags()) {
if (Objects.equals(tag.getDataType(), "FOUR_BYTE_FLOAT_DBCA")){
Object value = results.getValue(tag.getKey());
value = convertValueToFloat(value);
deviceData.put(tag.getKey(), value);
}else {
deviceData.put(tag.getKey(), results.getValue(tag.getKey()));
}
}
} catch (Exception e) {
logger.error("Failed read from devices '{}'", config.getDeviceName(), e);
hasError = true;
}
finally {
if (master != null) {
if (hasError) {
// 发生异常时废弃连接,下次重新创建
connectionManager.invalidateMaster(config, master);
} else {
// 正常时归还连接
connectionManager.returnMaster(config, master);
}
}
}
return deviceData;
}
private Object readTagValue(ModbusMaster master, int slaveId, TagConfig tag) throws Exception {
Object value;
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
Map<String, Integer> DATA_LENGTH = ModBusType.LENGTH;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = 0;
int addressLength = tag.getAddress().length();
int exp = (int) Math.pow(10, addressLength-1);
if (firstDigit != 0){
int digit = Integer.parseInt(tag.getAddress());
address = digit % (exp);
}else {
address = Integer.parseInt(tag.getAddress());
}
RegisterType registerType = type.get(firstDigit);
int dataLength = DATA_LENGTH.get(tag.getDataType());
// 增加配置校验和警告
if ((Objects.equals(registerType, COIL) || Objects.equals(registerType, DISCRETE_INPUT))) {
logger.warn("Configuration warning for tag '{}': ModBusType is {} but DataType is {}. DataType should be BOOLEAN. Proceeding with BOOLEAN read.",
tag.getKey(), registerType, tag.getDataType());
}
try {
switch (registerType) {
case COIL: {
BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, address);
value = master.getValue(loc);
logger.info("读取线圈{}成功: {}",tag.getAddress(), value);
break;
}
case DISCRETE_INPUT: {
BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, address);
value = master.getValue(loc);
logger.info("读取输入{}成功: {}",tag.getAddress(), value);
break;
}
case HOLDING_REGISTER: {
if (dataLength == 28){
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, 4);
value = master.getValue(locator);
//将 value 转换为二进制数据
value = convertValueToFloat(value);
}else{
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, dataLength);
value = master.getValue(locator);
}
logger.info("读取保持寄存器{}成功: {}",tag.getAddress(), value);
break;
}
case INPUT_REGISTER: {
BaseLocator<Number> locator = BaseLocator.inputRegister(slaveId, address, dataLength);
value= master.getValue(locator);
logger.info("读取输入寄存器{}成功: {}",tag.getAddress(), value);
break;
}
default:
logger.error("Unsupported register type: {}", registerType);
value = null;
break;
}
}catch (Exception e){
logger.error("Failed to read tag '{}'", tag.getKey(), e);
value = null;
}
return value;
}
private BatchResults<String> readTagValues(ModbusMaster master, int slaveId, List<TagConfig> tags) throws Exception {
try {
BatchResults<String> results = sendBatchRead(master, slaveId, tags);
logBatchResults(tags, results);
return results;
} catch (Exception e){
if (isTimeoutException(e)) {
logger.warn("批量读取超时尝试降级为单点读取slaveId: {}", slaveId);
BatchResults<String> fallback = new BatchResults<>();
for (TagConfig tag : tags) {
Object value = readTagValue(master, slaveId, tag);
fallback.addResult(tag.getKey(), value);
}
logBatchResults(tags, fallback);
return fallback;
}
logger.error("Failed to read master '{}'", slaveId, e);
throw new Exception(e);
}
}
private BatchResults<String> sendBatchRead(ModbusMaster master, int slaveId, List<TagConfig> tags) throws Exception {
BatchRead<String> batch = new BatchRead<>();
tags.forEach(tag -> {
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
Map<String, Integer> DATA_LENGTH = ModBusType.LENGTH;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = 0;
int addressLength = tag.getAddress().length();
int exp = (int) Math.pow(10, addressLength - 1);
if (firstDigit != 0) {
int digit = Integer.parseInt(tag.getAddress());
address = digit % (exp);
} else {
address = Integer.parseInt(tag.getAddress());
}
RegisterType registerType = type.get(firstDigit);
int dataLength = DATA_LENGTH.get(tag.getDataType());
switch (registerType) {
case COIL: {
BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, address);
batch.addLocator(tag.getKey(), loc);
break;
}
case DISCRETE_INPUT: {
BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, address);
batch.addLocator(tag.getKey(), loc);
break;
}
case HOLDING_REGISTER: {
if (dataLength == 28) {
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, 4);
batch.addLocator(tag.getKey(), locator);
} else {
BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, address, dataLength);
batch.addLocator(tag.getKey(), loc);
}
break;
}
case INPUT_REGISTER: {
BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, address, dataLength);
batch.addLocator(tag.getKey(), loc);
break;
}
}
});
return master.send(batch);
}
private void logBatchResults(List<TagConfig> tags, BatchResults<String> results) {
List<String> logInfoList = new ArrayList<>();
for (TagConfig tag : tags) {
StringBuilder logInfo = new StringBuilder();
logInfo.append(tag.getAddress());
if (tag.getBit() != null) {
logInfo.append("(").append(tag.getBit()).append("):");
} else {
logInfo.append(":");
}
logInfo.append(results.getValue(tag.getKey()));
logInfoList.add(logInfo.toString());
}
logger.info("批处理读取寄存器成功: {}", JSON.toJSONString(logInfoList));
}
private boolean isTimeoutException(Throwable e) {
Throwable current = e;
while (current != null) {
if (current instanceof com.serotonin.modbus4j.sero.messaging.TimeoutException) {
return true;
}
current = current.getCause();
}
return false;
}
public static float convertValueToFloat(Object value) {
if (!(value instanceof Number)) {
throw new IllegalArgumentException("Input must be a Number");
}
int intValue = ((Number) value).intValue();
String binaryData = Integer.toBinaryString(intValue);
// 补足32位二进制字符串
if (binaryData.length() < 32) {
binaryData = String.format("%32s", binaryData).replace(' ', '0');
}
// 分割为4个字节并重组为 dcba 格式
byte[] reorderedBytes = new byte[4];
for (int i = 0; i < 4; i++) {
int start = i * 8;
String byteStr = binaryData.substring(start, start + 8);
reorderedBytes[3 - i] = (byte) Integer.parseInt(byteStr, 2);
}
// 使用 ByteBuffer 提高可读性和安全性
return Float.intBitsToFloat(
java.nio.ByteBuffer.wrap(reorderedBytes).getInt()
);
}
/** 转换寄存器地址 */
public static int convertAddress(String address) {
if (StringUtils.isBlank(address)) {
return 0;
}
int firstDigit = Integer.parseInt(address.substring(0, 1));
int addressLength = address.length();
int exp = (int) Math.pow(10, addressLength-1);
if (firstDigit != 0){
int digit = Integer.parseInt(address);
return digit % (exp);
} else {
return Integer.parseInt(address);
}
}
}

View File

@ -1,58 +0,0 @@
package com.xzzn.common.core.modbus;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.ip.IpParameters;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
public class PooledModbusMasterFactory extends BasePooledObjectFactory<ModbusMaster> {
private final String host;
private final int port;
public PooledModbusMasterFactory(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public ModbusMaster create() throws Exception {
IpParameters params = new IpParameters();
params.setHost(this.host);
params.setPort(this.port);
params.setEncapsulated(false);
ModbusMaster master = new ModbusFactory().createTcpMaster(params, true);
master.init();
return master;
}
@Override
public PooledObject<ModbusMaster> wrap(ModbusMaster master) {
return new DefaultPooledObject<>(master);
}
@Override
public void destroyObject(PooledObject<ModbusMaster> p) throws Exception {
if (p.getObject() != null) {
p.getObject().destroy();
}
super.destroyObject(p);
}
@Override
public boolean validateObject(PooledObject<ModbusMaster> p) {
// testConnectivity() 方法在 modbus4j 中不存在。
// 一个真正的验证需要执行一次读操作,但这需要 slaveId而工厂是通用的不知道 slaveId。
// 因此,我们使用一个较弱的验证,只检查 master 对象是否已初始化。
// 这无法检测到被远程设备断开的连接,错误将在实际读取操作中被捕获。
if (p.getObject() == null) {
return false;
}
return p.getObject().isInitialized();
}
}

View File

@ -1,37 +0,0 @@
package com.xzzn.common.core.modbus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Modbus重试
*
*/
public class RetryableModbusOperation {
private static final Logger logger = LoggerFactory.getLogger(RetryableModbusOperation.class);
public interface ModbusOperation<T> {
T execute() throws Exception;
}
public static <T> T executeWithRetry(ModbusOperation<T> operation, int maxRetries) {
int retryCount = 0;
Exception lastException = null;
while (retryCount <= maxRetries) {
try {
return operation.execute();
} catch (Exception e) {
lastException = e;
retryCount++;
if (retryCount <= maxRetries) {
logger.info("Operation failed, retrying... (Attempt {})", retryCount);
}
}
}
logger.error("Max retries ({}) reached. Last error: {}", maxRetries,
lastException != null ? lastException.getMessage() : "Unknown");
throw new RuntimeException("Operation failed after " + maxRetries + " retries", lastException);
}
}

View File

@ -1,106 +0,0 @@
package com.xzzn.common.core.modbus.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "modbus")
public class ModbusProperties {
private PoolConfig pool = new PoolConfig();
private TimeoutConfig timeout = new TimeoutConfig();
public PoolConfig getPool() {
return pool;
}
public void setPool(PoolConfig pool) {
this.pool = pool;
}
public TimeoutConfig getTimeout() {
return timeout;
}
public void setTimeout(TimeoutConfig timeout) {
this.timeout = timeout;
}
public static class PoolConfig {
private int maxTotal = 20;
private int maxIdle = 10;
private int minIdle = 3;
private long maxWait = 5000;
private long timeBetweenEvictionRuns = 30000;
private long minEvictableIdleTime = 60000;
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public long getTimeBetweenEvictionRuns() {
return timeBetweenEvictionRuns;
}
public void setTimeBetweenEvictionRuns(long timeBetweenEvictionRuns) {
this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
}
public long getMinEvictableIdleTime() {
return minEvictableIdleTime;
}
public void setMinEvictableIdleTime(long minEvictableIdleTime) {
this.minEvictableIdleTime = minEvictableIdleTime;
}
}
public static class TimeoutConfig {
private int read = 10000;
private int write = 5000;
public int getRead() {
return read;
}
public void setRead(int read) {
this.read = read;
}
public int getWrite() {
return write;
}
public void setWrite(int write) {
this.write = write;
}
}
}

View File

@ -1,91 +0,0 @@
package com.xzzn.common.core.modbus.domain;
import java.util.List;
public class DeviceConfig {
private String deviceNumber;
private String deviceName;
private String host;
private int port;
private long time;
private int slaveId;
private boolean enabled;
private List<TagConfig> tags;
private List<WriteTagConfig> writeTags;
public String getDeviceNumber() {
return deviceNumber;
}
public void setDeviceNumber(String deviceNumber) {
this.deviceNumber = deviceNumber;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public int getSlaveId() {
return slaveId;
}
public void setSlaveId(int slaveId) {
this.slaveId = slaveId;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<TagConfig> getTags() {
return tags;
}
public void setTags(List<TagConfig> tags) {
this.tags = tags;
}
public List<WriteTagConfig> getWriteTags() {
return writeTags;
}
public void setWriteTags(List<WriteTagConfig> writeTags) {
this.writeTags = writeTags;
}
}

View File

@ -1,78 +0,0 @@
package com.xzzn.common.core.modbus.domain;
public class TagConfig {
private String key;
private String des;
private String address;
private String dataType;
private float a;
private float k;
private float b;
private Integer bit;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public float getA() {
return a;
}
public void setA(float a) {
this.a = a;
}
public float getK() {
return k;
}
public void setK(float k) {
this.k = k;
}
public float getB() {
return b;
}
public void setB(float b) {
this.b = b;
}
public Integer getBit() {
return bit;
}
public void setBit(Integer bit) {
this.bit = bit;
}
}

View File

@ -1,31 +0,0 @@
package com.xzzn.common.core.modbus.domain;
public class WriteTagConfig {
private Object value;
private String address;
private boolean isWrite;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isWrite() {
return isWrite;
}
public void setWrite(boolean write) {
isWrite = write;
}
}

View File

@ -7,8 +7,10 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
/**
@ -241,18 +243,6 @@ public class RedisCache
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 删除Hash中的多条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean deleteAllCacheMapValue(final String key, final Object[] hKey)
{
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 删除Hash中的某条数据
*
@ -265,18 +255,6 @@ public class RedisCache
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 批量往Hash中存入数据
*
* @param key Redis键
* @param value 值
*/
public <T> void setAllCacheMapValue(final String key, final Map<String, T> value)
{
redisTemplate.opsForHash().putAll(key, value);
}
/**
* 获得缓存的基本对象列表
*
@ -298,78 +276,4 @@ public class RedisCache
{
return redisTemplate.delete(key);
}
/**
* 批量缓存
* @param cacheMap
*/
public <T> void multiSet(final Map<String, String> cacheMap)
{
redisTemplate.opsForValue().multiSet(cacheMap);
}
/**
* 批量设置键值对,并为每个键设置相同的过期时间
* @param keyValueMap 键值对集合
* @param timeout 过期时间
* @param unit 时间单位
*/
public void multiSetWithExpire(Map<String, String> keyValueMap, long timeout, TimeUnit unit) {
if (keyValueMap.isEmpty()) {
return; // 空集合直接返回
}
// 使用Redis管道批量执行命令
redisTemplate.executePipelined(new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
// 循环处理每个键值对
for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// 1. 设置键值对
operations.opsForValue().set(key, value);
// 2. 设置过期时间
operations.expire(key, timeout, unit);
}
return null; // 管道操作无需返回值
}
});
}
/**
* 删除指定站点的所有历史测试数据缓存(最精准)
* @param testSiteId 测试数据所属的站点ID如"test-site-001"
*/
public void deleteTestCacheBySite(String testSiteId) {
System.out.println("开删除缓存redis" + testSiteId + "<UNK>");
if (testSiteId == null || testSiteId.isEmpty()) {
return;
}
// 构造键前缀测试站点ID开头的所有缓存键无论粒度和时间
String pattern = testSiteId + "_*";
deleteCacheByPattern(pattern);
}
/**
* 根据键前缀批量删除缓存(核心方法)
* @param pattern 键匹配模式支持Redis的通配符*表示任意字符,?表示单个字符)
*/
public void deleteCacheByPattern(String pattern) {
try {
// 1. 查找所有匹配的键注意keys命令在大数据量时可能阻塞Redis建议生产环境用scan
Set<String> keys = redisTemplate.keys(pattern);
if (keys == null || keys.isEmpty()) {
return;
}
// 2. 批量删除匹配的键
long deleteCount = redisTemplate.delete(keys);
System.out.println("删除缓存数据:" + deleteCount + "<UNK>");
} catch (Exception e) {
}
}
}

View File

@ -7,10 +7,8 @@ package com.xzzn.common.enums;
*/
public enum AmmeterCategory
{
CURRENT_FORWARD_ACTIVE("1", "当前正向有功电能"),
CURRENT_FORWARD_REACTIVE("2", "当前正向无功电能"),
CURRENT_REVERSE_ACTIVE("3", "当前反向有功电能"),
CURRENT_REVERSE_REACTIVE("4", "当前反向无功电能"),
CURRENT_COMB_ACTIVE("1", "当前组合有功电能"),
CURRENT_COMB_REACTIVE("2", "当前组合无功电能"),
A_POWER("3", "A相功率"),
B_POWER("4", "B相功率"),
C_POWER("5", "C相功率");

View File

@ -7,7 +7,7 @@ package com.xzzn.common.enums;
*/
public enum CommunicationStatus
{
OK("0", "正常"), SUSPEND("1", "通信中断") ,EXCEPTION("2", "异常");
OK("0", "正常"), SUSPEND("1", "通信中断") ,EXCEPTION("1", "异常");
private final String code;
private final String info;

View File

@ -1,42 +0,0 @@
package com.xzzn.common.enums;
/**
* 电量类型
*/
public enum CostType
{
PEAK("peak", ""),
HIGH("high", ""),
FLAT("flat", ""),
VALLEY("valley", ""),
;
private final String code;
private final String info;
CostType(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
public static CostType getEnumByCode(String code)
{
for (CostType costType : CostType.values()) {
if (costType.code.equals(code)) {
return costType;
}
}
return null;
}
}

View File

@ -1,10 +1,5 @@
package com.xzzn.common.enums;
import org.apache.xmlbeans.impl.common.NameUtil;
import java.util.HashMap;
import java.util.Map;
/**
* device-设备类别
*
@ -12,27 +7,21 @@ import java.util.Map;
*/
public enum DeviceCategory
{
PCS("PCS", "PCS设备", null),
BRANCH("BRANCH", "PCS分支设备", PCS),
STACK("STACK", "电池堆", null),
CLUSTER("CLUSTER", "电池簇", STACK),
BATTERY("BATTERY", "单体电池", CLUSTER),
AMMETER("AMMETER", "电表", null),
COOLING("COOLING", "", null),
DH("DH", "动环", null),
XF("XF", "消防", null),
BATTERY_GROUP("BATTERY_GROUP", "电池组", null),
EMS("EMS", "EMS设备", null),;
PCS("PCS", "PCS设备"),
BRANCH("BRANCH", "PCS分支设备"),
STACK("STACK", "电池堆"),
CLUSTER("CLUSTER", "电池簇"),
BATTERY("BATTERY", "单体电池"),
AMMETER("AMMETER", "电表"),
COOLING("COOLING", "液体");
private final String code;
private final String info;
private final DeviceCategory parentCategory;
DeviceCategory(String code, String info, DeviceCategory parentCategory)
DeviceCategory(String code, String info)
{
this.code = code;
this.info = info;
this.parentCategory = parentCategory;
}
public String getCode()
@ -44,43 +33,4 @@ public enum DeviceCategory
{
return info;
}
public DeviceCategory getParentCategory()
{
return parentCategory;
}
// 缓存info与code的映射优化查询效率
private static final Map<String, String> INFO_CODE_MAP = new HashMap<>();
// 静态块初始化缓存
static {
for (DeviceCategory category : DeviceCategory.values()) {
INFO_CODE_MAP.put(category.info, category.code);
}
}
// 通过info获取code的方法
public static String getCodeByInfo(String info) {
return INFO_CODE_MAP.get(info); // 从缓存中直接获取,效率高
}
// 通过code获取父类code
// 根据字符串编码查找对应的枚举
public static DeviceCategory fromCode(String code) {
for (DeviceCategory category : values()) {
if (category.code.equalsIgnoreCase(code)) { // 忽略大小写,增强兼容性
return category;
}
}
return null;
}
public static String getInfoByCode(String code) {
for (DeviceCategory category : DeviceCategory.values()) {
if (category.code.equals(code)) {
return category.info;
}
}
return null;
}
}

View File

@ -1,19 +1,18 @@
package com.xzzn.common.enums;
/**
* device-通信状态
* pcs-设备状态
*
* @author xzzn
*/
public enum DeviceRunningStatus
public enum DeviceStatus
{
OFFLINE("0", "离线"),
ONLINE("1", "在线");
ONLINE("0", "在线"), OFFLINE("1", "离线"), UNDER_REPAIR("2", "维修中");
private final String code;
private final String info;
DeviceRunningStatus(String code, String info)
DeviceStatus(String code, String info)
{
this.code = code;
this.info = info;
@ -28,5 +27,4 @@ public enum DeviceRunningStatus
{
return info;
}
}

View File

@ -1,55 +0,0 @@
package com.xzzn.common.enums;
import com.serotonin.modbus4j.code.DataType;
import java.util.HashMap;
import java.util.Map;
public class ModBusType {
public static final Map<Integer, RegisterType> REGISTER_TYPE = new HashMap<Integer, RegisterType>();
public static final Map<String, Integer> LENGTH = new HashMap<String, Integer>();
static {
REGISTER_TYPE.put(0, RegisterType.COIL);
REGISTER_TYPE.put(1, RegisterType.DISCRETE_INPUT);
REGISTER_TYPE.put(4, RegisterType.HOLDING_REGISTER);
REGISTER_TYPE.put(3, RegisterType.INPUT_REGISTER);
LENGTH.put("BINARY",DataType.BINARY);
LENGTH.put("TWO_BYTE_INT_UNSIGNED",DataType.TWO_BYTE_INT_UNSIGNED);
LENGTH.put("TWO_BYTE_INT_SIGNED",DataType.TWO_BYTE_INT_SIGNED);
LENGTH.put("TWO_BYTE_INT_UNSIGNED_SWAPPED",DataType.TWO_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("TWO_BYTE_INT_SIGNED_SWAPPED",DataType.TWO_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED",DataType.FOUR_BYTE_INT_UNSIGNED);
LENGTH.put("FOUR_BYTE_INT_SIGNED",DataType.FOUR_BYTE_INT_SIGNED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED_SWAPPED",DataType.FOUR_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_SIGNED_SWAPPED",DataType.FOUR_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED_SWAPPED_SWAPPED",DataType.FOUR_BYTE_INT_UNSIGNED_SWAPPED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED",DataType.FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED);
LENGTH.put("FOUR_BYTE_FLOAT",DataType.FOUR_BYTE_FLOAT);
LENGTH.put("FOUR_BYTE_FLOAT_SWAPPED",DataType.FOUR_BYTE_FLOAT_SWAPPED);
LENGTH.put("FOUR_BYTE_FLOAT_SWAPPED_INVERTED",DataType.FOUR_BYTE_FLOAT_SWAPPED_INVERTED);
LENGTH.put("EIGHT_BYTE_INT_UNSIGNED",DataType.EIGHT_BYTE_INT_UNSIGNED);
LENGTH.put("EIGHT_BYTE_INT_SIGNED",DataType.EIGHT_BYTE_INT_SIGNED);
LENGTH.put("EIGHT_BYTE_INT_UNSIGNED_SWAPPED",DataType.EIGHT_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("EIGHT_BYTE_INT_SIGNED_SWAPPED",DataType.EIGHT_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("EIGHT_BYTE_FLOAT",DataType.EIGHT_BYTE_FLOAT);
LENGTH.put("EIGHT_BYTE_FLOAT_SWAPPED",DataType.EIGHT_BYTE_FLOAT_SWAPPED);
LENGTH.put("TWO_BYTE_BCD",DataType.TWO_BYTE_BCD);
LENGTH.put("FOUR_BYTE_BCD",DataType.FOUR_BYTE_BCD);
LENGTH.put("FOUR_BYTE_BCD_SWAPPED",DataType.FOUR_BYTE_BCD_SWAPPED);
LENGTH.put("CHAR",DataType.CHAR);
LENGTH.put("VARCHAR",DataType.VARCHAR);
LENGTH.put("FOUR_BYTE_FLOAT_DBCA",28);
}
}

View File

@ -1,45 +0,0 @@
package com.xzzn.common.enums;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 设备点位类型
*/
public enum PointType
{
YES(1, ""),
NO(0, "");
private final Integer code;
private final String info;
private static final Map<Integer, String> CODE_NAME_MAP = new HashMap<>(PointType.values().length);
static {
Arrays.stream(PointType.values()).forEach(record -> {
CODE_NAME_MAP.put(record.code, record.info);
});
}
PointType(Integer code, String info)
{
this.code = code;
this.info = info;
}
public String getInfoByCode(Integer code) {
return CODE_NAME_MAP.get(code);
}
public Integer getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -1,30 +0,0 @@
package com.xzzn.common.enums;
/**
* 告警保护方案状态
*
* @author xzzn
*/
public enum ProtPlanStatus
{
STOP(0L, "未启用"), RUNNING(1L, "已启用");
private final Long code;
private final String info;
ProtPlanStatus(Long code, String info)
{
this.code = code;
this.info = info;
}
public Long getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -1,8 +0,0 @@
package com.xzzn.common.enums;
public enum RegisterType {
COIL,
DISCRETE_INPUT,
HOLDING_REGISTER,
INPUT_REGISTER
}

View File

@ -1,67 +0,0 @@
package com.xzzn.common.enums;
/**
*
*/
public enum SiteDevice
{
/**
* 电池堆
*/
BMSD,
/**
* 电池簇
*/
BMSC,
/**
* PCS设备
*/
PCS,
/**
* 电表-总表
*/
LOAD,
/**
* 电表-光伏电表
*/
METEGF,
/**
* 电表-储能电表
*/
METE,
/**
* 电表-储能电表
*/
METE0,
/**
* 动环
*/
donghuan,
/**
* 动环
*/
DH,
/**
* 消防
*/
XF,
/**
* 中水冷却
*/
ZSLQ,
/**
* EMS
*/
EMS
}

View File

@ -1,31 +0,0 @@
package com.xzzn.common.enums;
/**
* device-设备类型
*
* @author xzzn
*/
public enum SiteEnum
{
DDS("021_DDS_01", "电动所内部"), FX("021_FXX_01", "奉贤西部污水处理厂");
private final String code;
private final String info;
SiteEnum(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -1,32 +0,0 @@
package com.xzzn.common.enums;
/**
* SOC限制 (%) 1 = 开0 = 关
*
* @author xzzn
*/
public enum SocLimit
{
OFF(0, ""),
ON(1, ""),
;
private final Integer code;
private final String info;
SocLimit(Integer code, String info)
{
this.code = code;
this.info = info;
}
public Integer getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -7,7 +7,7 @@ package com.xzzn.common.enums;
*/
public enum StrategyStatus
{
NOT_ENABLED("0", "未启用"), RUNNING("1", "已运行"),SUSPENDED("2", "已暂停"), DISABLE("3", "禁用"),DELETE("4", "删除");
NOT_ENABLED("0", "未启用"), RUNNING("1", "已运行"),SUSPENDED("2", "已暂停"), DISABLE("1", "禁用"),DELETE("2", "删除");
private final String code;
private final String info;

View File

@ -1,30 +0,0 @@
package com.xzzn.common.enums;
/**
* ticket - 工单状态
*
* @author xzzn
*/
public enum TicketStatus
{
WAITING("1", "待处理"), PROCESSING("2", "处理中"),DONE("3", "已处理");
private final String code;
private final String info;
TicketStatus(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -1,39 +0,0 @@
package com.xzzn.common.enums;
/**
* MQTT主题处理类型未知类型
*/
public enum TopicHandleType {
DEVICE("DEVICE", "设备数据"),
DEVICE_ALARM("DEVICE_ALARM", "设备告警数据"),
STRATEGY("STRATEGY", "策略数据"),
SYSTEM("SYSTEM", "系统数据"),
;
private final String code;
private final String info;
TopicHandleType(String code, String info) {
this.code = code;
this.info = info;
}
public String getName() {
return code;
}
public String getInfo() {
return info;
}
// 根据名称查找枚举
public static TopicHandleType getEnumByCode(String code) {
for (TopicHandleType type : values()) {
if (type.getName().equals(code)) {
return type;
}
}
// 默认返回SYSTEM
return SYSTEM;
}
}

View File

@ -7,7 +7,7 @@ package com.xzzn.common.enums;
*/
public enum WorkStatus
{
NORMAL("0", "运行"), STOP("1", "停机"), ABNORMAL("2", "故障");
NORMAL("0", "正常"), ABNORMAL("1", "异常"), STOP("2", "停止");
private final String code;
private final String info;

View File

@ -1,33 +0,0 @@
package com.xzzn.common.enums;
public enum YesOrNo
{
YES(1, "", "Y"),
NO(0, "", "N");
private final Integer code;
private final String info;
private final String value;
YesOrNo(Integer code, String info, String value)
{
this.code = code;
this.info = info;
this.value = value;
}
public Integer getCode()
{
return code;
}
public String getInfo()
{
return info;
}
public String getValue()
{
return value;
}
}

View File

@ -1,39 +0,0 @@
package com.xzzn.common.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DataUtils {
private static final Logger log = LoggerFactory.getLogger(DataUtils.class);
public static String getJSONFromFile(InputStream inputStream) {
BufferedReader bufferReader = null;
StringBuffer stringBuffer = new StringBuffer();
try {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
bufferReader = new BufferedReader(inputStreamReader);
stringBuffer = new StringBuffer();
String lineData = null;
while ((lineData = bufferReader.readLine()) != null) {
stringBuffer.append(lineData);
}
} catch (Exception e) {
log.warn("getJSONFromFile error", e);
} finally {
if (null != bufferReader) {
try {
bufferReader.close();
inputStream.close();
} catch (Exception e) {
log.warn("getJSONFromFile error", e);
}
}
}
return stringBuffer.toString();
}
}

View File

@ -8,14 +8,9 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.LogFactory;
/**
* 时间工具类
@ -24,8 +19,6 @@ import org.apache.commons.logging.LogFactory;
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
private static final org.apache.commons.logging.Log log = LogFactory.getLog(DateUtils.class);
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
@ -36,13 +29,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static String YYYYMMDD = "yyyyMMdd";
public static String YYYY_MM_DD_HH_MM_00 = "yyyy-MM-dd HH:mm:00";
private static final DateTimeFormatter DAY_INPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter MIN_HOUR_INPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static String[] parsePatterns = {
"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",
@ -159,14 +145,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/**
* 计算相差分钟
*/
public static int differentMinutesByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 60)));
}
/**
* 计算时间差
*
@ -222,247 +200,4 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
long date = calendar.get(Calendar.DAY_OF_MONTH); // 月份从0开始所以要加1
return date;
}
// LocalDateTime 转 Date带时区
public static Date convertToDate(LocalDateTime localDateTime) {
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
}
/**
* 获取昨天的日期格式为yyyy-MM-dd 23:59:59
* @return 昨天的日期字符串
*/
public static String getYesterdayDate() {
// 获取今天的日期
LocalDate today = LocalDate.now();
// 减去一天得到昨天
LocalDate yesterday = today.minusDays(1);
// 将日期转换为LocalDateTime并设置时间为23:59:59
LocalDateTime yesterdayEndTime = yesterday.atTime(23, 59, 59);
// 定义日期格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
// 格式化并返回
return yesterdayEndTime.format(formatter);
}
/**
* 校验传入日期是否今天
* @param dataDate
* @return
*/
public static boolean checkIsToday(String dataDate) {
boolean flag = false;
Calendar calendar = Calendar.getInstance();
int todayMonth = calendar.get(Calendar.MONTH) + 1;
int todayDay = calendar.get(Calendar.DAY_OF_MONTH);
if (StringUtils.isNotEmpty(dataDate)){
String[] pcsDateArray = dataDate.split("-");
if (todayMonth == Integer.parseInt(pcsDateArray[1]) &&
todayDay == Integer.parseInt(pcsDateArray[2])) {
flag = true;
}
}
return flag;
}
/**
* 将时间转换为月份YYYY-MM
*/
public static String formatMonth(LocalDateTime time) {
return time.format(DateTimeFormatter.ofPattern("yyyy-MM"));
}
/**
* 增加 LocalDateTime ==> String
*/
public static String convertToString(LocalDateTime time) {
return time.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
}
/**
* 将输入时间调整到下一分钟的整点秒数强制为00
* 例如2026-09-03 18:34:49 -> 2026-09-03 18:35:00
* @param timeStr 输入时间字符串支持yyyy-MM-dd HH:mm:ss格式
* @return 调整后的时间字符串yyyy-MM-dd HH:mm:00
* @throws ParseException 时间格式错误时抛出
*/
public static String adjustToNextMinute(String timeStr) throws ParseException {
// 1. 解析原始时间(使用包含秒数的格式)
SimpleDateFormat fullFormat = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
Date originalDate = fullFormat.parse(timeStr);
// 2. 使用Calendar调整时间
Calendar cal = Calendar.getInstance();
cal.setTime(originalDate);
// 3. 如果当前秒数大于0自动进1分钟否则保持当前分钟
if (cal.get(Calendar.SECOND) > 0) {
cal.add(Calendar.MINUTE, 1); // 分钟+1
}
// 4. 强制设置秒数和毫秒为0
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// 5. 格式化为目标字符串
return new SimpleDateFormat(YYYY_MM_DD_HH_MM_00).format(cal.getTime());
}
/**
* 将"yyyy-MM-dd"字符串转换为Date类型的"yyyy-MM-dd 23:59:59"
*/
public static Date adjustToEndOfDay(String dateStr) {
// 1. 解析字符串为LocalDate仅日期
LocalDate localDate = LocalDate.parse(dateStr, DAY_INPUT_FORMATTER);
// 2. 补充时间为23:59:59转换为LocalDateTime
LocalDateTime localDateTime = localDate.atTime(23, 59, 59);
// 3. 转换为Date类型兼容旧API
return Date.from(
localDateTime.atZone(TimeZone.getDefault().toZoneId()) // 适配系统时区
.toInstant()
);
}
/**
* 将 "yyyy-MM-dd HH:mm:ss" 字符串转换为Date类型的"yyyy-MM-dd HH:00:00"
*/
public static Date adjustToStartOfHour(String inputTime) {
// 1. 解析输入字符串为LocalDateTime包含日期和小时、分钟
LocalDateTime inputLdt = LocalDateTime.parse(inputTime, MIN_HOUR_INPUT_FORMATTER);
// 2. 调整分钟为00秒为00保留日期和小时不变
LocalDateTime adjustedLdt = inputLdt
.withMinute(00) // 强制设为00分
.withSecond(00); // 强制设为00秒
// 3. 转换为Date类型适配旧API
return Date.from(
adjustedLdt.atZone(TimeZone.getDefault().toZoneId()) // 适配系统时区
.toInstant()
);
}
/**
* 将 "yyyy-MM-dd HH:mm:ss" 字符串转换为Date类型的"yyyy-MM-dd HH:mm:00"
*/
public static Date adjustToStartOfMinutes(String inputTime) {
// 1. 解析输入字符串为LocalDateTime包含日期和小时、分钟
LocalDateTime inputLdt = LocalDateTime.parse(inputTime, MIN_HOUR_INPUT_FORMATTER);
// 2. 调整分钟为00秒为00保留日期和小时不变
LocalDateTime adjustedLdt = inputLdt
.withSecond(00); // 强制设为00秒
// 3. 转换为Date类型适配旧API
return Date.from(
adjustedLdt.atZone(TimeZone.getDefault().toZoneId()) // 适配系统时区
.toInstant()
);
}
/**
* 将时间转换为月份YYYY-MM-DD HH:mm:00
*/
public static Date timeConvertToDate(LocalDateTime time) {
String dateStr = convertToString(time);
return dateTime(YYYY_MM_DD_HH_MM_SS,dateStr);
}
/**
* 增加 Date ==> LocalDateTime
*/
public static LocalDateTime toLocalDateTime(Date date)
{
if (date == null) {
return null;
}
// 1. Date → LocalDateTime保留原始时间
LocalDateTime dateTime = date.toInstant()
.atZone(TimeZone.getDefault().toZoneId()) // 关联时区
.toLocalDateTime();
return dateTime;
}
// 时间戳转时间
public static Date convertUpdateTime(Long updateTime) {
if (updateTime == null) {
return null;
}
// 兼容10位秒级和13位毫秒级
int length = String.valueOf(updateTime).length();
if (length == 10) { // 10位秒级 -> 转换为毫秒级
updateTime *= 1000;
} else if (length != 13) { // 既不是10位也不是13位视为非法
System.err.println("时间戳格式错误必须是10位(秒)或13位(毫秒)");
return null;
}
// 3. 转换为Date
return new Date(updateTime);
}
/**
* 获取昨天的日期格式为yyyy-MM-dd
* @return 昨天的日期字符串
*/
public static String getYesterdayDayString() {
// 获取今天的日期
LocalDate today = LocalDate.now();
// 减去一天得到昨天
LocalDate yesterday = today.minusDays(1);
// 定义日期格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
// 格式化并返回
return yesterday.format(formatter);
}
/**
* 获取日期的开始时间
* @param dateString 格式为yyyy-MM-dd的日期字符串
* @return 日期的开始时间字符串
*/
public static String getDayBeginString(String dateString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
// 解析日期字符串
LocalDate date = LocalDate.parse(dateString, formatter);
// 创建时间段的开始时间 00:00:00
LocalDateTime startTime = date.atTime(LocalTime.MIN);
return convertToString(startTime);
} catch (DateTimeParseException e) {
log.info("Error parsing date: " + e.getMessage());
}
return dateString + " 00:00:00";
}
/**
* 获取日期的结束时间
* @param dateString 格式为yyyy-MM-dd的日期字符串
* @return 日期的结束时间字符串
*/
public static String getDayEndString(String dateString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
// 解析日期字符串
LocalDate date = LocalDate.parse(dateString, formatter);
// 创建时间段的结束时间 23:59:59
LocalDateTime endTime = date.atTime(LocalTime.MAX);
return convertToString(endTime);
} catch (DateTimeParseException e) {
log.info("Error parsing date: " + e.getMessage());
}
return dateString + " 23:59:59";
}
}

View File

@ -1,44 +0,0 @@
package com.xzzn.common.utils;
import java.util.Map;
public class MapUtils {
/**
* 从Map中获取值并转为Integer适配tinyint字段
* @param map 数据源Map
* @param key 字段名
* @return 转换后的Integer默认返回0可根据业务调整默认值
*/
public static Integer getInteger(Map<String, Object> map, String key) {
// 1. 处理Map为null或key不存在的情况
if (map == null || !map.containsKey(key)) {
return 0;
}
// 2. 获取原始值
Object value = map.get(key);
if (value == null) {
return 0;
}
// 3. 转换为Integer处理常见类型
if (value instanceof Integer) {
return (Integer) value;
} else if (value instanceof Long) {
// 若Map中存的是Long如JSON解析时数字默认转为Long
return ((Long) value).intValue();
} else if (value instanceof String) {
// 若值是字符串类型(如"1"
try {
return Integer.parseInt((String) value);
} catch (NumberFormatException e) {
// 字符串无法转数字,返回默认值
return 0;
}
} else if (value instanceof Boolean) {
// 特殊情况布尔值转整数true→1false→0
return (Boolean) value ? 1 : 0;
} else {
// 其他不支持的类型,返回默认值
return 0;
}
}
}

View File

@ -751,17 +751,4 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
}
return result;
}
// 补全三位数字(返回字符串)
public static String fillThreeDigits(String value) {
if (value == null || value.trim().isEmpty()) {
return "000";
}
try {
int num = Integer.parseInt(value.trim());
return String.format("%03d", num);
} catch (NumberFormatException e) {
return value;
}
}
}

View File

@ -50,7 +50,11 @@
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<!-- 轮询 -->
<dependency>
<groupId>net.wimpi</groupId>
<artifactId>j2mod</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>

View File

@ -1,97 +0,0 @@
package com.xzzn.framework.aspectj;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsDeviceChangeLog;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.UUID;
/**
* 设备运行状态变更日志同步
* 本地 - 云端
*/
@Aspect
@Component
public class DeviceChangeLogAspect {
private static final Log logger = LogFactory.getLog(DeviceChangeLogAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "DEVICE_CHANGE_LOG_UP";
private static final String TABLE_NAME = "ems_device_change_log";
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
// 定义切点拦截策略相关表的Mapper方法
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsDeviceChangeLogMapper.insertEmsDeviceChangeLog(..)) && args(insertEntity)) ")
public void insertPointCut(EmsDeviceChangeLog insertEntity) {
logger.info("【新增设备运行状态变更日志】DeviceChangeLogAspect 实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsDeviceChangeLog insertEntity, Integer result) {
logger.info("【新增设备运行状态变更日志下发数据切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String operateType = "INSERT";
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,siteId);
try {
// 数据转换
String content = objectMapper.writeValueAsString(insertEntity);
message.setContent(content);
// mqtt同步到云端
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject(siteId);
message.setTarget("CLOUD");
return message;
}
}

View File

@ -1,104 +0,0 @@
package com.xzzn.framework.aspectj;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsAlarmRecords;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.UUID;
/**
* 本地保护告警信息同步云端
* 本地 - 云端
* @author xzzn
*/
@Aspect
@Component
public class FaultPlanAlarmAspect
{
private static final Log logger = LogFactory.getLog(FaultPlanAlarmAspect.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private MqttPublisher mqttPublisher;
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
private static final String MQTT_TOPIC = "FAULT_ALARM_RECORD_UP";
private static final String TABLE_NAME = "ems_alarm_records";
// 切入点:拦截所有添加了@SyncAfterInsert注解的方法
@Pointcut("@annotation(com.xzzn.common.annotation.SyncAfterInsert)")
public void syncInsertPointcut() {}
// 方法执行成功后同步数据
@AfterReturning(pointcut = "syncInsertPointcut()", returning = "result")
public void afterInsert(JoinPoint joinPoint, Integer result) {
logger.info("【新增保护策略告警数据切面进入成功】");
if (result == 0) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 获取参数中的EmsAlarmRecords对象
Object[] args = joinPoint.getArgs();
EmsAlarmRecords alarmRecords = null;
for (Object arg : args) {
if (arg instanceof EmsAlarmRecords) {
alarmRecords = (EmsAlarmRecords) arg;
break;
}
}
if (alarmRecords == null) {
return;
}
// 构建日志同步消息
MqttSyncLog message = createMessageObject("INSERT", alarmRecords.getSiteId());
try {
// 同步内容
String content = objectMapper.writeValueAsString(alarmRecords);
message.setContent(content);
// 发布到MQTT主题-同步到云端
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject(siteId);
message.setTarget("CLOUD");
return message;
}
}

View File

@ -1,98 +0,0 @@
package com.xzzn.framework.aspectj;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsFaultIssueLog;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 保护告警方案下发日志同步
* 本地 - 云端
*/
@Aspect
@Component
public class FaultPlanIssueAspect {
private static final Log logger = LogFactory.getLog(FaultPlanIssueAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "FAULT_PLAN_ISSUE_UP";
private static final String TABLE_NAME = "ems_fault_issue_log";
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
// 定义切点拦截策略相关表的Mapper方法
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultIssueLogMapper.insertEmsFaultIssueLog(..)) && args(insertEntity)) ")
public void insertPointCut(EmsFaultIssueLog insertEntity) {
logger.info("【新增保护告警策略下发数据】FaultPlanIssueAspect 实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsFaultIssueLog insertEntity, Integer result) {
logger.info("【新增保护告警策略下发数据切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String operateType = "INSERT";
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,siteId);
try {
// 数据转换
String content = objectMapper.writeValueAsString(insertEntity);
message.setContent(content);
// mqtt同步到云端
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject(siteId);
message.setTarget("CLOUD");
return message;
}
}

View File

@ -1,277 +0,0 @@
package com.xzzn.framework.aspectj;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 设备保护告警方案同步
* 云端 - 本地
*/
@Aspect
@Component
public class FaultProtPlanAspect {
private static final Log logger = LogFactory.getLog(FaultProtPlanAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "FAULT_PROTECTION_PLAN_UP";
private static final String TABLE_NAME = "ems_fault_protection_plan";
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;
// 用ThreadLocal暂存删除前的对象
private ThreadLocal<EmsFaultProtectionPlan> beforeDeleteThreadLocal = new ThreadLocal<>();
@Before("execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.deleteEmsFaultProtectionPlanByIds(..)) && args(ids)")
public void beforeDelete(JoinPoint joinPoint, Long[] ids) {
// 获取删除的id
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
Long[] id = (Long[]) args[0];
// 查询删除前的数据
EmsFaultProtectionPlan faultInfo = emsFaultProtectionPlanMapper.selectEmsFaultProtectionPlanById(id[0]);
beforeDeleteThreadLocal.set(faultInfo); // 暂存
}
// 定义切点拦截策略相关表的Mapper方法
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.insertEmsFaultProtectionPlan(..)) && args(insertEntity)) ")
public void insertPointCut(EmsFaultProtectionPlan insertEntity) {
logger.info("【新增设备保护告警】FaultProtPlanAspect 实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(..)) && args(updateEntity)) ")
public void updatePointCut(EmsFaultProtectionPlan updateEntity) {
logger.info("【更新设备保护告警】FaultProtPlanAspect 实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.deleteEmsFaultProtectionPlanByIds(..)) && args(ids)) ")
public void deletePointCut(Long[] ids) {
logger.info("【删除设备保护告警】FaultProtPlanAspect 实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsFaultProtectionPlan insertEntity, Integer result) {
logger.info("【新增设备保护告警切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,siteId);
try {
// 数据转换
String content = convertEntityToJson(insertEntity);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
@AfterReturning(pointcut = "updatePointCut(updateEntity)", returning = "result")
public void afterUpdate(JoinPoint joinPoint, EmsFaultProtectionPlan updateEntity, Integer result) {
logger.info("【更新设备保护告警切面进入成功】");
if (result == 0 || updateEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = updateEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,siteId);
try {
// 数据转换
String content = convertEntityToJson(updateEntity);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
@AfterReturning(pointcut = "deletePointCut(id)", returning = "result")
public void afterDelete(JoinPoint joinPoint, Long[] id, Integer result) {
logger.info("【删除设备保护告警切面进入成功】");
if (result == 0 || id == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
// 从ThreadLocal中获取删除前的对象
EmsFaultProtectionPlan faultInfo = beforeDeleteThreadLocal.get();
if (faultInfo == null) {
return;
}
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,faultInfo.getSiteId());
try {
// 数据转换
String content = convertEntityToJson(faultInfo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject("CLOUD");
message.setTarget(siteId);
return message;
}
// 从方法名判断操作类型示例insert→INSERTupdate→UPDATEdelete→DELETE
private String getOperateType(String methodName) {
if (methodName.startsWith("insert")) return "INSERT";
if (methodName.startsWith("stop")) return "STOP";
if (methodName.startsWith("update") || methodName.startsWith("stop")) return "UPDATE";
if (methodName.startsWith("delete")) return "DELETE";
return "UNKNOWN";
}
// 从方法参数提取数据示例若参数是实体类转成Map
private Map<String, Object> extractDataFromParams(Object[] args) {
// 实际需反射获取实体类的字段和值如id、name等
Map<String, Object> data = new HashMap<>();
if (args == null || args.length == 0) {
return data;
}
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg == null) {
continue; // 跳过null参数
}
// 处理基本类型/包装类/字符串直接作为值存入key为"param0"、"param1"等)
if (isBasicType(arg.getClass())) {
String key = "param" + i; // 基本类型参数用"param0"、"param1"作为key
data.put(key, arg);
} else {
Map<String, Object> beanMap = beanToMap(arg);
data.putAll(beanMap); // 合并实体类的字段到结果Map
}
}
return data;
}
/**
* 判断是否为基本类型或包装类或字符串
*/
private boolean isBasicType(Class<?> clazz) {
return clazz.isPrimitive() // 基本类型int、long、boolean等
|| clazz == String.class // 字符串
|| Number.class.isAssignableFrom(clazz) // 数字包装类Integer、Long等
|| clazz == Boolean.class; // 布尔包装类
}
/**
* 将实体类转换为Map字段名为key字段值为value
*/
private Map<String, Object> beanToMap(Object bean) {
Map<String, Object> map = new HashMap<>();
if (bean == null) {
return map;
}
// 方式1使用BeanMap简洁高效
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key.toString(), beanMap.get(key));
}
return map;
}
// 在方法中转换
public String convertEntityToJson(EmsFaultProtectionPlan insertEntity) throws Exception {
if (insertEntity == null) {
return null; // 空对象返回空JSON
}
// 将实体类转换为JSON字符串
return objectMapper.writeValueAsString(insertEntity);
}
}

View File

@ -1,272 +0,0 @@
package com.xzzn.framework.aspectj;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsStrategyRunning;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.domain.vo.StrategyRunningVo;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
/**
* 策略运行切面同步
* 云端 - 本地
*/
@Aspect
@Component
public class StrategyRunningSyncAspect {
private static final Logger logger = LoggerFactory.getLogger(StrategyRunningSyncAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "EMS_STRATEGY_UP";
private static final String TABLE_NAME = "ems_strategy_running";
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private EmsStrategyRunningMapper emsStrategyRunningMapper;
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyRunningMapper.stopEmsStrategyRunning(..)) && args(id)) ")
public void stopPointCut(Long id) {
logger.info("【停止策略切面】StrategyAspect 被实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyRunningMapper.insertEmsStrategyRunning(..)) && args(insertEntity)) ")
public void insertPointCut(EmsStrategyRunning insertEntity) {
logger.info("【新增策略切面】StrategyAspect 被实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyRunningMapper.updateEmsStrategyRunning(..)) && args(updateEntity)) ")
public void updatePointCut(EmsStrategyRunning updateEntity) {
logger.info("【更新策略切面】StrategyAspect 被实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "updatePointCut(updateEntity)", returning = "result")
public void afterUpdate(JoinPoint joinPoint, EmsStrategyRunning updateEntity, Integer result) {
logger.info("【更新策略切面进入成功】");
if (result == 0 || updateEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = updateEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType,siteId);
try {
// 数据转换
List<StrategyRunningVo> runningVos = emsStrategyRunningMapper.getRunningList(siteId);
if (runningVos == null || runningVos.size() == 0) {
return;
}
StrategyRunningVo runningVo = runningVos.get(0);
String content = objectMapper.writeValueAsString(runningVo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsStrategyRunning insertEntity, Integer result) {
logger.info("【新增策略切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 数据转换
List<StrategyRunningVo> runningVos = emsStrategyRunningMapper.getRunningList(siteId);
if (runningVos == null || runningVos.size() == 0) {
return;
}
StrategyRunningVo runningVo = runningVos.get(0);
String content = objectMapper.writeValueAsString(runningVo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
@AfterReturning(pointcut = "stopPointCut(id)", returning = "result")
public void afterStop(JoinPoint joinPoint, Long id, Integer result) {
logger.info("【停止策略切面进入成功】");
if (result == 0 || id == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
EmsStrategyRunning emsStrategyRunning = emsStrategyRunningMapper.selectEmsStrategyRunningById(id);
String siteId = emsStrategyRunning==null ? null : emsStrategyRunning.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 数据转换
Map<String, Object> idMap = new HashMap<>();
idMap.put("id", id); // 手动将参数值映射到"id"字段
String content = JSON.toJSONString(idMap);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject("CLOUD");
message.setTarget(siteId);
return message;
}
// 从方法名判断操作类型示例insert→INSERTupdate→UPDATEdelete→DELETE
private String getOperateType(String methodName) {
if (methodName.startsWith("insert")) return "INSERT";
if (methodName.startsWith("stop")) return "STOP";
if (methodName.startsWith("update") || methodName.startsWith("stop")) return "UPDATE";
if (methodName.startsWith("delete")) return "DELETE";
return "UNKNOWN";
}
// 从方法参数提取数据示例若参数是实体类转成Map
private Map<String, Object> extractDataFromParams(Object[] args) {
// 实际需反射获取实体类的字段和值如id、name等
Map<String, Object> data = new HashMap<>();
if (args == null || args.length == 0) {
return data;
}
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg == null) {
continue; // 跳过null参数
}
// 处理基本类型/包装类/字符串直接作为值存入key为"param0"、"param1"等)
if (isBasicType(arg.getClass())) {
String key = "param" + i; // 基本类型参数用"param0"、"param1"作为key
data.put(key, arg);
} else {
Map<String, Object> beanMap = beanToMap(arg);
data.putAll(beanMap); // 合并实体类的字段到结果Map
}
}
return data;
}
/**
* 判断是否为基本类型或包装类或字符串
*/
private boolean isBasicType(Class<?> clazz) {
return clazz.isPrimitive() // 基本类型int、long、boolean等
|| clazz == String.class // 字符串
|| Number.class.isAssignableFrom(clazz) // 数字包装类Integer、Long等
|| clazz == Boolean.class; // 布尔包装类
}
/**
* 将实体类转换为Map字段名为key字段值为value
*/
private Map<String, Object> beanToMap(Object bean) {
Map<String, Object> map = new HashMap<>();
if (bean == null) {
return map;
}
// 方式1使用BeanMap简洁高效
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key.toString(), beanMap.get(key));
}
return map;
}
// 在方法中转换
public String convertEntityToJson(EmsStrategyRunning insertEntity) throws Exception {
if (insertEntity == null) {
return null; // 空对象返回空JSON
}
// 将实体类转换为JSON字符串
return objectMapper.writeValueAsString(insertEntity);
}
}

View File

@ -1,261 +0,0 @@
package com.xzzn.framework.aspectj;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.common.utils.bean.BeanUtils;
import com.xzzn.ems.domain.EmsStrategy;
import com.xzzn.ems.domain.EmsStrategyRunning;
import com.xzzn.ems.domain.EmsStrategyTemp;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.domain.vo.SyncStrategyTempVo;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.EmsStrategyMapper;
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
/**
* 策略模板数据同步
* 云端 - 本地
*/
@Aspect
@Component
public class StrategyTempSyncAspect {
private static final Logger logger = LoggerFactory.getLogger(StrategyTempSyncAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "EMS_STRATEGY_UP";
private static final String TABLE_NAME = "ems_strategy_temp";
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private EmsStrategyMapper emsStrategyMapper;
@Autowired
private EmsStrategyTempMapper emsStrategyTempMapper;
// 用ThreadLocal暂存删除前的对象
private ThreadLocal<EmsStrategyTemp> beforeDeleteThreadLocal = new ThreadLocal<>();
@Before("execution(* com.xzzn.ems.mapper.EmsStrategyTempMapper.deleteTempByTempId(..)) && args(templateId)")
public void beforeDelete(JoinPoint joinPoint, String templateId) {
// 查询删除前的数据-仅存一获取siteId
List<EmsStrategyTemp> tempList = emsStrategyTempMapper.selectStrategyTempByTempId(templateId);
if (tempList != null && tempList.size() > 0) {
beforeDeleteThreadLocal.set(tempList.get(0)); // 暂存
}
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyTempMapper.deleteTempByTempId(..)) && args(templateId)) ")
public void deletePointCut(String templateId) {
logger.info("【删除策略模版切面】StrategyTempSyncAspect 被实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyTempMapper.insertEmsStrategyTemp(..)) && args(insertEntity)) ")
public void insertPointCut(EmsStrategyTemp insertEntity) {
logger.info("【新增策略模版切面】StrategyTempSyncAspect 被实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsStrategyTemp insertEntity, Integer result) {
logger.info("【新增策略切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 校验策略id是否存在
Long strategyId = insertEntity.getStrategyId();
if (strategyId == null) {
return;
}
// 数据转换
SyncStrategyTempVo tempVo = convertEntity(insertEntity);
String content = JSON.toJSONString(tempVo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
private SyncStrategyTempVo convertEntity(EmsStrategyTemp insertEntity) {
SyncStrategyTempVo tempVo = new SyncStrategyTempVo();
BeanUtils.copyProperties(insertEntity, tempVo);
EmsStrategy strategy = emsStrategyMapper.selectEmsStrategyById(insertEntity.getStrategyId());
if (strategy != null) {
tempVo.setStrategyName(strategy.getStrategyName());
tempVo.setStrategyType(strategy.getStrategyType());
}
return tempVo;
}
@AfterReturning(pointcut = "deletePointCut(templateId)", returning = "result")
public void afterDelete(JoinPoint joinPoint, String templateId, Integer result) {
logger.info("【删除策略模版切面进入成功】");
if (result == 0 || StringUtils.isEmpty(templateId)) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
// 从ThreadLocal中获取删除前的对象
EmsStrategyTemp strategyTemp = beforeDeleteThreadLocal.get();
String siteId = "";
if (strategyTemp != null) {
siteId = strategyTemp.getSiteId();
}
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 数据转换
Map<String, Object> idMap = new HashMap<>();
idMap.put("templateId", templateId); // 手动将参数值映射到"id"字段
String content = JSON.toJSONString(idMap);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject("CLOUD");
message.setTarget(siteId);
return message;
}
// 从方法名判断操作类型示例insert→INSERTupdate→UPDATEdelete→DELETE
private String getOperateType(String methodName) {
if (methodName.startsWith("insert")) return "INSERT";
if (methodName.startsWith("stop")) return "STOP";
if (methodName.startsWith("update") || methodName.startsWith("stop")) return "UPDATE";
if (methodName.startsWith("delete")) return "DELETE";
return "UNKNOWN";
}
// 从方法参数提取数据示例若参数是实体类转成Map
private Map<String, Object> extractDataFromParams(Object[] args) {
// 实际需反射获取实体类的字段和值如id、name等
Map<String, Object> data = new HashMap<>();
if (args == null || args.length == 0) {
return data;
}
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg == null) {
continue; // 跳过null参数
}
// 处理基本类型/包装类/字符串直接作为值存入key为"param0"、"param1"等)
if (isBasicType(arg.getClass())) {
String key = "param" + i; // 基本类型参数用"param0"、"param1"作为key
data.put(key, arg);
} else {
Map<String, Object> beanMap = beanToMap(arg);
data.putAll(beanMap); // 合并实体类的字段到结果Map
}
}
return data;
}
/**
* 判断是否为基本类型或包装类或字符串
*/
private boolean isBasicType(Class<?> clazz) {
return clazz.isPrimitive() // 基本类型int、long、boolean等
|| clazz == String.class // 字符串
|| Number.class.isAssignableFrom(clazz) // 数字包装类Integer、Long等
|| clazz == Boolean.class; // 布尔包装类
}
/**
* 将实体类转换为Map字段名为key字段值为value
*/
private Map<String, Object> beanToMap(Object bean) {
Map<String, Object> map = new HashMap<>();
if (bean == null) {
return map;
}
// 方式1使用BeanMap简洁高效
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key.toString(), beanMap.get(key));
}
return map;
}
// 在方法中转换
public String convertEntityToJson(EmsStrategyRunning insertEntity) throws Exception {
if (insertEntity == null) {
return null; // 空对象返回空JSON
}
// 将实体类转换为JSON字符串
return objectMapper.writeValueAsString(insertEntity);
}
}

View File

@ -1,241 +0,0 @@
package com.xzzn.framework.aspectj;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.common.utils.bean.BeanUtils;
import com.xzzn.ems.domain.EmsStrategy;
import com.xzzn.ems.domain.EmsStrategyRunning;
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.domain.vo.SyncStrategyTimeConfigVo;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.EmsStrategyMapper;
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
/**
* 策略时间配置同步
* 云端 - 本地
*/
@Aspect
@Component
public class StrategyTimeConfigSyncAspect {
private static final Logger logger = LoggerFactory.getLogger(StrategyTimeConfigSyncAspect.class);
@Autowired
private MqttPublisher mqttPublisher;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String MQTT_TOPIC = "EMS_STRATEGY_UP";
private static final String TABLE_NAME = "ems_strategy_temp";
@Autowired
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
@Autowired
private MqttSyncLogMapper mqttSyncLogMapper;
@Autowired
private EmsStrategyMapper emsStrategyMapper;
@Autowired
private EmsStrategyTempMapper emsStrategyTempMapper;
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyTimeConfigMapper.insertEmsStrategyTimeConfig(..)) && args(insertEntity)) ")
public void insertPointCut(EmsStrategyTimeConfig insertEntity) {
logger.info("【新增策略模版时间配置切面】StrategyTimeConfigSyncAspect 被实例化");
}
@Pointcut("(execution(* com.xzzn.ems.mapper.EmsStrategyTimeConfigMapper.updateEmsStrategyTimeConfig(..)) && args(updateEntity)) ")
public void updatePointCut(EmsStrategyTimeConfig updateEntity) {
logger.info("【更新策略模版时间配置切面】StrategyTimeConfigSyncAspect 被实例化");
}
// 方法执行成功后发布同步消息
@AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
public void afterInsert(JoinPoint joinPoint, EmsStrategyTimeConfig insertEntity, Integer result) {
logger.info("【新增策略模版时间切面进入成功】");
if (result == 0 || insertEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = insertEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 校验策略id是否存在
Long strategyId = insertEntity.getStrategyId();
if (strategyId == null) {
return;
}
// 数据转换
SyncStrategyTimeConfigVo timeConfigVo = convertEntity(insertEntity);
String content = objectMapper.writeValueAsString(timeConfigVo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
private SyncStrategyTimeConfigVo convertEntity(EmsStrategyTimeConfig insertEntity) {
SyncStrategyTimeConfigVo timeConfigVo = new SyncStrategyTimeConfigVo();
BeanUtils.copyProperties(insertEntity, timeConfigVo);
EmsStrategy strategy = emsStrategyMapper.selectEmsStrategyById(insertEntity.getStrategyId());
if (strategy != null) {
timeConfigVo.setStrategyName(strategy.getStrategyName());
timeConfigVo.setStrategyType(strategy.getStrategyType());
}
return timeConfigVo;
}
@AfterReturning(pointcut = "updatePointCut(updateEntity)", returning = "result")
public void afterUpdate(JoinPoint joinPoint, EmsStrategyTimeConfig updateEntity, Integer result) {
logger.info("【删除策略模版切面进入成功】");
if (result == 0 || updateEntity == null) {
return;
}
// 校验是否配置监听topic-监听则不发布
String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
if (!StringUtils.isEmpty(topic)) {
return;
}
// 解析方法名获取操作类型INSERT/UPDATE/DELETE和表名
String methodName = joinPoint.getSignature().getName();
String operateType = getOperateType(methodName);
String siteId = updateEntity.getSiteId();
// 构建日志同步消息
MqttSyncLog message = createMessageObject(operateType, siteId);
try {
// 数据转换
SyncStrategyTimeConfigVo timeConfigVo = convertEntity(updateEntity);
String content = objectMapper.writeValueAsString(timeConfigVo);
message.setContent(content);
// 发布到MQTT主题
mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
} catch (Exception e) {
message.setStatus("FAIL");
message.setErrorMsg(e.getMessage());
}
// 存储同步信息
mqttSyncLogMapper.insertMqttSyncLog(message);
}
// 构建同步信息
private MqttSyncLog createMessageObject(String operateType, String siteId) {
MqttSyncLog message = new MqttSyncLog();
message.setSyncId(UUID.randomUUID().toString());
message.setOperateType(operateType);
message.setTableName(TABLE_NAME);
message.setCreateTime(new Date());
message.setTopic(MQTT_TOPIC);
message.setStatus("SUCCESS");
message.setSyncObject("CLOUD");
message.setTarget(siteId);
return message;
}
// 从方法名判断操作类型示例insert→INSERTupdate→UPDATEdelete→DELETE
private String getOperateType(String methodName) {
if (methodName.startsWith("insert")) return "INSERT";
if (methodName.startsWith("stop")) return "STOP";
if (methodName.startsWith("update") || methodName.startsWith("stop")) return "UPDATE";
if (methodName.startsWith("delete")) return "DELETE";
return "UNKNOWN";
}
// 从方法参数提取数据示例若参数是实体类转成Map
private Map<String, Object> extractDataFromParams(Object[] args) {
// 实际需反射获取实体类的字段和值如id、name等
Map<String, Object> data = new HashMap<>();
if (args == null || args.length == 0) {
return data;
}
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg == null) {
continue; // 跳过null参数
}
// 处理基本类型/包装类/字符串直接作为值存入key为"param0"、"param1"等)
if (isBasicType(arg.getClass())) {
String key = "param" + i; // 基本类型参数用"param0"、"param1"作为key
data.put(key, arg);
} else {
Map<String, Object> beanMap = beanToMap(arg);
data.putAll(beanMap); // 合并实体类的字段到结果Map
}
}
return data;
}
/**
* 判断是否为基本类型或包装类或字符串
*/
private boolean isBasicType(Class<?> clazz) {
return clazz.isPrimitive() // 基本类型int、long、boolean等
|| clazz == String.class // 字符串
|| Number.class.isAssignableFrom(clazz) // 数字包装类Integer、Long等
|| clazz == Boolean.class; // 布尔包装类
}
/**
* 将实体类转换为Map字段名为key字段值为value
*/
private Map<String, Object> beanToMap(Object bean) {
Map<String, Object> map = new HashMap<>();
if (bean == null) {
return map;
}
// 方式1使用BeanMap简洁高效
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key.toString(), beanMap.get(key));
}
return map;
}
// 在方法中转换
public String convertEntityToJson(EmsStrategyRunning insertEntity) throws Exception {
if (insertEntity == null) {
return null; // 空对象返回空JSON
}
// 将实体类转换为JSON字符串
return objectMapper.writeValueAsString(insertEntity);
}
}

View File

@ -13,9 +13,8 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
* @author xzzn
*/
@Configuration
// proxyTargetClass = true表示使用cglib代理false表示jdk动态代理
// exposeProxy = true表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 指定要扫描的Mapper类的包的路径
@MapperScan("com.xzzn.**.mapper")
public class ApplicationConfig

View File

@ -0,0 +1,38 @@
package com.xzzn.framework.config;
import com.xzzn.framework.manager.ModbusConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ModbusConfig {
@Value("${modbus.pool.max-total:20}")
private int maxTotal;
@Value("${modbus.pool.max-idle:10}")
private int maxIdle;
@Value("${modbus.pool.min-idle:3}")
private int minIdle;
@Value("${modbus.pool.max-wait:3000}")
private long maxWaitMillis;
@Value("${modbus.pool.time-between-eviction-runs:30000}")
private long timeBetweenEvictionRunsMillis;
@Value("${modbus.pool.min-evictable-idle-time:60000}")
private long minEvictableIdleTimeMillis;
public ModbusConnectionManager modbusConnectionManager() {
ModbusConnectionManager manager = new ModbusConnectionManager();
manager.setMaxTotal(maxTotal);
manager.setMaxIdle(maxIdle);
manager.setMinIdle(minIdle);
manager.setMaxWaitMillis(maxWaitMillis);
manager.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
manager.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
return manager;
}
}

View File

@ -0,0 +1,254 @@
package com.xzzn.framework.manager;
import com.ghgande.j2mod.modbus.net.TCPMasterConnection;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;
@Component
public class ModbusConnectionManager implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(ModbusConnectionManager.class);
private final Map<Integer, ModbusConnectionWrapper> connectionPool = new ConcurrentHashMap<>();
// 连接池配置参数
private int maxTotal = 20;
private int maxIdle = 10;
private int minIdle = 3;
private long maxWaitMillis = 3000;
private long timeBetweenEvictionRunsMillis = 30000;
private long minEvictableIdleTimeMillis = 60000;
private ScheduledExecutorService scheduler;
@Autowired
private EmsDevicesSettingMapper deviceRepo;
@Override
public void run(ApplicationArguments args) throws Exception {
init();
}
public void init() {
// 启动心跳检测线程
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::heartbeatCheck, 1, 5, TimeUnit.MINUTES);
logger.info("Modbus连接管理器已初始化");
}
/**
* 获取连接(带自动创建和缓存)
*/
public ModbusConnectionWrapper getConnection(EmsDevicesSetting device) throws Exception {
return connectionPool.compute(Math.toIntExact(device.getId()), (id, wrapper) -> {
try {
if (wrapper == null || !wrapper.isActive()) {
if (connectionPool.size() >= maxTotal) {
evictIdleConnection();
}
logger.info("创建新连接: {}", device);
return new ModbusConnectionWrapper(createRawConnection(device));
}
wrapper.updateLastAccess();
return wrapper;
} catch (Exception e) {
throw new RuntimeException("连接创建失败: " + device.getId(), e);
}
});
}
/**
* 创建原始Modbus连接
*/
private TCPMasterConnection createRawConnection(EmsDevicesSetting device) throws Exception {
try {
InetAddress addr = InetAddress.getByName("192.168.80.100");
TCPMasterConnection connection = new TCPMasterConnection(addr);
connection.setPort(502);
connection.setTimeout(5000);
connection.connect();
return connection;
} catch (Exception e) {
logger.error("创建Modbus连接失败: {}", device, e);
throw e;
}
}
/**
* 心跳检测
*/
private void heartbeatCheck() {
logger.info("开始监控Modbus连接池状态当前连接数: {}", connectionPool.size());
// 步骤1获取所有活跃设备列表与轮询逻辑共用同一批设备
List<EmsDevicesSetting> activeDevices = null;
if (activeDevices == null || activeDevices.isEmpty()) {
logger.warn("无活跃设备,心跳检测仅清理无效连接");
}
// 步骤2清理无效连接遍历连接池移除已失效的连接
List<Integer> invalidDeviceIds = new ArrayList<>();
connectionPool.forEach((deviceId, wrapper) -> {
try {
if (!wrapper.isActive()) {
logger.info("连接{}已失效,移除连接", deviceId);
invalidDeviceIds.add(deviceId);
wrapper.close();
}
} catch (Exception e) {
logger.error("心跳检测异常: {}", deviceId, e);
}
});
// 批量移除无效连接(避免边遍历边修改)
invalidDeviceIds.forEach(connectionPool::remove);
logger.debug("移除无效连接后,连接池大小: {}", connectionPool.size());
// 步骤3补充关键设备的连接优先保障活跃设备的连接存在
if (!activeDevices.isEmpty()) {
// 3.1 先为所有活跃设备预加载连接(确保需要轮询的设备有连接)
preloadCriticalConnection(activeDevices);
// 3.2 若连接数仍不足minIdle补充额外连接可选避免连接池过小
int currentSize = connectionPool.size();
if (currentSize < minIdle) {
logger.info("连接数{}不足最小空闲数{},补充额外连接", currentSize, minIdle);
// 从活跃设备中选未创建连接的设备补充(避免重复创建)
List<EmsDevicesSetting> needMoreDevices = activeDevices.stream()
.filter(device -> !connectionPool.containsKey(Math.toIntExact(device.getId())))
.limit(minIdle - currentSize) // 只补充差额
.collect(Collectors.toList());
preloadCriticalConnection(needMoreDevices); // 复用预加载方法
}
}
}
/**
* 预加载关键连接
*/
private void preloadCriticalConnection(List<EmsDevicesSetting> devices) {
// 简化示例,不实现具体逻辑
logger.info("预加载连接: 连接池当前大小={}, 最小空闲={}", connectionPool.size(), minIdle);
devices.forEach(device -> {
try {
Integer deviceId = Math.toIntExact(device.getId());
if (!connectionPool.containsKey(deviceId)) {
getConnection(device); // 复用已有创建逻辑
}
} catch (Exception e) {
logger.warn("预加载设备{}连接失败", device.getId(), e);
}
});
}
/**
* 移除最久未使用的空闲连接
*/
private void evictIdleConnection() {
if (connectionPool.isEmpty()) {
return;
}
ModbusConnectionWrapper oldestWrapper = null;
long oldestAccessTime = Long.MAX_VALUE;
for (ModbusConnectionWrapper wrapper : connectionPool.values()) {
if (wrapper.isActive() && wrapper.getLastAccessTime() < oldestAccessTime) {
oldestAccessTime = wrapper.getLastAccessTime();
oldestWrapper = wrapper;
}
}
if (oldestWrapper != null) {
logger.info("移除空闲连接: {}", oldestWrapper.getConnection());
connectionPool.values().remove(oldestWrapper);
oldestWrapper.close();
}
}
// 移除指定设备连接
public void removeConnection(Integer deviceId) {
ModbusConnectionWrapper wrapper = connectionPool.remove(deviceId);
if (wrapper != null) {
wrapper.close(); // 双重保障,确保连接关闭
logger.info("连接池主动移除设备{}的连接", deviceId);
}
}
/**
* 判断是否应该移除空连接池
*/
private boolean shouldRemoveEmptyPool(GenericObjectPool<?> pool) {
// 可根据配置或逻辑决定是否移除空连接池
// 这里简单实现为当连接池数量超过最大值时移除
return connectionPool.size() > maxTotal;
}
/**
* 关闭连接
*/
private void closeConnection(TCPMasterConnection connection) {
try {
if (connection != null && connection.isConnected()) {
connection.close();
}
} catch (Exception e) {
logger.error("关闭Modbus连接失败", e);
}
}
// 容器销毁时关闭线程池
@PreDestroy
public void destroy() {
if (scheduler != null) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
}
}
}
// Getters and Setters
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public void setMaxWaitMillis(long maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
}

View File

@ -0,0 +1,81 @@
package com.xzzn.framework.manager;
import com.ghgande.j2mod.modbus.net.SerialConnection;
import com.ghgande.j2mod.modbus.net.TCPMasterConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class ModbusConnectionWrapper {
private static final Logger logger = LoggerFactory.getLogger(ModbusConnectionWrapper.class);
private static final AtomicInteger COUNTER = new AtomicInteger(0);
private final Object connection;
private final int connectionId;
private volatile long lastAccessTime;
private volatile boolean active = true;
public ModbusConnectionWrapper(Object connection) {
this.connection = connection;
this.connectionId = COUNTER.incrementAndGet();
this.lastAccessTime = System.currentTimeMillis();
logger.info("创建连接包装: {}", this);
}
public boolean isActive() {
if (!active) return false;
try {
// 检查连接是否物理上有效
if (connection instanceof TCPMasterConnection) {
return ((TCPMasterConnection) connection).isConnected();
} else if (connection instanceof SerialConnection) {
return ((SerialConnection) connection).isOpen();
}
} catch (Exception e) {
logger.error("连接状态检查失败: {}", connectionId, e);
return false;
}
// 默认检查空闲时间
return System.currentTimeMillis() - lastAccessTime < 300000; // 5分钟
}
public void updateLastAccess() {
this.lastAccessTime = System.currentTimeMillis();
}
public Object getConnection() {
return connection;
}
public void close() {
try {
logger.info("关闭连接: {}", this);
if (connection instanceof TCPMasterConnection) {
((TCPMasterConnection) connection).close();
} else if (connection instanceof SerialConnection) {
((SerialConnection) connection).close();
}
} catch (Exception e) {
logger.error("关闭连接失败: {}", connectionId, e);
} finally {
this.active = false;
}
}
public long getLastAccessTime() {
return lastAccessTime;
}
@Override
public String toString() {
return "ModbusConnectionWrapper{" +
"connectionId=" + connectionId +
", active=" + active +
", lastAccessTime=" + lastAccessTime +
'}';
}
}

View File

@ -1,6 +1,5 @@
package com.xzzn.framework.manager;
import com.xzzn.ems.service.IEmsAlarmRecordsService;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
@ -17,17 +16,15 @@ import java.util.concurrent.ConcurrentHashMap;
public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle, MqttCallback {
private final MqttConnectOptions connectOptions;
private final IEmsAlarmRecordsService iEmsAlarmRecordsService;
private MqttClient mqttClient;
private volatile boolean running = false;
private volatile boolean running = true;
// 存储订阅关系: topic -> (listener, qos)
private final ConcurrentHashMap<String, SubscriptionInfo> subscriptions = new ConcurrentHashMap<>();
@Autowired
public MqttLifecycleManager(MqttConnectOptions connectOptions, IEmsAlarmRecordsService iEmsAlarmRecordsService) {
public MqttLifecycleManager(MqttConnectOptions connectOptions) {
this.connectOptions = connectOptions;
this.iEmsAlarmRecordsService = iEmsAlarmRecordsService;
}
// Spring Boot 启动完成后执行
@ -110,11 +107,7 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
subscriptions.put(topic, new SubscriptionInfo(listener, qos));
} catch (MqttException e) {
System.err.println("Subscribe failed: " + e.getMessage());
// 订阅失败-增加告警
iEmsAlarmRecordsService.addSubFailedAlarmRecord(topic);
}
// 订阅成功了-校验是否存在未处理或者处理中的订阅失败信息
iEmsAlarmRecordsService.checkFailedRecord(topic);
}
// 发布方法

View File

@ -0,0 +1,126 @@
package com.xzzn.framework.scheduler;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsMqttMessageMapper;
import com.xzzn.framework.manager.ModbusConnectionManager;
import com.xzzn.framework.manager.ModbusConnectionWrapper;
import com.xzzn.framework.manager.MqttLifecycleManager;
import com.xzzn.framework.web.service.ModbusService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@EnableScheduling
public class ModbusPoller {
private static final Logger logger = LoggerFactory.getLogger(ModbusPoller.class);
private final MqttLifecycleManager mqttLifecycleManager;
@Autowired
private ModbusConnectionManager connectionManager;
@Autowired
private ModbusService modbusService;
@Autowired
private EmsDevicesSettingMapper deviceRepo;
@Autowired
private EmsMqttMessageMapper emsMqttMessageMapper;
@Autowired
public ModbusPoller(MqttLifecycleManager mqttLifecycleManager) {
this.mqttLifecycleManager = mqttLifecycleManager;
}
// 每5分钟触发支持cron表达式动态配置
@Scheduled(cron = "${modbus.poll.interval}")
@Async("modbusTaskExecutor")
public void pollAllDevices() {
logger.info("开始执行Modbus设备轮询...");
List<EmsDevicesSetting> activeDevices = deviceRepo.selectEmsDevicesSettingList(null);
EmsDevicesSetting device = activeDevices.get(0);
try {
processData(device,null);
} catch (Exception e) {
logger.error("调度设备{}任务失败", device.getId(), e);
}
/*
try {
pollSingleDevice(device);
} catch (Exception e) {
logger.error("调度设备{}任务失败", device.getId(), e);
}*/
/*activeDevices.forEach(device -> {
try {
CompletableFuture.runAsync(() -> pollSingleDevice(device))
.exceptionally(e -> {
logger.error("设备{}轮询异常", device.getId(), e);
return null;
});
} catch (Exception e) {
logger.error("调度设备{}任务失败", device.getId(), e);
}
});*/
}
private void pollSingleDevice(EmsDevicesSetting device) {
logger.debug("开始轮询设备: {}", device.getSiteId(), device.getDeviceName(), device.getId());
ModbusConnectionWrapper wrapper = null;
try {
// 获取连接
wrapper = connectionManager.getConnection(device);
// 读取保持寄存器
int[] data = modbusService.readHoldingRegisters(
wrapper.getConnection(),
1, //从站ID
10 // 寄存器数量
);
// 处理读取到的数据
processData(device, data);
} catch (Exception e) {
logger.error("轮询设备{}失败: {}", device.getId(), e.getMessage());
// 标记连接为无效
if (wrapper != null) {
wrapper.close();
connectionManager.removeConnection(Integer.parseInt(device.getDeviceId()));
}
throw new RuntimeException("轮询设备失败", e);
}
}
// 处理获取到的数据发到mqtt服务上
private void processData(EmsDevicesSetting device, int[] data) throws MqttException {
/*if (data == null || data.length == 0) {
logger.warn("设备{}返回空数据", device.getId());
return;
}*/
/*// 数据处理逻辑
StringBuilder sb = new StringBuilder();
sb.append("设备[").append(device.getDeviceName()).append("]数据: ");
for (int i = 0; i < data.length; i++) {
sb.append("R").append(i).append("=").append(data[i]).append(" ");
}
logger.info(sb.toString());*/
// 测试发送mqtt
/* EmsMqttMessage msg = emsMqttMessageMapper.selectEmsMqttMessageById(1L);
String dataJson = msg.getMqttMessage();
String topic = msg.getMqttTopic();
logger.info("topic" + topic);
logger.info("dataJson" + dataJson);
// 将设备数据下发到mqtt服务器上
mqttLifecycleManager.publish(topic, dataJson, 0);*/
}
}

View File

@ -0,0 +1,170 @@
package com.xzzn.framework.scheduler;
import com.alibaba.fastjson2.JSON;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsStrategyCurve;
import com.xzzn.ems.domain.EmsStrategyTemp;
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
import com.xzzn.ems.domain.vo.StrategyPowerDataVo;
import com.xzzn.ems.domain.vo.StrategyRunningVo;
import com.xzzn.ems.mapper.*;
import com.xzzn.framework.manager.ModbusConnectionManager;
import com.xzzn.framework.manager.MqttLifecycleManager;
import com.xzzn.framework.web.service.ModbusService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@Component
@EnableScheduling
public class StrategyPoller {
private static final Logger logger = LoggerFactory.getLogger(StrategyPoller.class);
private final MqttLifecycleManager mqttLifecycleManager;
@Autowired
private ModbusConnectionManager connectionManager;
@Autowired
private ModbusService modbusService;
@Autowired
private EmsDevicesSettingMapper deviceRepo;
@Autowired
private EmsMqttMessageMapper emsMqttMessageMapper;
@Autowired
private EmsStrategyRunningMapper emsStrategyRunningMapper;
@Autowired
private EmsStrategyTempMapper emsStrategyTempMapper;
@Autowired
private EmsStrategyTimeConfigMapper emsStrategyTimeConfigMapper;
@Autowired
private EmsStrategyCurveMapper emsStrategyCurveMapper;
@Autowired
public StrategyPoller(MqttLifecycleManager mqttLifecycleManager) {
this.mqttLifecycleManager = mqttLifecycleManager;
}
// 每1分钟触发支持cron表达式动态配置
@Scheduled(cron = "0 */1 * * * *")
@Async("strategyTaskExecutor")
public void pollAllDevices() {
logger.info("开始执行策略数据轮询...");
List<StrategyRunningVo> strategyRunningVoList = emsStrategyRunningMapper.getRunningList(null);
strategyRunningVoList.forEach(strategyVo -> {
try {
CompletableFuture.runAsync(() -> {
processData(strategyVo);
})
.exceptionally(e -> {
logger.error("策略{}轮询异常", strategyVo.getId(), e);
return null;
});
} catch (Exception e) {
logger.error("策略下方{}任务失败", strategyVo.getId(), e);
}
});
}
// 处理获取到的数据发到mqtt服务上
private void processData(StrategyRunningVo strategyVo) {
logger.info("策略下发数据处理开始");
// 根据运行策略获取主副策略的模板数据
Long mainStrategyId = strategyVo.getMainStrategyId();
Long auxStrategyId = strategyVo.getAuxStrategyId();
String siteId = strategyVo.getSiteId();
// 处理主策略数据
if (mainStrategyId != null && StringUtils.isNotBlank(siteId)) {
dealStrategyCurveData(mainStrategyId, siteId);
}
// 处理副策略数据
if (auxStrategyId != null && StringUtils.isNotBlank(siteId)) {
dealStrategyCurveData(auxStrategyId, siteId);
}
// 策略数据下发-下方格式暂无
logger.info("策略下发结束");
}
private void dealStrategyCurveData(Long mainStrategyId, String siteId) {
// 获取当前策略的所有模板
List<Map<String, String>> temps = emsStrategyTempMapper.getTempNameList(mainStrategyId,siteId);
if (temps != null && temps.size() > 0) {
for (Map<String, String> temp : temps) {
String tempId = temp.get("templateId");
List<EmsStrategyTimeConfig> timeConfigs = emsStrategyTimeConfigMapper.getAllTimeConfigByTempId(tempId);
if (timeConfigs != null && timeConfigs.size() > 0) {
for (EmsStrategyTimeConfig timeConfig : timeConfigs) {
EmsStrategyCurve curve = new EmsStrategyCurve();
curve.setStrategyId(mainStrategyId);
curve.setSiteId(siteId);
curve.setTemplateId(tempId);
curve.setCreateBy("system");
curve.setCreateTime(DateUtils.getNowDate());
curve.setUpdateBy("system");
curve.setUpdateTime(DateUtils.getNowDate());
// 时间设置
int month = Integer.parseInt(timeConfig.getMonth().toString());
String[] dateList= dealWithMonth(month);
curve.setMonth(Long.valueOf(month));
curve.setStartDate(DateUtils.dateTime(DateUtils.YYYY_MM_DD,dateList[0]));
curve.setEndDate(DateUtils.dateTime(DateUtils.YYYY_MM_DD,dateList[1]));
// powerData-存json格式
List<EmsStrategyTemp> powerConfig = emsStrategyTempMapper.selectStrategyTempByTempId(tempId);
List<StrategyPowerDataVo> powerDataVoList = new ArrayList<>();
for (int i = 0; i < powerConfig.size(); i++) {
EmsStrategyTemp powerTemp = powerConfig.get(i);
StrategyPowerDataVo powerDataVo = new StrategyPowerDataVo();
powerDataVo.setPowerData(powerTemp.getChargeDischargePower());
powerDataVo.setEndTime(DateUtils.parseDateToStr("HH:mm:ss",powerTemp.getEndTime()));
powerDataVo.setStartTime(DateUtils.parseDateToStr("HH:mm:ss",powerTemp.getStartTime()));
powerDataVoList.add(powerDataVo);
}
curve.setPowerData(powerDataVoList !=null ? JSON.toJSON(powerDataVoList).toString() : "");
// 记录推送记录
emsStrategyCurveMapper.insertEmsStrategyCurve(curve);
// 设置已下发
timeConfig.setIsPost(0);
emsStrategyTimeConfigMapper.updateEmsStrategyTimeConfig(timeConfig);
}
}
}
}
}
private String[] dealWithMonth(int month) {
// 获取当前年份
int currentYear = LocalDate.now().getYear();
// 创建YearMonth对象表示当年指定的月份
YearMonth yearMonth = YearMonth.of(currentYear, month);
// 获取当月的第一天和最后一天
LocalDate firstDay = yearMonth.atDay(1);
LocalDate lastDay = yearMonth.atEndOfMonth();
// 定义日期格式(年月日)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 格式化日期
return new String[]{
firstDay.format(formatter),
lastDay.format(formatter)
};
}
}

View File

@ -0,0 +1,101 @@
package com.xzzn.framework.web.service;
import com.ghgande.j2mod.modbus.ModbusException;
import com.ghgande.j2mod.modbus.ModbusIOException;
import com.ghgande.j2mod.modbus.io.ModbusTCPTransaction;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersRequest;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersResponse;
import com.ghgande.j2mod.modbus.net.SerialConnection;
import com.ghgande.j2mod.modbus.net.TCPMasterConnection;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
/**
* Modbus操作服务添加重试机制
*/
@Service
public class ModbusService {
private static final Logger logger = LoggerFactory.getLogger(ModbusService.class);
@Retryable(
value = {ModbusException.class}, // 仅对自定义Modbus异常重试
maxAttempts = 3, // 最大重试3次1次原始调用 + 2次重试
backoff = @Backoff(delay = 1000, multiplier = 2) // 退避策略1s → 2s → 4s
)
@CircuitBreaker(name = "modbusOperation", fallbackMethod = "readRegistersFallback")
public int[] readHoldingRegisters(Object connection, int startAddr, int count) throws ModbusException {
try {
if (connection instanceof TCPMasterConnection) {
return readTcpRegisters((TCPMasterConnection) connection, startAddr, count);
} else if (connection instanceof SerialConnection) {
return readRtuRegisters((SerialConnection) connection, startAddr, count);
}
throw new IllegalArgumentException("不支持的连接类型: " + connection.getClass().getName());
} catch (ModbusIOException e) {
throw new ModbusException("通信故障", e);
} catch (Exception e) {
throw new ModbusException("系统错误", e);
}
}
private int[] readRtuRegisters(SerialConnection connection, int startAddr, int count) {
return null;
}
private int[] readTcpRegisters(TCPMasterConnection conn, int start, int count) throws ModbusException {
// 验证连接是否已建立
if (!conn.isConnected()) {
throw new ModbusIOException("TCP连接未建立");
}
// 使用正确的功能码03 - 读取保持寄存器ReadHoldingRegistersRequest
ReadInputRegistersRequest request = new ReadInputRegistersRequest(start, count);
ModbusTCPTransaction transaction = new ModbusTCPTransaction(conn);
transaction.setRequest(request);
// 设置超时避免长时间阻塞
transaction.setRetries(2);
try {
transaction.execute();
ReadInputRegistersResponse response = (ReadInputRegistersResponse) transaction.getResponse();
if (response == null) {
throw new ModbusException("Modbus异常响应: " + response.getMessage());
}
// 正确解析寄存器值
return parseRegisters(response);
} catch (ModbusException e) {
// 记录详细错误信息
logger.error("读取TCP寄存器失败: {}", e.getMessage());
throw e;
}
}
/**
* 解析Modbus响应中的寄存器值
*/
private int[] parseRegisters(ReadInputRegistersResponse response) {
int byteCount = response.getByteCount();
int[] result = new int[byteCount / 2];
for (int i = 0; i < result.length; i++) {
// 转换为无符号整数
result[i] = response.getRegisterValue(i) & 0xFFFF;
}
return result;
}
/**
* 熔断降级方法
*/
public int[] readRegistersFallback(Object connection, int startAddr, int count, Exception e) {
logger.warn("Modbus操作降级原因: {}),返回空数据", e.getMessage());
return new int[0];
}
}

View File

@ -34,10 +34,6 @@
<groupId>com.xzzn</groupId>
<artifactId>ems-common</artifactId>
</dependency>
<dependency>
<groupId>com.xzzn</groupId>
<artifactId>ems-framework</artifactId>
</dependency>
</dependencies>

View File

@ -1,33 +0,0 @@
package com.xzzn.quartz.config;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.PreDestroy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Modbus操作执行器配置
* 所有Modbus读写操作必须通过此单线程执行器串行执行避免并发访问导致通讯故障
*/
@Configuration
public class ModbusExecutorConfig {
private final ExecutorService modbusExecutor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "modbus-io-thread");
t.setDaemon(false);
return t;
});
@Bean(name = "modbusExecutor")
public ExecutorService modbusExecutor() {
return modbusExecutor;
}
@PreDestroy
public void shutdown() {
modbusExecutor.shutdown();
}
}

View File

@ -1,34 +0,0 @@
package com.xzzn.quartz.config;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
public void startTask(String deviceId, Runnable task, long period) {
stopTask(deviceId); // 如果已有同ID任务在运行先停止
ScheduledFuture<?> future = executor.scheduleAtFixedRate(task, 0, period, TimeUnit.MILLISECONDS);
futureMap.put(deviceId, future);
}
public void stopTask(String deviceId) {
ScheduledFuture<?> future = futureMap.get(deviceId);
if (future != null && !future.isDone()) {
future.cancel(true);
}
futureMap.remove(deviceId);
}
}

View File

@ -1,336 +0,0 @@
package com.xzzn.quartz.task;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.serotonin.modbus4j.ModbusMaster;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.modbus.ModbusProcessor;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.DeviceRunningStatus;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.service.IEmsAlarmRecordsService;
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
import com.xzzn.framework.manager.MqttLifecycleManager;
import com.xzzn.framework.web.service.MqttPublisher;
import com.xzzn.quartz.config.ScheduledTask;
import com.xzzn.quartz.domain.SysJob;
import com.xzzn.quartz.service.ISysJobService;
import com.xzzn.quartz.util.CronUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Resource;
import java.util.stream.Collectors;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
/**
* 轮询设备-通过modbus协议读取数据
*/
@Component("modbusPoller")
public class ModbusPoller {
private static final Logger log = LoggerFactory.getLogger(ModbusPoller.class);
private final MqttLifecycleManager mqttLifecycleManager;
private final ScheduledTask scheduledTask;
private final ObjectMapper objectMapper = new ObjectMapper();
private final Map<String, Integer> deviceFailureCounts = new ConcurrentHashMap<>();
private final AtomicBoolean polling = new AtomicBoolean(false);
@Resource(name = "modbusExecutor")
private ExecutorService modbusExecutor;
@Autowired
private ModbusProcessor modbusProcessor;
@Autowired
private IEmsAlarmRecordsService iEmsAlarmRecordsService;
@Autowired
private ISysJobService iSysJobService;
@Autowired
private DeviceDataProcessServiceImpl deviceDataProcessServiceImpl;
@Autowired
private EmsDevicesSettingMapper emsDevicesSettingMapper;
@Autowired
private RedisCache redisCache;
@Autowired
private MqttPublisher mqttPublisher;
@Value("${mqtt.topic}")
private String topic;
@Value("${mqtt.siteId}")
private String siteId;
@Autowired
public ModbusPoller(MqttLifecycleManager mqttLifecycleManager, ScheduledTask scheduledTask) {
this.mqttLifecycleManager = mqttLifecycleManager;
this.scheduledTask = scheduledTask;
}
public void pollAllDevices() {
if (!polling.compareAndSet(false, true)) {
log.warn("上一次轮询尚未完成,本次轮询跳过");
return;
}
Path devicesDir = Paths.get(System.getProperty("user.dir"), "devices");
if (!Files.exists(devicesDir)) {
log.error("Devices目录不存在: {}", devicesDir);
polling.set(false);
return;
}
List<Path> jsonFiles = null;
try {
jsonFiles = Files.list(devicesDir)
.filter(path -> path.toString().endsWith(".json"))
.collect(Collectors.toList());
} catch (IOException e) {
log.error("modbusPoller.loadConfigs 获取设备配置文件失败: {}", devicesDir, e);
polling.set(false);
return;
}
// 按主机IP分组同一网关的不同端口也归为一组避免并发访问导致Connection Reset
Map<String, List<DeviceConfig>> groupedByHost = new HashMap<>();
for (Path filePath : jsonFiles) {
DeviceConfig config = null;
try {
config = objectMapper.readValue(filePath.toFile(), DeviceConfig.class);
} catch (IOException e) {
log.error("modbusPoller.loadConfigs 解析设备配置文件失败: {}", filePath, e);
continue;
}
if (config.isEnabled()) {
// 只按主机IP分组确保同一网关的所有端口串行访问
String hostKey = config.getHost();
groupedByHost.computeIfAbsent(hostKey, k -> new ArrayList<>()).add(config);
}
}
// 使用单线程 executor 串行执行所有主机的 Modbus 操作
// 将所有主机的设备按顺序串行处理,避免任何并发访问
Future<?> future = modbusExecutor.submit(() -> {
for (Map.Entry<String, List<DeviceConfig>> entry : groupedByHost.entrySet()) {
String hostKey = entry.getKey();
List<DeviceConfig> configs = entry.getValue();
for (DeviceConfig config : configs) {
try {
scheduledStart(config);
// 每次读取后等待200ms给Modbus网关足够的处理时间
Thread.sleep(200);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
log.warn("Modbus轮询被中断");
return;
} catch (Exception e) {
log.error("采集设备数据异常: {}", config.getDeviceName(), e);
}
}
log.info("采集设备数据{}轮询任务执行完成", hostKey);
}
});
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("Modbus轮询任务等待中断");
} catch (Exception e) {
log.error("Modbus轮询任务执行异常", e);
} finally {
polling.set(false);
}
}
public void scheduledStart(DeviceConfig config) {
if (config.isEnabled()) {
log.info("Reading data from devices: {}", config.getDeviceName());
// 带重试的读取最多重试2次
Map<String, Object> data = readWithRetry(config, 2);
List<String> rawValuEmptyList = new ArrayList<>();
// 在这里处理采集到的数据空
config.getTags().forEach(tag -> {
Object rawValue = data.get(tag.getKey());
if (rawValue != null) {
float value = 0;
if (rawValue instanceof Number) {
value = ((Number) rawValue).floatValue(); // 安全地转换为 float
} else {
log.error("tag:{},无法将数据转换为数字: {}", tag.getKey(), rawValue);
}
value = tag.getA() * value * value + tag.getK() * value + tag.getB();
int intValue = (int) value;
if (tag.getBit() != null) {
log.info("tag:{},bit:{},value:{}", tag.getKey(), tag.getBit(), value);
String binary = Integer.toBinaryString(intValue);
data.put(tag.getKey(), binary);
} else {
data.put(tag.getKey(), value);
}
} else {
// data.put(tag.getKey(), rawValue);
// log.warn("tag:{},数据为空: {}", tag.getKey(), rawValue);
rawValuEmptyList.add("tag: " + tag.getKey() + ",数据为空: " + rawValue);
}
});
if (!rawValuEmptyList.isEmpty()) {
log.warn("设备 {} 数据为空: {}", config.getDeviceName(), JSON.toJSONString(rawValuEmptyList));
}
log.info("Data from {}: {}", config.getDeviceName(), data);
String deviceNumber = config.getDeviceNumber();
//处理数据并发送MQTT消息、保存Redis数据和数据入库
processingData(data, deviceNumber);
}
}
/**
* 带重试的读取方法
*/
private Map<String, Object> readWithRetry(DeviceConfig config, int maxRetries) {
Map<String, Object> data = new HashMap<>();
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
ModbusMaster master = modbusProcessor.borrowMaster(config);
data = modbusProcessor.readDataFromDevice(config, master);
// 如果读取成功(有数据),直接返回
if (!data.isEmpty()) {
if (attempt > 0) {
log.info("设备 {} 第 {} 次重试成功", config.getDeviceName(), attempt);
}
return data;
}
// 读取返回空数据,等待后重试
if (attempt < maxRetries) {
log.warn("设备 {} 读取返回空数据等待1秒后重试 ({}/{})",
config.getDeviceName(), attempt + 1, maxRetries);
Thread.sleep(1000);
}
} catch (Exception e) {
log.error("设备 {} 读取异常 ({}/{}): {}",
config.getDeviceName(), attempt + 1, maxRetries, e.getMessage());
if (attempt < maxRetries) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
break;
}
}
}
}
// 所有重试都失败
log.error("设备 {} 读取失败,已重试 {} 次", config.getDeviceName(), maxRetries);
return data;
}
private void processingData(Map<String, Object> data, String deviceNumber) {
if (CollectionUtils.isEmpty(data)) {
// 增加失败计数
int failureCount = deviceFailureCounts.getOrDefault(deviceNumber, 0) + 1;
deviceFailureCounts.put(deviceNumber, failureCount);
log.warn("设备 {} 数据读取失败,当前连续失败次数: {}", deviceNumber, failureCount);
// 连续6次失败触发报警
if (failureCount >= 6) {
addDeviceOfflineRecord(siteId, deviceNumber);
log.error("设备 {} 连续 {} 次未读取到数据,触发报警", deviceNumber, failureCount);
}
return;
}
// 数据读取成功,重置计数器
deviceFailureCounts.remove(deviceNumber);
updateDeviceStatus(siteId, deviceNumber, DeviceRunningStatus.ONLINE.getCode());
// 发送MQTT消息、保存Redis数据和数据入库
Long timestamp = System.currentTimeMillis();
JSONObject json = new JSONObject();
json.put("Data", data);
json.put("timestamp", timestamp);
json.put("Device", deviceNumber);
sendMqttMsg(json);
saveRedisData(json, deviceNumber);
saveDataToDatabase(data, deviceNumber, timestamp);
}
public void sendMqttMsg(JSONObject json) {
try {
mqttPublisher.publish(topic, Collections.singletonList(json).toString(), 0);
} catch (MqttException e) {
log.error("MQTT消息发布失败: {}, reason code: {}", json.toJSONString(), e.getReasonCode() ,e);
}
log.info("已发送数据: {}", json.toJSONString());
}
public void saveRedisData(JSONObject obj, String deviceNumber) {
try {
// 存放mqtt原始每个设备最晚一次数据便于后面点位获取数据
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj);
// 存放每次同步数据,失效时间(同同步时间)-用于判断是否正常同步数据和保护策略查询
redisCache.setCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceNumber, obj, 1, TimeUnit.MINUTES);
log.info("数据已成功存储在Redis: {}", deviceNumber);
} catch (Exception e) {
log.error("无法在设备的Redis中存储数据: {}", deviceNumber, e);
}
}
private void saveDataToDatabase(Map<String, Object> data, String deviceNumber, Long timestamp) {
deviceDataProcessServiceImpl.processingDeviceData(siteId, deviceNumber, JSON.toJSONString(data), DateUtils.convertUpdateTime(timestamp));
}
//处理设备连接失败的情况,更新设备状态为离线,添加报警记录
private void addDeviceOfflineRecord(String siteId, String deviceNumber) {
updateDeviceStatus(siteId, deviceNumber, DeviceRunningStatus.OFFLINE.getCode());
iEmsAlarmRecordsService.addDeviceOfflineRecord(siteId, deviceNumber);
}
// 更新设备状态为在线或离线
private void updateDeviceStatus(String siteId, String deviceNumber, String deviceStatus) {
EmsDevicesSetting emsDevicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceNumber, siteId);
if (emsDevicesSetting != null && !Objects.equals(emsDevicesSetting.getDeviceStatus(), deviceStatus)) {
emsDevicesSetting.setDeviceStatus(deviceStatus);
emsDevicesSettingMapper.updateEmsDevicesSetting(emsDevicesSetting);
}
}
private int getScheduledTaskInterval() {
SysJob query = new SysJob();
query.setInvokeTarget("modbusPoller.pollAllDevices");
List<SysJob> sysJobs = iSysJobService.selectJobList(query);
return Math.toIntExact(CronUtils.getNextExecutionIntervalMillis(sysJobs.get(0).getCronExpression()));
}
}

View File

@ -1,482 +0,0 @@
package com.xzzn.quartz.task;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.annotation.SyncAfterInsert;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.AlarmLevelStatus;
import com.xzzn.common.enums.AlarmStatus;
import com.xzzn.common.enums.ProtPlanStatus;
import com.xzzn.common.enums.StrategyStatus;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsAlarmRecords;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.EmsFaultIssueLog;
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
import com.xzzn.ems.domain.EmsStrategyRunning;
import com.xzzn.ems.domain.vo.ProtectionPlanVo;
import com.xzzn.ems.domain.vo.ProtectionSettingVo;
import com.xzzn.ems.mapper.EmsAlarmRecordsMapper;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsFaultIssueLogMapper;
import com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper;
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
import com.xzzn.ems.service.IEmsFaultProtectionPlanService;
import com.xzzn.common.core.modbus.ModbusProcessor;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
/**
* 告警保护方案轮询
*
* @author xzzn
*/
@Component("protectionPlanTask")
public class ProtectionPlanTask {
private static final Logger logger = LoggerFactory.getLogger(ProtectionPlanTask.class);
@Resource(name = "scheduledExecutorService")
private ScheduledExecutorService scheduledExecutorService;
@Autowired
private IEmsFaultProtectionPlanService iEmsFaultProtectionPlanService;
@Autowired
private EmsAlarmRecordsMapper emsAlarmRecordsMapper;
@Autowired
private EmsStrategyRunningMapper emsStrategyRunningMapper;
@Autowired
private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;
@Autowired
private RedisCache redisCache;
private static final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private EmsDevicesSettingMapper emsDevicesSettingMapper;
@Autowired
private ModbusProcessor modbusProcessor;
@Autowired
private EmsFaultIssueLogMapper emsFaultIssueLogMapper;
public ProtectionPlanTask(IEmsFaultProtectionPlanService iEmsFaultProtectionPlanService) {
this.iEmsFaultProtectionPlanService = iEmsFaultProtectionPlanService;
}
public void pollPlanList() {
Long planId = 0L;
try {
// 获取所有方案,轮询
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
for (EmsFaultProtectionPlan plan : planList) {
planId = plan.getId();
String siteId = plan.getSiteId();
if (StringUtils.isEmpty(siteId)) {
return;
}
// 保护前提
String protectionSettings = plan.getProtectionSettings();
final List<ProtectionSettingVo> protSettings = objectMapper.readValue(
protectionSettings,
new TypeReference<List<ProtectionSettingVo>>() {}
);
if (protSettings == null) {
return;
}
// 处理告警保护方案
boolean isHighLevel = dealWithProtectionPlan(plan, protSettings);
if (isHighLevel) {
// 触发最高故障等级-结束循环
return;
}
}
} catch (Exception e) {
logger.error("轮询失败,方案id为{}", planId, e);
}
}
// 处理告警保护方案-返回触发下发方案时是否最高等级
// 需要同步云端
@SyncAfterInsert
private boolean dealWithProtectionPlan(EmsFaultProtectionPlan plan, List<ProtectionSettingVo> protSettings) {
logger.info("<轮询保护方案> 站点:{}方案ID:{}", plan.getSiteId(), plan.getId());
boolean isHighLevel = false;
String siteId = plan.getSiteId();
final Integer isAlertAlarm = plan.getIsAlert();
final Long status = plan.getStatus();
// 看方案是否启用,走不同判断
if (Objects.equals(status, ProtPlanStatus.STOP.getCode())) {
logger.info("<方案未启用> 站点:{}方案ID:{}", siteId, plan.getId());
// 未启用,获取方案的故障值与最新数据判断是否需要下发方案
if(checkIsNeedIssuedPlan(protSettings, siteId)){
if("3".equals(plan.getFaultLevel())){
isHighLevel = true;//最高故障等级
}
// 延时
final int faultDelay = plan.getFaultDelaySeconds().intValue();
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
// 延时后再次确认是否仍满足触发条件(防止期间状态变化)
if (checkIsNeedIssuedPlan(protSettings, siteId)) {
// 判断是否需要生成告警
if (isAlertAlarm == 1) {
logger.info("<生成告警> 方案ID:{},站点:{}", plan.getId(), siteId);
EmsAlarmRecords alarmRecords = addAlarmRecord(siteId,plan.getFaultName(),
getAlarmLevel(plan.getFaultLevel()));
emsAlarmRecordsMapper.insertEmsAlarmRecords(alarmRecords);
}
// 是否有保护方案有则通过modbus连接设备下发方案
String protPlanJson = plan.getProtectionPlan();
if (protPlanJson != null && !protPlanJson.isEmpty() && !"[]".equals(protPlanJson)) {
logger.info("<下发保护方案> 方案内容:{}", protPlanJson);
executeProtectionActions(protPlanJson,siteId,plan.getId(),plan.getFaultLevel()); // 执行Modbus指令
}
// 更新方案状态为“已启用”
logger.info("<方案已启用> 方案ID:{}", plan.getId());
plan.setStatus(ProtPlanStatus.RUNNING.getCode());
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
// 更新该站点策略为暂停状态
updateStrategyRunningStatus(siteId, StrategyStatus.SUSPENDED.getCode());
}
}, faultDelay, TimeUnit.SECONDS);
}
} else {
logger.info("<方案已启用> 站点:{}方案ID:{}", siteId, plan.getId());
// 已启用,则获取方案的释放值与最新数据判断是否需要取消方案
if(checkIsNeedCancelPlan(protSettings, siteId)){
// 延时,
int releaseDelay = plan.getReleaseDelaySeconds().intValue();
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
// 判断是否已存在未处理告警,有着取消
if(isAlertAlarm == 1){
logger.info("<取消告警>");
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.getFailedRecord(siteId,
plan.getFaultName(),getAlarmLevel(plan.getFaultLevel()));
if(emsAlarmRecords != null){
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
}
}
// 更新方案状态为“未启用”
logger.info("<方案变更为未启用> 方案ID:{}", plan.getId());
plan.setStatus(ProtPlanStatus.STOP.getCode());
plan.setUpdateBy("system");
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
// 更新该站点策略为启用状态
updateStrategyRunningStatus(siteId, StrategyStatus.RUNNING.getCode());
}, releaseDelay, TimeUnit.SECONDS);
}
}
return isHighLevel;
}
// 下发保护方案
private void executeProtectionActions(String protPlanJson, String siteId, Long planId, Integer faultLevel){
final List<ProtectionPlanVo> protPlanList;
try {
protPlanList = objectMapper.readValue(
protPlanJson,
new TypeReference<List<ProtectionPlanVo>>() {}
);
if (protPlanList == null) {
return;
}
// 遍历保护方案
for (ProtectionPlanVo plan : protPlanList) {
if (StringUtils.isEmpty(plan.getDeviceId()) || StringUtils.isEmpty(plan.getPoint())) {
return;
}
// 给设备发送指令记录日志,并同步云端
EmsFaultIssueLog faultIssueLog = createLogEntity(plan,siteId);
faultIssueLog.setLogLevel(faultLevel);
emsFaultIssueLogMapper.insertEmsFaultIssueLog(faultIssueLog);
// 通过modbus连接设备发送数据
executeSinglePlan(plan,siteId);
}
} catch (Exception e) {
logger.error("下发保护方案失败,方案id为", planId, e);
}
}
private EmsFaultIssueLog createLogEntity(ProtectionPlanVo plan,String siteId) {
EmsFaultIssueLog faultIssueLog = new EmsFaultIssueLog();
faultIssueLog.setLogId(UUID.randomUUID().toString());
faultIssueLog.setLogTime(new Date());
faultIssueLog.setSiteId(siteId);
faultIssueLog.setDeviceId(plan.getDeviceId());
faultIssueLog.setPoint(plan.getPoint());
faultIssueLog.setValue(plan.getValue());
faultIssueLog.setCreateBy("sys");
faultIssueLog.setCreateTime(new Date());
return faultIssueLog;
}
private void executeSinglePlan(ProtectionPlanVo plan, String siteId) throws Exception {
String deviceId = plan.getDeviceId();
// 获取设备地址信息
EmsDevicesSetting device = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
if (device == null || StringUtils.isEmpty(device.getIpAddress()) || device.getIpPort()==null) {
logger.warn("设备信息不完整deviceId:{}", deviceId);
return;
}
// 构建设备配置
DeviceConfig config = new DeviceConfig();
config.setHost(device.getIpAddress());
config.setPort(device.getIpPort().intValue());
config.setSlaveId(device.getSlaveId().intValue());
config.setDeviceName(device.getDeviceName());
config.setDeviceNumber(device.getDeviceId());
// 构建写入标签配置
WriteTagConfig writeTag = new WriteTagConfig();
writeTag.setAddress(plan.getPoint());
writeTag.setValue(plan.getValue());
List<WriteTagConfig> writeTags = new ArrayList<>();
writeTags.add(writeTag);
config.setWriteTags(writeTags);
// 写入数据到设备
boolean success = modbusProcessor.writeDataToDeviceWithRetry(config);
if (!success) {
logger.error("写入失败,设备地址:{}", device.getIpAddress());
}
}
// 校验释放值是否取消方案
private boolean checkIsNeedCancelPlan(List<ProtectionSettingVo> protSettings, String siteId) {
BigDecimal releaseValue = BigDecimal.ZERO;
StringBuilder conditionSb = new StringBuilder();
for (int i = 0; i < protSettings.size(); i++) {
ProtectionSettingVo vo = protSettings.get(i);
String deviceId = vo.getDeviceId();
String point = vo.getPoint();
releaseValue = vo.getFaultValue();
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || releaseValue == null
|| StringUtils.isEmpty(vo.getReleaseOperator())){
return false;
}
// 获取点位最新值
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
logger.info("checkIsNeedCancelPlan 点位:{},最新值:{},比较方式:{},释放值:{}", point, lastPointValue, vo.getReleaseOperator(), releaseValue);
if(lastPointValue == null){
return false;
}
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
conditionSb.append(lastPointValue).append(vo.getReleaseOperator()).append(releaseValue);
if (i < protSettings.size() - 1) {
String relation = vo.getRelationNext();
conditionSb.append(" ").append(relation).append(" ");
}
}
// 执行比较语句
return executeWithParser(conditionSb.toString());
}
// 校验故障值是否需要下发方案
private boolean checkIsNeedIssuedPlan(List<ProtectionSettingVo> protSettings, String siteId) {
BigDecimal faultValue = BigDecimal.ZERO;
StringBuilder conditionSb = new StringBuilder();
for (int i = 0; i < protSettings.size(); i++) {
ProtectionSettingVo vo = protSettings.get(i);
String deviceId = vo.getDeviceId();
String point = vo.getPoint();
faultValue = vo.getFaultValue();
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || faultValue == null
|| StringUtils.isEmpty(vo.getFaultOperator())){
return false;
}
// 获取点位最新值
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
logger.info("checkIsNeedIssuedPlan 点位:{},最新值:{},比较方式:{},故障值:{}", point, lastPointValue, vo.getFaultOperator(), faultValue);
if(lastPointValue == null){
return false;
}
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
conditionSb.append(lastPointValue).append(vo.getFaultOperator()).append(faultValue);
if (i < protSettings.size() - 1) {
String relation = vo.getRelationNext();
conditionSb.append(" ").append(relation).append(" ");
}
}
// 执行比较语句
return executeWithParser(conditionSb.toString());
}
private BigDecimal getPointLastValue(String deviceId, String point, String siteId) {
JSONObject mqttJson = redisCache.getCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceId);
if(mqttJson == null){
return null;
}
String jsonData = mqttJson.get("Data").toString();
if(StringUtils.isEmpty(jsonData)){
return null;
}
Map<String, Object> obj = JSON.parseObject(jsonData, new com.alibaba.fastjson2.TypeReference<Map<String, Object>>() {});
return StringUtils.getBigDecimal(obj.get(point));
}
// 更新站点策略为启用
private void updateStrategyRunningStatus(String siteId, String status) {
// 获取是否有正在运行的策略,如果有则不更改
EmsStrategyRunning query = new EmsStrategyRunning();
query.setSiteId(siteId);
query.setStatus(StrategyStatus.RUNNING.getCode().equals(status) ? StrategyStatus.SUSPENDED.getCode() : StrategyStatus.RUNNING.getCode());
List<EmsStrategyRunning> strategyRunningList = emsStrategyRunningMapper.selectEmsStrategyRunningList(query);
if (CollectionUtils.isNotEmpty(strategyRunningList)) {
// 获取已存在并且状态为:未启用和已暂停的最晚一条策略,更新为已启用
strategyRunningList.forEach(emsStrategyRunning -> {
emsStrategyRunning.setStatus(status);
emsStrategyRunningMapper.updateEmsStrategyRunning(emsStrategyRunning);
});
}
}
// 更新站点策略为启用
private void updateStrategyRunning(String siteId) {
// 获取是否有正在运行的策略,如果有则不更改
EmsStrategyRunning emsStrategyRunning = emsStrategyRunningMapper.getRunningStrategy(siteId);
if (emsStrategyRunning == null) {
// 获取已存在并且状态为:未启用和已暂停的最晚一条策略,更新为已启用
emsStrategyRunning = emsStrategyRunningMapper.getPendingStrategy(siteId);
emsStrategyRunning.setStatus(StrategyStatus.RUNNING.getCode());
emsStrategyRunningMapper.updateEmsStrategyRunning(emsStrategyRunning);
}
}
private EmsAlarmRecords addAlarmRecord(String siteId, String content,String level) {
EmsAlarmRecords emsAlarmRecords = new EmsAlarmRecords();
emsAlarmRecords.setSiteId(siteId);
emsAlarmRecords.setAlarmContent(content);
emsAlarmRecords.setAlarmLevel(level);
emsAlarmRecords.setAlarmStartTime(new Date());
emsAlarmRecords.setStatus(AlarmStatus.WAITING.getCode());
emsAlarmRecords.setDeviceType("TCP");
emsAlarmRecords.setCreateBy("system");
emsAlarmRecords.setCreateTime(new Date());
return emsAlarmRecords;
}
// 故障等级-告警等级匹配
private String getAlarmLevel(Integer faultLevel) {
if (ObjectUtils.isEmpty(faultLevel) || faultLevel < 1 || faultLevel > 3) {
logger.warn("非法故障等级:{},默认返回普通告警", faultLevel);
return AlarmLevelStatus.EMERGENCY.getCode();
}
switch (faultLevel) {
case 1: return AlarmLevelStatus.GENERAL.getCode();
case 2: return AlarmLevelStatus.SERIOUS.getCode();
case 3: return AlarmLevelStatus.EMERGENCY.getCode();
default:
logger.error("未匹配的故障等级:{}", faultLevel);
return AlarmLevelStatus.EMERGENCY.getCode();
}
}
// 自定义表达式解析器(仅支持简单运算符和逻辑关系)
public boolean executeWithParser(String conditionStr) {
if (conditionStr == null || conditionStr.isEmpty()) {
return false;
}
// 1. 拆分逻辑关系(提取 && 或 ||
List<String> logicRelations = new ArrayList<>();
Pattern logicPattern = Pattern.compile("(&&|\\|\\|)");
Matcher logicMatcher = logicPattern.matcher(conditionStr);
while (logicMatcher.find()) {
logicRelations.add(logicMatcher.group());
}
// 2. 拆分原子条件(如 "3.55>3.52"
String[] atomicConditions = logicPattern.split(conditionStr);
// 3. 解析每个原子条件并计算结果
List<Boolean> atomicResults = new ArrayList<>();
Pattern conditionPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*([><]=?|==)\\s*(\\d+\\.?\\d*)");
for (String atomic : atomicConditions) {
Matcher matcher = conditionPattern.matcher(atomic.trim());
if (!matcher.matches()) {
logger.error("无效的原子条件:{}", atomic);
return false;
}
double left = Double.parseDouble(matcher.group(1)); // 左值(最新值)
String operator = matcher.group(2); // 运算符
double right = Double.parseDouble(matcher.group(3)); // 右值(故障值)
// 执行比较
boolean result;
switch (operator) {
case ">":
result = left > right;
break;
case ">=":
result = left >= right;
break;
case "<":
result = left < right;
break;
case "<=":
result = left <= right;
break;
case "==":
result = left == right;
break;
default:
result = false;
break;
}
atomicResults.add(result);
}
// 4. 组合原子结果(根据逻辑关系)
boolean finalResult = atomicResults.get(0);
for (int i = 0; i < logicRelations.size(); i++) {
String relation = logicRelations.get(i);
boolean nextResult = atomicResults.get(i+1);
if ("&&".equals(relation)) {
finalResult = finalResult && nextResult;
} else if ("||".equals(relation)) {
finalResult = finalResult || nextResult;
}
}
return finalResult;
}
}

View File

@ -1,494 +0,0 @@
package com.xzzn.quartz.task;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.xzzn.common.core.modbus.ModbusProcessor;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
import com.xzzn.common.enums.ChargeStatus;
import com.xzzn.common.enums.DeviceCategory;
import com.xzzn.common.enums.SiteDevice;
import com.xzzn.common.enums.SocLimit;
import com.xzzn.common.enums.WorkStatus;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsAmmeterData;
import com.xzzn.ems.domain.EmsBatteryStack;
import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.EmsPcsSetting;
import com.xzzn.ems.domain.EmsStrategyLog;
import com.xzzn.ems.domain.EmsStrategyTemp;
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
import com.xzzn.ems.domain.vo.StrategyRunningVo;
import com.xzzn.ems.mapper.EmsAmmeterDataMapper;
import com.xzzn.ems.mapper.EmsBatteryStackMapper;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsPcsSettingMapper;
import com.xzzn.ems.mapper.EmsStrategyLogMapper;
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
import com.xzzn.ems.mapper.EmsStrategyTimeConfigMapper;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("strategyPoller")
public class StrategyPoller {
private static final Logger logger = LoggerFactory.getLogger(StrategyPoller.class);
private static final ConcurrentHashMap<Long, Boolean> strategyLocks = new ConcurrentHashMap<>();
// SOC 上下限值默认为0%-100%
private static final BigDecimal SOC_DOWN = new BigDecimal(0);
private static final BigDecimal SOC_UP = new BigDecimal(100);
// 逆变器功率下限值默认为30kW
private static final BigDecimal ANTI_REVERSE_THRESHOLD = new BigDecimal(30);
// 逆变器下限值范围默认为20%
private static final BigDecimal ANTI_REVERSE_RANGE_PERCENT = new BigDecimal(20);
// 逆变器功率上限值默认为100kW
private static final BigDecimal ANTI_REVERSE_UP = new BigDecimal(100);
// PCS功率降幅默认为10%
private static final BigDecimal ANTI_REVERSE_POWER_DOWN_PERCENT = new BigDecimal(10);
@Autowired
private EmsStrategyRunningMapper emsStrategyRunningMapper;
@Autowired
private EmsStrategyTempMapper emsStrategyTempMapper;
@Autowired
private EmsStrategyTimeConfigMapper emsStrategyTimeConfigMapper;
@Autowired
private EmsBatteryStackMapper emsBatteryStackMapper;
@Autowired
private EmsDevicesSettingMapper emsDevicesMapper;
@Autowired
private EmsPcsSettingMapper emsPcsSettingMapper;
@Autowired
private EmsAmmeterDataMapper emsAmmeterDataMapper;
@Autowired
private EmsStrategyLogMapper emsStrategyLogMapper;
@Autowired
private ModbusProcessor modbusProcessor;
@Resource(name = "modbusExecutor")
private ExecutorService modbusExecutor;
public void pollAllDevices() {
logger.info("开始执行运行策略数据轮询...");
List<StrategyRunningVo> strategyRunningVoList = emsStrategyRunningMapper.getPendingPollerStrategy(null);
strategyRunningVoList.forEach(strategyVo -> {
Long strategyId = strategyVo.getId();
if (strategyLocks.putIfAbsent(strategyId, true) == null) {
// 使用共享的modbusExecutor串行执行避免与ModbusPoller并发访问导致通讯故障
modbusExecutor.submit(() -> {
try {
processData(strategyVo);
} catch (Exception e) {
logger.error("运行策略{}轮询异常", strategyVo.getId(), e);
} finally {
logger.info("运行策略{}轮询任务执行完成,释放锁", strategyVo.getId());
strategyLocks.remove(strategyId);
}
});
} else {
logger.info("策略{}已在处理中,跳过重复执行", strategyId);
}
});
}
// 处理获取到的运行策略数据modbus发送指定的命令控制设备
private void processData(StrategyRunningVo strategyVo) {
logger.info("运行策略数据处理开始");
// 根据运行策略获取主副策略的模板数据
Long mainStrategyId = strategyVo.getMainStrategyId();
Long auxStrategyId = strategyVo.getAuxStrategyId();
String siteId = strategyVo.getSiteId();
// 处理主策略数据
if (mainStrategyId != null && StringUtils.isNotBlank(siteId)) {
dealStrategyCurveData(mainStrategyId, siteId);
}
// 处理副策略数据
if (auxStrategyId != null && StringUtils.isNotBlank(siteId)) {
dealStrategyCurveData(auxStrategyId, siteId);
}
logger.info("运行策略轮询处理结束");
}
private void dealStrategyCurveData(Long strategyId, String siteId) {
// 1.获取当前策略的所有模板
List<Map<String, String>> temps = emsStrategyTempMapper.getTempNameList(strategyId, siteId);
if (CollectionUtils.isEmpty(temps)) {
logger.info("当前站点: {}, 策略: {} 没有模板数据", siteId, strategyId);
return;
}
for (Map<String, String> temp : temps) {
// 2.查询当月配置的运行策略
String tempId = temp.get("templateId");
int month = LocalDateTime.now().getMonthValue();
List<EmsStrategyTimeConfig> timeConfigs = emsStrategyTimeConfigMapper.getTimeConfigByTempIdAndMonth(tempId, month);
if (CollectionUtils.isEmpty(timeConfigs)) {
continue;
}
logger.info("当前站点: {}, 策略: {}, {}月配置模版:{}", siteId, strategyId, month, tempId);
// 3.查询当月配置的运行策略时间阶段数据
List<EmsStrategyTemp> powerConfig = emsStrategyTempMapper.selectStrategyTempByTempId(tempId);
if (CollectionUtils.isEmpty(powerConfig)) {
logger.info("当前站点: {}, 策略: {}, 模版:{} 未配置数据", siteId, strategyId, tempId);
continue;
}
// 4.遍历时间段数据,判断当前时间是否在时间段内,在时间段内的进行处理
for (EmsStrategyTemp emsStrategyTemp : powerConfig) {
if (emsStrategyTemp.getStartTime() == null || emsStrategyTemp.getEndTime() == null) {
logger.info("当前站点: {}, 策略: {}, 模版:{} 未配置时间阶段数据", siteId, strategyId, tempId);
continue;
}
// 判断当前时间是否在时间段内
if (!isTimeInRange(LocalTime.now(), emsStrategyTemp.getStartTime(), emsStrategyTemp.getEndTime())) {
logger.info("当前站点: {}, 策略: {}, 时间段:{} 不在时间段内", siteId, strategyId, emsStrategyTemp.getStartTime() + "-" + emsStrategyTemp.getEndTime());
continue;
}
// 查询PCS设备信息
EmsDevicesSetting queryDevices = new EmsDevicesSetting();
queryDevices.setSiteId(siteId);
queryDevices.setDeviceCategory(DeviceCategory.PCS.getCode());
List<EmsDevicesSetting> pcsDeviceList = emsDevicesMapper.selectEmsDevicesSettingList(queryDevices);
if (CollectionUtils.isEmpty(pcsDeviceList)) {
logger.info("当前站点: {} 未配置PCS设备", siteId);
continue;
}
// 判断SOC上下限
if (isSocInRange(emsStrategyTemp)) {
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower().divide(new BigDecimal(pcsDeviceList.size()));
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
EmsPcsSetting pcsSetting = emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(pcsDevice.getId());
if (pcsSetting == null || pcsSetting.getClusterNum() < 1) {
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
continue;
}
// 功率默认放大10倍平均功率值根据电池簇数量进行平均分配
avgChargeDischargePower = avgChargeDischargePower.multiply(new BigDecimal(10)).divide(new BigDecimal(pcsSetting.getClusterNum()));
// 根据充电状态,处理数据
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
// 发送Modbus命令控制设备-充电
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.CHARGING, avgChargeDischargePower, emsStrategyTemp, false, null);
} else if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
boolean needAntiReverseFlow = false;
Integer powerDownType = null;
BigDecimal chargeDischargePower = avgChargeDischargePower;
// 查询策略运行日志
EmsStrategyLog lastStrategyLog = getLastStrategyLog(pcsDevice.getDeviceId(), emsStrategyTemp);
if (lastStrategyLog != null) {
// 如果当前时间段已经进入待机状态,则不处理
if (ChargeStatus.STANDBY.getCode().equals(lastStrategyLog.getChargeStatus())) {
continue;
}
chargeDischargePower = lastStrategyLog.getChargeDischargePower();
powerDownType = lastStrategyLog.getPowerDownType();
}
// 查询电网电表的正向有功功率,36kW-50kW范围内稳定运行低于36kW降功率高于50kW增加功率
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
if (emsAmmeterData == null || emsAmmeterData.getTotalActivePower() == null) {
logger.info("当前站点: {}, 未获取到最新电表数据", emsStrategyTemp.getSiteId());
} else {
// 判断是否需要防逆流
needAntiReverseFlow = isNeedAntiReverseFlow(emsAmmeterData.getTotalActivePower());
BigDecimal power = avgChargeDischargePower.multiply(ANTI_REVERSE_POWER_DOWN_PERCENT).divide(new BigDecimal(100));
if (needAntiReverseFlow) {
// 降功率
chargeDischargePower = chargeDischargePower.subtract(power);
powerDownType = 0;
} else {
// 判断是否需要增加功率,
if (powerDownType != null && emsAmmeterData.getTotalActivePower().compareTo(ANTI_REVERSE_UP) > 0) {
if (chargeDischargePower.compareTo(avgChargeDischargePower) == 0) {
// 功率增加到平均值则停止
continue;
}
// 增加功率
chargeDischargePower = chargeDischargePower.add(power);
powerDownType = 1;
needAntiReverseFlow = true;
}
}
}
if (BigDecimal.ZERO.compareTo(chargeDischargePower) == 0) {
// 如果已经降功率到0则设备直接待机
// 发送Modbus命令控制设备-待机
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, needAntiReverseFlow, powerDownType);
} else {
// 发送Modbus命令控制设备-放电
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.DISCHARGING, chargeDischargePower, emsStrategyTemp, needAntiReverseFlow, powerDownType);
}
} else {
// 发送Modbus命令控制设备-待机
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, false, null);
}
}
} else {
// 发送Modbus命令控制设备-待机
sendModbusCommand(pcsDeviceList, null, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, false, null);
}
}
}
}
private void saveStrategyLog(String deviceId, BigDecimal chargeDischargePower, String chargeStatus,
EmsStrategyTemp strategyTemp, boolean needAntiReverseFlow, Integer powerDownType) {
EmsStrategyLog log = new EmsStrategyLog();
log.setStrategyId(strategyTemp.getStrategyId());
log.setTemplateId(strategyTemp.getTemplateId());
log.setSiteId(strategyTemp.getSiteId());
log.setDeviceId(deviceId);
log.setStartTime(strategyTemp.getStartTime());
log.setEndTime(strategyTemp.getEndTime());
log.setChargeDischargePower(chargeDischargePower);
log.setChargeStatus(chargeStatus);
log.setExecutionDate(DateUtils.toDate(LocalDateTime.now()));
log.setAntiReverse(needAntiReverseFlow ? 1 : 0);
log.setPowerDownType(powerDownType);
emsStrategyLogMapper.insertEmsStrategyLog(log);
}
private List<EmsStrategyLog> getStrategyLog(String deviceId, String chargeStatus,
EmsStrategyTemp strategyTemp, boolean needAntiReverseFlow) {
EmsStrategyLog query = new EmsStrategyLog();
query.setStrategyId(strategyTemp.getStrategyId());
query.setTemplateId(strategyTemp.getTemplateId());
query.setSiteId(strategyTemp.getSiteId());
query.setDeviceId(deviceId);
query.setStartTime(strategyTemp.getStartTime());
query.setEndTime(strategyTemp.getEndTime());
query.setChargeStatus(chargeStatus);
query.setExecutionDate(DateUtils.toDate(LocalDateTime.now()));
query.setAntiReverse(needAntiReverseFlow ? 1 : 0);
return emsStrategyLogMapper.selectEmsStrategyLogList(query);
}
private EmsStrategyLog getLastStrategyLog(String deviceId, EmsStrategyTemp strategyTemp) {
EmsStrategyLog query = new EmsStrategyLog();
query.setStrategyId(strategyTemp.getStrategyId());
query.setTemplateId(strategyTemp.getTemplateId());
query.setSiteId(strategyTemp.getSiteId());
query.setDeviceId(deviceId);
query.setStartTime(strategyTemp.getStartTime());
query.setEndTime(strategyTemp.getEndTime());
query.setExecutionDate(DateUtils.toDate(LocalDateTime.now()));
return emsStrategyLogMapper.getLastStrategyLog(query);
}
private boolean isNeedAntiReverseFlow(BigDecimal totalActivePower) {
// 获取当前设定的防逆流阈值(30kW)
BigDecimal threshold = ANTI_REVERSE_THRESHOLD;
// 计算20%范围的上限(36kW)
BigDecimal upperLimit = threshold.multiply(ANTI_REVERSE_RANGE_PERCENT).divide(new BigDecimal(100)).add(threshold);
// 判断电网电表正向有功功率是否小于36kW(接近30kW的20%范围)
return totalActivePower.compareTo(upperLimit) < 0;
}
public List<WriteTagConfig> getSwitchDeviceWriteTags(EmsPcsSetting pcsSetting, String workStatus) {
List<WriteTagConfig> writeTags = new ArrayList<>();
BigDecimal power;
if (WorkStatus.NORMAL.getCode().equals(workStatus)) {
// 开机先发送开机指令再发送有功功率给定值
WriteTagConfig writeTag = new WriteTagConfig();
writeTag.setAddress(pcsSetting.getPointAddress());
writeTag.setValue(pcsSetting.getStartCommand());
writeTags.add(writeTag);
power = pcsSetting.getStartPower();
} else {
// 关机
power = pcsSetting.getStopPower();
}
JSONArray array = JSON.parseArray(pcsSetting.getClusterPointAddress());
for (int i = 0; i < pcsSetting.getClusterNum(); i++) {
Object clusterPointAddress = array.get(i);
WriteTagConfig clusterWriteTag = new WriteTagConfig();
clusterWriteTag.setAddress(String.valueOf(clusterPointAddress));
// 电池簇PCS有功功率给定默认置0
if (power == null) {
power = BigDecimal.ZERO;
}
clusterWriteTag.setValue(power);
writeTags.add(clusterWriteTag);
}
if (WorkStatus.STOP.getCode().equals(workStatus)) {
// 关机先发送有功功率给定值再发送关机指令
WriteTagConfig writeTag = new WriteTagConfig();
writeTag.setAddress(pcsSetting.getPointAddress());
writeTag.setValue(pcsSetting.getStopCommand());
writeTags.add(writeTag);
}
return writeTags;
}
public List<WriteTagConfig> getWriteTags(EmsPcsSetting pcsSetting, BigDecimal chargeDischargePower) {
List<WriteTagConfig> writeTags = new ArrayList<>();
JSONArray array = JSON.parseArray(pcsSetting.getClusterPointAddress());
for (int i = 0; i < pcsSetting.getClusterNum(); i++) {
Object clusterPointAddress = array.get(i);
WriteTagConfig clusterWriteTag = new WriteTagConfig();
clusterWriteTag.setAddress(String.valueOf(clusterPointAddress));
clusterWriteTag.setValue(chargeDischargePower);
writeTags.add(clusterWriteTag);
}
return writeTags;
}
public DeviceConfig getDeviceConfig(String siteId, String deviceId, EmsDevicesSetting device, EmsPcsSetting pcsSetting, BigDecimal chargeDischargePower, int writeType) {
if (Objects.isNull(pcsSetting)) {
pcsSetting = emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(device.getId());
if (pcsSetting == null) {
logger.info("当前站点: {}, PCS设备: {} 未找到对应PCS配置", siteId, deviceId);
return null;
}
}
if (device.getIpPort() == null || device.getSlaveId() == null) {
logger.info("当前站点: {}, PCS设备: {} 未配置IP端口或从站号", siteId, deviceId);
return null;
}
DeviceConfig deviceConfig = new DeviceConfig();
deviceConfig.setDeviceNumber(device.getDeviceId());
deviceConfig.setDeviceName(device.getDeviceName());
deviceConfig.setSlaveId(device.getSlaveId().intValue());
deviceConfig.setHost(device.getIpAddress());
deviceConfig.setPort(device.getIpPort().intValue());
deviceConfig.setWriteTags(writeType == 0 ? getWriteTags(pcsSetting, chargeDischargePower) : getSwitchDeviceWriteTags(pcsSetting, device.getWorkStatus()));
return deviceConfig;
}
private void sendModbusCommand(List<EmsDevicesSetting> pcsDeviceList, EmsPcsSetting pcsSetting, ChargeStatus chargeStatus, BigDecimal chargeDischargePower,
EmsStrategyTemp emsStrategyTemp, boolean needAntiReverseFlow, Integer powerDownType) {
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
String siteId = pcsDevice.getSiteId();
String deviceId = pcsDevice.getDeviceId();
List<EmsStrategyLog> strategyLogList = getStrategyLog(deviceId, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow);
if (CollectionUtils.isNotEmpty(strategyLogList)) {
boolean isExist = true;
if (ChargeStatus.DISCHARGING.equals(chargeStatus) && needAntiReverseFlow) {
isExist = false;
}
if (isExist) {
logger.info("当前站点: {}, PCS设备: {} 当前时间段已存在策略执行记录,不再重复执行", siteId, deviceId);
continue;
}
}
// 每次操作先判断设备工作状态
if (StringUtils.isEmpty(pcsDevice.getWorkStatus()) || WorkStatus.ABNORMAL.getCode().equals(pcsDevice.getWorkStatus())) {
// 设备故障,不发送指令
continue;
} else if (WorkStatus.STOP.getCode().equals(pcsDevice.getWorkStatus())) {
// 设备停机
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
// 待机,则不写入功率值
continue;
} else {
// 充、放电,则先开机设备
switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL);
continue;
}
}
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting, chargeDischargePower, 0);
if (deviceConfig == null) {
continue;
}
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
if (!result) {
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
continue;
} else {
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
// 待机,先写功率值,再关机
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP)) {
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, WorkStatus.STOP.getInfo());
continue;
}
}
}
// 记录策略执行日志
saveStrategyLog(deviceId, chargeDischargePower, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow, powerDownType);
}
}
//设备开关机
private boolean switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
String siteId = pcsDevice.getSiteId();
String deviceId = pcsDevice.getDeviceId();
pcsDevice.setWorkStatus(workStatus.getCode());
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
if (deviceConfig == null) {
return false;
}
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
if (!result) {
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceConfig, workStatus.getInfo());
}
return result;
}
// 判断当前时间是否在时间范围内
private static boolean isTimeInRange(LocalTime now, Date startTime, Date endTime) {
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
LocalTime startLocalTime = startTime.toInstant()
.atZone(zoneId)
.toLocalTime();
LocalTime endLocalTime = endTime.toInstant()
.atZone(zoneId)
.toLocalTime();
return now.equals(startLocalTime) || (now.isAfter(startLocalTime) && now.isBefore(endLocalTime));
}
// 判断SOC上限和下限
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp) {
BigDecimal socDown = SOC_DOWN;
BigDecimal socUp = SOC_UP;
if (SocLimit.ON.getCode().equals(emsStrategyTemp.getSdcLimit())) {
socDown = emsStrategyTemp.getSdcDown();
socUp = emsStrategyTemp.getSdcUp();
}
// 查询电池堆(BMSD) SOC
EmsBatteryStack emsBatteryStack = emsBatteryStackMapper.getSiteSumStackInfo(emsStrategyTemp.getSiteId());
if (emsBatteryStack == null || emsBatteryStack.getStackSoc() == null) {
return true;
}
// 充电阶段判断SOC上限值
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus()) && emsBatteryStack.getStackSoc().compareTo(socUp) >= 0) {
return false;
}
// 放电阶段判断SOC下限值
if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus()) && emsBatteryStack.getStackSoc().compareTo(socDown) <= 0) {
return false;
}
return true;
}
}

View File

@ -60,25 +60,4 @@ public class CronUtils
throw new IllegalArgumentException(e.getMessage());
}
}
/**
* 返回当前时间到下一次执行时间间隔的毫秒
*/
public static long getNextExecutionIntervalMillis(String cronExpression)
{
try
{
CronExpression cron = new CronExpression(cronExpression);
Date now = new Date();
Date nextExecution = cron.getNextValidTimeAfter(now);
Date nextExecution2 = cron.getNextValidTimeAfter(nextExecution);
return nextExecution2.getTime() - nextExecution.getTime();
}
catch (ParseException e)
{
throw new IllegalArgumentException(e.getMessage());
}
}
}

View File

@ -1,117 +0,0 @@
package com.xzzn.ems.domain;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 告警点位匹配数据对象 ems_alarm_match_data
*
* @author xzzn
* @date 2025-09-22
*/
public class EmsAlarmMatchData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 告警点位 */
@Excel(name = "告警点位")
private String point;
/** 告警值 */
@Excel(name = "告警值")
private Long alarmData;
/** 告警描述 */
@Excel(name = "告警描述")
private String alarmDescription;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备类型 */
@Excel(name = "设备类型")
private String deviceCategory;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setPoint(String point)
{
this.point = point;
}
public String getPoint()
{
return point;
}
public void setAlarmData(Long alarmData)
{
this.alarmData = alarmData;
}
public Long getAlarmData()
{
return alarmData;
}
public void setAlarmDescription(String alarmDescription)
{
this.alarmDescription = alarmDescription;
}
public String getAlarmDescription()
{
return alarmDescription;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceCategory(String deviceCategory)
{
this.deviceCategory = deviceCategory;
}
public String getDeviceCategory()
{
return deviceCategory;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("point", getPoint())
.append("alarmData", getAlarmData())
.append("alarmDescription", getAlarmDescription())
.append("siteId", getSiteId())
.append("deviceCategory", getDeviceCategory())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -24,8 +24,8 @@ public class EmsAlarmRecords extends BaseEntity
@Excel(name = "设备类型")
private String deviceType;
/** 告警等级A-提示 B-一般 C-严重 D紧急 */
@Excel(name = "告警等级A-提示 B-一般 C-严重 D紧急")
/** 告警等级 */
@Excel(name = "告警等级")
private String alarmLevel;
/** 告警内容 */
@ -42,12 +42,8 @@ public class EmsAlarmRecords extends BaseEntity
@Excel(name = "告警结束时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date alarmEndTime;
/** 告警点位 */
@Excel(name = "告警点位")
private String alarmPoint;
/** 状态:0-待处理 1-已处理 2-处理中 */
@Excel(name = "状态:0-待处理 1-已处理 2-处理中")
/** 状态 */
@Excel(name = "状态")
private String status;
/** 站点id */
@ -58,6 +54,10 @@ public class EmsAlarmRecords extends BaseEntity
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 设备名称,用于标识设备 */
@Excel(name = "设备名称,用于标识设备")
private String deviceName;
/** 工单号规则T+日期+6位随机 */
@Excel(name = "工单号", readConverterExp = "规=则T+日期+6位随机")
private String ticketNo;
@ -122,16 +122,6 @@ public class EmsAlarmRecords extends BaseEntity
return alarmEndTime;
}
public void setAlarmPoint(String alarmPoint)
{
this.alarmPoint = alarmPoint;
}
public String getAlarmPoint()
{
return alarmPoint;
}
public void setStatus(String status)
{
this.status = status;
@ -162,16 +152,24 @@ public class EmsAlarmRecords extends BaseEntity
return deviceId;
}
public void setTicketNo(String ticketNo)
public void setDeviceName(String deviceName)
{
this.ticketNo = ticketNo;
this.deviceName = deviceName;
}
public String getTicketNo()
public String getDeviceName()
{
return deviceName;
}
public String getTicketNo() {
return ticketNo;
}
public void setTicketNo(String ticketNo) {
this.ticketNo = ticketNo;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -181,7 +179,6 @@ public class EmsAlarmRecords extends BaseEntity
.append("alarmContent", getAlarmContent())
.append("alarmStartTime", getAlarmStartTime())
.append("alarmEndTime", getAlarmEndTime())
.append("alarmPoint", getAlarmPoint())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
@ -190,7 +187,8 @@ public class EmsAlarmRecords extends BaseEntity
.append("remark", getRemark())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("deviceName", getDeviceName())
.append("ticketNo", getTicketNo())
.toString();
}
}
}

View File

@ -1,15 +1,11 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import com.xzzn.common.utils.StringUtils;
import java.math.BigDecimal;
import java.util.Date;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 电池簇数据对象 ems_battery_cluster
@ -24,13 +20,8 @@ public class EmsBatteryCluster extends BaseEntity
/** */
private Long id;
/** 数据更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataUpdateTime;
/** 工作状态0-运行 1-停机 2-故障 */
@Excel(name = "工作状态0-运行 1-停机 2-故障")
/** 工作状态0-正常 1-异常 2-停止 */
@Excel(name = "工作状态0-正常 1-异常 2-停止")
private String workStatus;
/** 与PCS通信状态0-正常 1-通信中断 2-异常 */
@ -155,7 +146,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最高单体电压对应点号 */
@Excel(name = "最高单体电压对应点号")
private String maxCellVoltageId;
private Long maxCellVoltageId;
/** 最低单体电压 */
@Excel(name = "最低单体电压")
@ -163,7 +154,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最低单体电压对应点号 */
@Excel(name = "最低单体电压对应点号")
private String minCellVoltageId;
private Long minCellVoltageId;
/** 最高单体温度 */
@Excel(name = "最高单体温度")
@ -171,7 +162,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最高单体温度对应点号 */
@Excel(name = "最高单体温度对应点号")
private String maxCellTempId;
private Long maxCellTempId;
/** 最低单体温度 */
@Excel(name = "最低单体温度")
@ -179,7 +170,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最低单体温度对应点号 */
@Excel(name = "最低单体温度对应点号")
private String minCellTempId;
private Long minCellTempId;
/** 最高单体SOC */
@Excel(name = "最高单体SOC")
@ -187,7 +178,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最高单体SOC对应点号 */
@Excel(name = "最高单体SOC对应点号")
private String maxCellSocId;
private Long maxCellSocId;
/** 最低单体SOC */
@Excel(name = "最低单体SOC")
@ -195,7 +186,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最低单体SOC对应点号 */
@Excel(name = "最低单体SOC对应点号")
private String minCellSocId;
private Long minCellSocId;
/** 最高单体SOH */
@Excel(name = "最高单体SOH")
@ -203,7 +194,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最高单体SOH对应点号 */
@Excel(name = "最高单体SOH对应点号")
private String maxCellSohId;
private Long maxCellSohId;
/** 最低单体SOH */
@Excel(name = "最低单体SOH")
@ -211,7 +202,7 @@ public class EmsBatteryCluster extends BaseEntity
/** 最低单体SOH对应点号 */
@Excel(name = "最低单体SOH对应点号")
private String minCellSohId;
private Long minCellSohId;
/** 单次累计充电电量 */
@Excel(name = "单次累计充电电量")
@ -231,14 +222,6 @@ public class EmsBatteryCluster extends BaseEntity
return id;
}
public Date getDataUpdateTime() {
return dataUpdateTime;
}
public void setDataUpdateTime(Date dataUpdateTime) {
this.dataUpdateTime = dataUpdateTime;
}
public void setWorkStatus(String workStatus)
{
this.workStatus = workStatus;
@ -549,12 +532,12 @@ public class EmsBatteryCluster extends BaseEntity
return maxCellVoltage;
}
public void setMaxCellVoltageId(String maxCellVoltageId)
public void setMaxCellVoltageId(Long maxCellVoltageId)
{
this.maxCellVoltageId = StringUtils.fillThreeDigits(maxCellVoltageId);
this.maxCellVoltageId = maxCellVoltageId;
}
public String getMaxCellVoltageId()
public Long getMaxCellVoltageId()
{
return maxCellVoltageId;
}
@ -569,12 +552,12 @@ public class EmsBatteryCluster extends BaseEntity
return minCellVoltage;
}
public void setMinCellVoltageId(String minCellVoltageId)
public void setMinCellVoltageId(Long minCellVoltageId)
{
this.minCellVoltageId = StringUtils.fillThreeDigits(minCellVoltageId);
this.minCellVoltageId = minCellVoltageId;
}
public String getMinCellVoltageId()
public Long getMinCellVoltageId()
{
return minCellVoltageId;
}
@ -589,12 +572,12 @@ public class EmsBatteryCluster extends BaseEntity
return maxCellTemp;
}
public void setMaxCellTempId(String maxCellTempId)
public void setMaxCellTempId(Long maxCellTempId)
{
this.maxCellTempId = StringUtils.fillThreeDigits(maxCellTempId);
this.maxCellTempId = maxCellTempId;
}
public String getMaxCellTempId()
public Long getMaxCellTempId()
{
return maxCellTempId;
}
@ -609,12 +592,12 @@ public class EmsBatteryCluster extends BaseEntity
return minCellTemp;
}
public void setMinCellTempId(String minCellTempId)
public void setMinCellTempId(Long minCellTempId)
{
this.minCellTempId = StringUtils.fillThreeDigits(minCellTempId);
this.minCellTempId = minCellTempId;
}
public String getMinCellTempId()
public Long getMinCellTempId()
{
return minCellTempId;
}
@ -629,12 +612,12 @@ public class EmsBatteryCluster extends BaseEntity
return maxCellSoc;
}
public void setMaxCellSocId(String maxCellSocId)
public void setMaxCellSocId(Long maxCellSocId)
{
this.maxCellSocId = StringUtils.fillThreeDigits(maxCellSocId);
this.maxCellSocId = maxCellSocId;
}
public String getMaxCellSocId()
public Long getMaxCellSocId()
{
return maxCellSocId;
}
@ -649,12 +632,12 @@ public class EmsBatteryCluster extends BaseEntity
return minCellSoc;
}
public void setMinCellSocId(String minCellSocId)
public void setMinCellSocId(Long minCellSocId)
{
this.minCellSocId = StringUtils.fillThreeDigits(minCellSocId);
this.minCellSocId = minCellSocId;
}
public String getMinCellSocId()
public Long getMinCellSocId()
{
return minCellSocId;
}
@ -669,12 +652,12 @@ public class EmsBatteryCluster extends BaseEntity
return maxCellSoh;
}
public void setMaxCellSohId(String maxCellSohId)
public void setMaxCellSohId(Long maxCellSohId)
{
this.maxCellSohId = StringUtils.fillThreeDigits(maxCellSohId);
this.maxCellSohId = maxCellSohId;
}
public String getMaxCellSohId()
public Long getMaxCellSohId()
{
return maxCellSohId;
}
@ -689,12 +672,12 @@ public class EmsBatteryCluster extends BaseEntity
return minCellSoh;
}
public void setMinCellSohId(String minCellSohId)
public void setMinCellSohId(Long minCellSohId)
{
this.minCellSohId = StringUtils.fillThreeDigits(minCellSohId);
this.minCellSohId = minCellSohId;
}
public String getMinCellSohId()
public Long getMinCellSohId()
{
return minCellSohId;
}

View File

@ -1,14 +1,12 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 单体电池实时数据对象 ems_battery_data
@ -72,10 +70,6 @@ public class EmsBatteryData extends BaseEntity
@Excel(name = "单体电池内阻")
private BigDecimal interResistance;
/** 单体电池电流 */
@Excel(name = "单体电池电流")
private BigDecimal current;
public void setId(Long id)
{
this.id = id;
@ -206,14 +200,6 @@ public class EmsBatteryData extends BaseEntity
return interResistance;
}
public BigDecimal getCurrent() {
return current;
}
public void setCurrent(BigDecimal current) {
this.current = current;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -235,7 +221,6 @@ public class EmsBatteryData extends BaseEntity
.append("deviceId", getDeviceId())
.append("clusterDeviceId", getClusterDeviceId())
.append("interResistance", getInterResistance())
.append("current", getCurrent())
.toString();
}
}

View File

@ -1,257 +0,0 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.Date;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 单体电池天级数据对象 ems_battery_data_day
*
* @author xzzn
* @date 2025-08-20
*/
public class EmsBatteryDataDay extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 电池堆 */
@Excel(name = "电池堆")
private String batteryPack;
/** 电池簇 */
@Excel(name = "电池簇")
private String batteryCluster;
/** 单体编号 */
@Excel(name = "单体编号")
private String batteryCellId;
/** 电压 (V) */
@Excel(name = "电压 (V)")
private BigDecimal voltage;
/** 温度 (℃) */
@Excel(name = "温度 (℃)")
private BigDecimal temperature;
/** SOC (%) */
@Excel(name = "SOC (%)")
private BigDecimal soc;
/** SOH (%) */
@Excel(name = "SOH (%)")
private BigDecimal soh;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataTimestamp;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 簇设备id */
@Excel(name = "簇设备id")
private String clusterDeviceId;
/** 单体电池内阻 */
@Excel(name = "单体电池内阻")
private BigDecimal interResistance;
/** 天级时间维度 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "天级时间维度", width = 30, dateFormat = "yyyy-MM-dd")
private Date dayTime;
/** 单体电池电流 */
@Excel(name = "单体电池电流")
private BigDecimal current;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setBatteryPack(String batteryPack)
{
this.batteryPack = batteryPack;
}
public String getBatteryPack()
{
return batteryPack;
}
public void setBatteryCluster(String batteryCluster)
{
this.batteryCluster = batteryCluster;
}
public String getBatteryCluster()
{
return batteryCluster;
}
public void setBatteryCellId(String batteryCellId)
{
this.batteryCellId = batteryCellId;
}
public String getBatteryCellId()
{
return batteryCellId;
}
public void setVoltage(BigDecimal voltage)
{
this.voltage = voltage;
}
public BigDecimal getVoltage()
{
return voltage;
}
public void setTemperature(BigDecimal temperature)
{
this.temperature = temperature;
}
public BigDecimal getTemperature()
{
return temperature;
}
public void setSoc(BigDecimal soc)
{
this.soc = soc;
}
public BigDecimal getSoc()
{
return soc;
}
public void setSoh(BigDecimal soh)
{
this.soh = soh;
}
public BigDecimal getSoh()
{
return soh;
}
public void setDataTimestamp(Date dataTimestamp)
{
this.dataTimestamp = dataTimestamp;
}
public Date getDataTimestamp()
{
return dataTimestamp;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setClusterDeviceId(String clusterDeviceId)
{
this.clusterDeviceId = clusterDeviceId;
}
public String getClusterDeviceId()
{
return clusterDeviceId;
}
public void setInterResistance(BigDecimal interResistance)
{
this.interResistance = interResistance;
}
public BigDecimal getInterResistance()
{
return interResistance;
}
public void setDayTime(Date dayTime)
{
this.dayTime = dayTime;
}
public Date getDayTime()
{
return dayTime;
}
public BigDecimal getCurrent() {
return current;
}
public void setCurrent(BigDecimal current) {
this.current = current;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("batteryPack", getBatteryPack())
.append("batteryCluster", getBatteryCluster())
.append("batteryCellId", getBatteryCellId())
.append("voltage", getVoltage())
.append("temperature", getTemperature())
.append("soc", getSoc())
.append("soh", getSoh())
.append("dataTimestamp", getDataTimestamp())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("clusterDeviceId", getClusterDeviceId())
.append("interResistance", getInterResistance())
.append("dayTime", getDayTime())
.append("current", getCurrent())
.toString();
}
}

View File

@ -1,242 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 单体电池小时级数据对象 ems_battery_data_hour
*
* @author xzzn
* @date 2025-08-19
*/
public class EmsBatteryDataHour extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 电池堆 */
@Excel(name = "电池堆")
private String batteryPack;
/** 电池簇 */
@Excel(name = "电池簇")
private String batteryCluster;
/** 单体编号 */
@Excel(name = "单体编号")
private String batteryCellId;
/** 电压 (V) */
@Excel(name = "电压 (V)")
private BigDecimal voltage;
/** 温度 (℃) */
@Excel(name = "温度 (℃)")
private BigDecimal temperature;
/** SOC (%) */
@Excel(name = "SOC (%)")
private BigDecimal soc;
/** SOH (%) */
@Excel(name = "SOH (%)")
private BigDecimal soh;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataTimestamp;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 簇设备id */
@Excel(name = "簇设备id")
private String clusterDeviceId;
/** 单体电池内阻 */
@Excel(name = "单体电池内阻")
private BigDecimal interResistance;
/** 小时级时间维度 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "小时级时间维度", width = 30, dateFormat = "yyyy-MM-dd")
private Date hourTime;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setBatteryPack(String batteryPack)
{
this.batteryPack = batteryPack;
}
public String getBatteryPack()
{
return batteryPack;
}
public void setBatteryCluster(String batteryCluster)
{
this.batteryCluster = batteryCluster;
}
public String getBatteryCluster()
{
return batteryCluster;
}
public void setBatteryCellId(String batteryCellId)
{
this.batteryCellId = batteryCellId;
}
public String getBatteryCellId()
{
return batteryCellId;
}
public void setVoltage(BigDecimal voltage)
{
this.voltage = voltage;
}
public BigDecimal getVoltage()
{
return voltage;
}
public void setTemperature(BigDecimal temperature)
{
this.temperature = temperature;
}
public BigDecimal getTemperature()
{
return temperature;
}
public void setSoc(BigDecimal soc)
{
this.soc = soc;
}
public BigDecimal getSoc()
{
return soc;
}
public void setSoh(BigDecimal soh)
{
this.soh = soh;
}
public BigDecimal getSoh()
{
return soh;
}
public void setDataTimestamp(Date dataTimestamp)
{
this.dataTimestamp = dataTimestamp;
}
public Date getDataTimestamp()
{
return dataTimestamp;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setClusterDeviceId(String clusterDeviceId)
{
this.clusterDeviceId = clusterDeviceId;
}
public String getClusterDeviceId()
{
return clusterDeviceId;
}
public void setInterResistance(BigDecimal interResistance)
{
this.interResistance = interResistance;
}
public BigDecimal getInterResistance()
{
return interResistance;
}
public void setHourTime(Date hourTime)
{
this.hourTime = hourTime;
}
public Date getHourTime()
{
return hourTime;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("batteryPack", getBatteryPack())
.append("batteryCluster", getBatteryCluster())
.append("batteryCellId", getBatteryCellId())
.append("voltage", getVoltage())
.append("temperature", getTemperature())
.append("soc", getSoc())
.append("soh", getSoh())
.append("dataTimestamp", getDataTimestamp())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("clusterDeviceId", getClusterDeviceId())
.append("interResistance", getInterResistance())
.append("hourTime", getHourTime())
.toString();
}
}

View File

@ -1,226 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 单体电池分钟级数据对象 ems_battery_data_minutes
*
* @author xzzn
* @date 2025-08-18
*/
public class EmsBatteryDataMinutes extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 电池堆 */
@Excel(name = "电池堆")
private String batteryPack;
/** 电池簇 */
@Excel(name = "电池簇")
private String batteryCluster;
/** 单体编号 */
@Excel(name = "单体编号")
private String batteryCellId;
/** 电压 (V) */
@Excel(name = "电压 (V)")
private BigDecimal voltage;
/** 温度 (℃) */
@Excel(name = "温度 (℃)")
private BigDecimal temperature;
/** SOC (%) */
@Excel(name = "SOC (%)")
private BigDecimal soc;
/** SOH (%) */
@Excel(name = "SOH (%)")
private BigDecimal soh;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataTimestamp;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 簇设备id */
@Excel(name = "簇设备id")
private String clusterDeviceId;
/** 单体电池内阻 */
@Excel(name = "单体电池内阻")
private BigDecimal interResistance;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setBatteryPack(String batteryPack)
{
this.batteryPack = batteryPack;
}
public String getBatteryPack()
{
return batteryPack;
}
public void setBatteryCluster(String batteryCluster)
{
this.batteryCluster = batteryCluster;
}
public String getBatteryCluster()
{
return batteryCluster;
}
public void setBatteryCellId(String batteryCellId)
{
this.batteryCellId = batteryCellId;
}
public String getBatteryCellId()
{
return batteryCellId;
}
public void setVoltage(BigDecimal voltage)
{
this.voltage = voltage;
}
public BigDecimal getVoltage()
{
return voltage;
}
public void setTemperature(BigDecimal temperature)
{
this.temperature = temperature;
}
public BigDecimal getTemperature()
{
return temperature;
}
public void setSoc(BigDecimal soc)
{
this.soc = soc;
}
public BigDecimal getSoc()
{
return soc;
}
public void setSoh(BigDecimal soh)
{
this.soh = soh;
}
public BigDecimal getSoh()
{
return soh;
}
public void setDataTimestamp(Date dataTimestamp)
{
this.dataTimestamp = dataTimestamp;
}
public Date getDataTimestamp()
{
return dataTimestamp;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setClusterDeviceId(String clusterDeviceId)
{
this.clusterDeviceId = clusterDeviceId;
}
public String getClusterDeviceId()
{
return clusterDeviceId;
}
public void setInterResistance(BigDecimal interResistance)
{
this.interResistance = interResistance;
}
public BigDecimal getInterResistance()
{
return interResistance;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("batteryPack", getBatteryPack())
.append("batteryCluster", getBatteryCluster())
.append("batteryCellId", getBatteryCellId())
.append("voltage", getVoltage())
.append("temperature", getTemperature())
.append("soc", getSoc())
.append("soh", getSoh())
.append("dataTimestamp", getDataTimestamp())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("clusterDeviceId", getClusterDeviceId())
.append("interResistance", getInterResistance())
.toString();
}
}

View File

@ -1,242 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 单体电池月级数据对象 ems_battery_data_month
*
* @author xzzn
* @date 2025-08-22
*/
public class EmsBatteryDataMonth extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 电池堆 */
@Excel(name = "电池堆")
private String batteryPack;
/** 电池簇 */
@Excel(name = "电池簇")
private String batteryCluster;
/** 单体编号 */
@Excel(name = "单体编号")
private String batteryCellId;
/** 电压 (V) */
@Excel(name = "电压 (V)")
private BigDecimal voltage;
/** 温度 (℃) */
@Excel(name = "温度 (℃)")
private BigDecimal temperature;
/** SOC (%) */
@Excel(name = "SOC (%)")
private BigDecimal soc;
/** SOH (%) */
@Excel(name = "SOH (%)")
private BigDecimal soh;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataTimestamp;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 簇设备id */
@Excel(name = "簇设备id")
private String clusterDeviceId;
/** 单体电池内阻 */
@Excel(name = "单体电池内阻")
private BigDecimal interResistance;
/** 月级时间维度 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "月级时间维度", width = 30, dateFormat = "yyyy-MM-dd")
private Date monthTime;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setBatteryPack(String batteryPack)
{
this.batteryPack = batteryPack;
}
public String getBatteryPack()
{
return batteryPack;
}
public void setBatteryCluster(String batteryCluster)
{
this.batteryCluster = batteryCluster;
}
public String getBatteryCluster()
{
return batteryCluster;
}
public void setBatteryCellId(String batteryCellId)
{
this.batteryCellId = batteryCellId;
}
public String getBatteryCellId()
{
return batteryCellId;
}
public void setVoltage(BigDecimal voltage)
{
this.voltage = voltage;
}
public BigDecimal getVoltage()
{
return voltage;
}
public void setTemperature(BigDecimal temperature)
{
this.temperature = temperature;
}
public BigDecimal getTemperature()
{
return temperature;
}
public void setSoc(BigDecimal soc)
{
this.soc = soc;
}
public BigDecimal getSoc()
{
return soc;
}
public void setSoh(BigDecimal soh)
{
this.soh = soh;
}
public BigDecimal getSoh()
{
return soh;
}
public void setDataTimestamp(Date dataTimestamp)
{
this.dataTimestamp = dataTimestamp;
}
public Date getDataTimestamp()
{
return dataTimestamp;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setClusterDeviceId(String clusterDeviceId)
{
this.clusterDeviceId = clusterDeviceId;
}
public String getClusterDeviceId()
{
return clusterDeviceId;
}
public void setInterResistance(BigDecimal interResistance)
{
this.interResistance = interResistance;
}
public BigDecimal getInterResistance()
{
return interResistance;
}
public void setMonthTime(Date monthTime)
{
this.monthTime = monthTime;
}
public Date getMonthTime()
{
return monthTime;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("batteryPack", getBatteryPack())
.append("batteryCluster", getBatteryCluster())
.append("batteryCellId", getBatteryCellId())
.append("voltage", getVoltage())
.append("temperature", getTemperature())
.append("soc", getSoc())
.append("soh", getSoh())
.append("dataTimestamp", getDataTimestamp())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("clusterDeviceId", getClusterDeviceId())
.append("interResistance", getInterResistance())
.append("monthTime", getMonthTime())
.toString();
}
}

View File

@ -1,14 +1,11 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.Date;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 电池堆数据对象 ems_battery_stack
@ -23,13 +20,8 @@ public class EmsBatteryStack extends BaseEntity
/** */
private Long id;
/** 数据更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataUpdateTime;
/** 工作状态0-运行 1-停机 2-故障 */
@Excel(name = "工作状态0-运行 1-停机 2-故障")
/** 工作状态0-正常 1-异常 2-停止 */
@Excel(name = "工作状态0-正常 1-异常 2-停止")
private String workStatus;
/** 与PCS通信状态0-正常 1-通信中断 2-异常 */
@ -262,14 +254,6 @@ public class EmsBatteryStack extends BaseEntity
return id;
}
public Date getDataUpdateTime() {
return dataUpdateTime;
}
public void setDataUpdateTime(Date dataUpdateTime) {
this.dataUpdateTime = dataUpdateTime;
}
public void setWorkStatus(String workStatus)
{
this.workStatus = workStatus;

View File

@ -1,795 +0,0 @@
package com.xzzn.ems.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* ZSLQ告警故障数据对象 ems_cooling_alarm_data
*
* @author xzzn
* @date 2025-10-22
*/
public class EmsCoolingAlarmData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 记录唯一ID */
private Long id;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataTimestamp;
/** 站点ID */
@Excel(name = "站点ID")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** */
@Excel(name = "")
private Integer lsjyx;
/** */
@Excel(name = "")
private Integer pqdcfyx;
/** */
@Excel(name = "")
private Integer djrq2yx;
/** */
@Excel(name = "")
private Integer djrq1yx;
/** */
@Excel(name = "")
private Integer bqbyx;
/** */
@Excel(name = "")
private Integer bsbyx;
/** */
@Excel(name = "")
private Integer zxhbyx;
/** */
@Excel(name = "")
private Integer sltzgz;
/** */
@Excel(name = "")
private Integer slzhyj;
/** */
@Excel(name = "")
private Integer slxtyctzxh;
/** */
@Excel(name = "")
private Integer slxtycqdxh;
/** */
@Excel(name = "")
private Integer slxtyckz;
/** */
@Excel(name = "")
private Integer slxtbdkz;
/** */
@Excel(name = "")
private Integer slxtzdms;
/** */
@Excel(name = "")
private Integer slxtsdms;
/** */
@Excel(name = "")
private Integer hsylcdyj;
/** */
@Excel(name = "")
private Integer hsyldyj;
/** */
@Excel(name = "")
private Integer gsylcgyj;
/** */
@Excel(name = "")
private Integer gsylgyj;
/** */
@Excel(name = "")
private Integer gsylcdyj;
/** */
@Excel(name = "")
private Integer gsyldyj;
/** */
@Excel(name = "")
private Integer hcgywg;
/** */
@Excel(name = "")
private Integer hcgywcdtz;
/** */
@Excel(name = "")
private Integer hcgywd;
/** */
@Excel(name = "")
private Integer hcgylg;
/** */
@Excel(name = "")
private Integer hcgyld;
/** */
@Excel(name = "")
private Integer lysylgyj;
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private Integer lysyldyj;
/** */
@Excel(name = "")
private Integer hswdcgyj;
/** */
@Excel(name = "")
private Integer hswdgyj;
/** */
@Excel(name = "")
private Integer gswdcgtz;
/** */
@Excel(name = "")
private Integer gswdgyj;
/** */
@Excel(name = "")
private Integer gswddyj;
/** */
@Excel(name = "")
private Integer ddf2gz;
/** */
@Excel(name = "")
private Integer ddf1gz;
/** */
@Excel(name = "")
private Integer lyswdbsqyJ;
/** */
@Excel(name = "")
private Integer hsylbsqyJ;
/** */
@Excel(name = "")
private Integer gsylbsqyJ;
/** */
@Excel(name = "")
private Integer hswdbsqyJ;
/** */
@Excel(name = "")
private Integer gswdbsqgztz;
/** */
@Excel(name = "")
private Integer lsjgz;
/** */
@Excel(name = "")
private Integer djrq2gz;
/** */
@Excel(name = "")
private Integer djrq1gz;
/** */
@Excel(name = "")
private Integer bqbgz;
/** */
@Excel(name = "")
private Integer bsbgz;
/** */
@Excel(name = "")
private Integer xhbgz;
/** */
@Excel(name = "")
private Integer zdygz;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDataTimestamp(Date dataTimestamp)
{
this.dataTimestamp = dataTimestamp;
}
public Date getDataTimestamp()
{
return dataTimestamp;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setLsjyx(Integer lsjyx)
{
this.lsjyx = lsjyx;
}
public Integer getLsjyx()
{
return lsjyx;
}
public void setPqdcfyx(Integer pqdcfyx)
{
this.pqdcfyx = pqdcfyx;
}
public Integer getPqdcfyx()
{
return pqdcfyx;
}
public void setDjrq2yx(Integer djrq2yx)
{
this.djrq2yx = djrq2yx;
}
public Integer getDjrq2yx()
{
return djrq2yx;
}
public void setDjrq1yx(Integer djrq1yx)
{
this.djrq1yx = djrq1yx;
}
public Integer getDjrq1yx()
{
return djrq1yx;
}
public void setBqbyx(Integer bqbyx)
{
this.bqbyx = bqbyx;
}
public Integer getBqbyx()
{
return bqbyx;
}
public void setBsbyx(Integer bsbyx)
{
this.bsbyx = bsbyx;
}
public Integer getBsbyx()
{
return bsbyx;
}
public void setZxhbyx(Integer zxhbyx)
{
this.zxhbyx = zxhbyx;
}
public Integer getZxhbyx()
{
return zxhbyx;
}
public void setSltzgz(Integer sltzgz)
{
this.sltzgz = sltzgz;
}
public Integer getSltzgz()
{
return sltzgz;
}
public void setSlzhyj(Integer slzhyj)
{
this.slzhyj = slzhyj;
}
public Integer getSlzhyj()
{
return slzhyj;
}
public void setSlxtyctzxh(Integer slxtyctzxh)
{
this.slxtyctzxh = slxtyctzxh;
}
public Integer getSlxtyctzxh()
{
return slxtyctzxh;
}
public void setSlxtycqdxh(Integer slxtycqdxh)
{
this.slxtycqdxh = slxtycqdxh;
}
public Integer getSlxtycqdxh()
{
return slxtycqdxh;
}
public void setSlxtyckz(Integer slxtyckz)
{
this.slxtyckz = slxtyckz;
}
public Integer getSlxtyckz()
{
return slxtyckz;
}
public void setSlxtbdkz(Integer slxtbdkz)
{
this.slxtbdkz = slxtbdkz;
}
public Integer getSlxtbdkz()
{
return slxtbdkz;
}
public void setSlxtzdms(Integer slxtzdms)
{
this.slxtzdms = slxtzdms;
}
public Integer getSlxtzdms()
{
return slxtzdms;
}
public void setSlxtsdms(Integer slxtsdms)
{
this.slxtsdms = slxtsdms;
}
public Integer getSlxtsdms()
{
return slxtsdms;
}
public void setHsylcdyj(Integer hsylcdyj)
{
this.hsylcdyj = hsylcdyj;
}
public Integer getHsylcdyj()
{
return hsylcdyj;
}
public void setHsyldyj(Integer hsyldyj)
{
this.hsyldyj = hsyldyj;
}
public Integer getHsyldyj()
{
return hsyldyj;
}
public void setGsylcgyj(Integer gsylcgyj)
{
this.gsylcgyj = gsylcgyj;
}
public Integer getGsylcgyj()
{
return gsylcgyj;
}
public void setGsylgyj(Integer gsylgyj)
{
this.gsylgyj = gsylgyj;
}
public Integer getGsylgyj()
{
return gsylgyj;
}
public void setGsylcdyj(Integer gsylcdyj)
{
this.gsylcdyj = gsylcdyj;
}
public Integer getGsylcdyj()
{
return gsylcdyj;
}
public void setGsyldyj(Integer gsyldyj)
{
this.gsyldyj = gsyldyj;
}
public Integer getGsyldyj()
{
return gsyldyj;
}
public void setHcgywg(Integer hcgywg)
{
this.hcgywg = hcgywg;
}
public Integer getHcgywg()
{
return hcgywg;
}
public void setHcgywcdtz(Integer hcgywcdtz)
{
this.hcgywcdtz = hcgywcdtz;
}
public Integer getHcgywcdtz()
{
return hcgywcdtz;
}
public void setHcgywd(Integer hcgywd)
{
this.hcgywd = hcgywd;
}
public Integer getHcgywd()
{
return hcgywd;
}
public void setHcgylg(Integer hcgylg)
{
this.hcgylg = hcgylg;
}
public Integer getHcgylg()
{
return hcgylg;
}
public void setHcgyld(Integer hcgyld)
{
this.hcgyld = hcgyld;
}
public Integer getHcgyld()
{
return hcgyld;
}
public void setLysylgyj(Integer lysylgyj)
{
this.lysylgyj = lysylgyj;
}
public Integer getLysylgyj()
{
return lysylgyj;
}
public void setLysyldyj(Integer lysyldyj)
{
this.lysyldyj = lysyldyj;
}
public Integer getLysyldyj()
{
return lysyldyj;
}
public void setHswdcgyj(Integer hswdcgyj)
{
this.hswdcgyj = hswdcgyj;
}
public Integer getHswdcgyj()
{
return hswdcgyj;
}
public void setHswdgyj(Integer hswdgyj)
{
this.hswdgyj = hswdgyj;
}
public Integer getHswdgyj()
{
return hswdgyj;
}
public void setGswdcgtz(Integer gswdcgtz)
{
this.gswdcgtz = gswdcgtz;
}
public Integer getGswdcgtz()
{
return gswdcgtz;
}
public void setGswdgyj(Integer gswdgyj)
{
this.gswdgyj = gswdgyj;
}
public Integer getGswdgyj()
{
return gswdgyj;
}
public void setGswddyj(Integer gswddyj)
{
this.gswddyj = gswddyj;
}
public Integer getGswddyj()
{
return gswddyj;
}
public void setDdf2gz(Integer ddf2gz)
{
this.ddf2gz = ddf2gz;
}
public Integer getDdf2gz()
{
return ddf2gz;
}
public void setDdf1gz(Integer ddf1gz)
{
this.ddf1gz = ddf1gz;
}
public Integer getDdf1gz()
{
return ddf1gz;
}
public void setLyswdbsqyJ(Integer lyswdbsqyJ)
{
this.lyswdbsqyJ = lyswdbsqyJ;
}
public Integer getLyswdbsqyJ()
{
return lyswdbsqyJ;
}
public void setHsylbsqyJ(Integer hsylbsqyJ)
{
this.hsylbsqyJ = hsylbsqyJ;
}
public Integer getHsylbsqyJ()
{
return hsylbsqyJ;
}
public void setGsylbsqyJ(Integer gsylbsqyJ)
{
this.gsylbsqyJ = gsylbsqyJ;
}
public Integer getGsylbsqyJ()
{
return gsylbsqyJ;
}
public void setHswdbsqyJ(Integer hswdbsqyJ)
{
this.hswdbsqyJ = hswdbsqyJ;
}
public Integer getHswdbsqyJ()
{
return hswdbsqyJ;
}
public void setGswdbsqgztz(Integer gswdbsqgztz)
{
this.gswdbsqgztz = gswdbsqgztz;
}
public Integer getGswdbsqgztz()
{
return gswdbsqgztz;
}
public void setLsjgz(Integer lsjgz)
{
this.lsjgz = lsjgz;
}
public Integer getLsjgz()
{
return lsjgz;
}
public void setDjrq2gz(Integer djrq2gz)
{
this.djrq2gz = djrq2gz;
}
public Integer getDjrq2gz()
{
return djrq2gz;
}
public void setDjrq1gz(Integer djrq1gz)
{
this.djrq1gz = djrq1gz;
}
public Integer getDjrq1gz()
{
return djrq1gz;
}
public void setBqbgz(Integer bqbgz)
{
this.bqbgz = bqbgz;
}
public Integer getBqbgz()
{
return bqbgz;
}
public void setBsbgz(Integer bsbgz)
{
this.bsbgz = bsbgz;
}
public Integer getBsbgz()
{
return bsbgz;
}
public void setXhbgz(Integer xhbgz)
{
this.xhbgz = xhbgz;
}
public Integer getXhbgz()
{
return xhbgz;
}
public void setZdygz(Integer zdygz)
{
this.zdygz = zdygz;
}
public Integer getZdygz()
{
return zdygz;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("dataTimestamp", getDataTimestamp())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("lsjyx", getLsjyx())
.append("pqdcfyx", getPqdcfyx())
.append("djrq2yx", getDjrq2yx())
.append("djrq1yx", getDjrq1yx())
.append("bqbyx", getBqbyx())
.append("bsbyx", getBsbyx())
.append("zxhbyx", getZxhbyx())
.append("sltzgz", getSltzgz())
.append("slzhyj", getSlzhyj())
.append("slxtyctzxh", getSlxtyctzxh())
.append("slxtycqdxh", getSlxtycqdxh())
.append("slxtyckz", getSlxtyckz())
.append("slxtbdkz", getSlxtbdkz())
.append("slxtzdms", getSlxtzdms())
.append("slxtsdms", getSlxtsdms())
.append("hsylcdyj", getHsylcdyj())
.append("hsyldyj", getHsyldyj())
.append("gsylcgyj", getGsylcgyj())
.append("gsylgyj", getGsylgyj())
.append("gsylcdyj", getGsylcdyj())
.append("gsyldyj", getGsyldyj())
.append("hcgywg", getHcgywg())
.append("hcgywcdtz", getHcgywcdtz())
.append("hcgywd", getHcgywd())
.append("hcgylg", getHcgylg())
.append("hcgyld", getHcgyld())
.append("lysylgyj", getLysylgyj())
.append("lysyldyj", getLysyldyj())
.append("hswdcgyj", getHswdcgyj())
.append("hswdgyj", getHswdgyj())
.append("gswdcgtz", getGswdcgtz())
.append("gswdgyj", getGswdgyj())
.append("gswddyj", getGswddyj())
.append("ddf2gz", getDdf2gz())
.append("ddf1gz", getDdf1gz())
.append("lyswdbsqyJ", getLyswdbsqyJ())
.append("hsylbsqyJ", getHsylbsqyJ())
.append("gsylbsqyJ", getGsylbsqyJ())
.append("hswdbsqyJ", getHswdbsqyJ())
.append("gswdbsqgztz", getGswdbsqgztz())
.append("lsjgz", getLsjgz())
.append("djrq2gz", getDjrq2gz())
.append("djrq1gz", getDjrq1gz())
.append("bqbgz", getBqbgz())
.append("bsbgz", getBsbgz())
.append("xhbgz", getXhbgz())
.append("zdygz", getZdygz())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,9 +1,7 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@ -13,7 +11,7 @@ import com.xzzn.common.annotation.Excel;
* 冷却系统参数对象 ems_cooling_data
*
* @author xzzn
* @date 2025-09-26
* @date 2025-06-29
*/
public class EmsCoolingData extends BaseEntity
{
@ -22,17 +20,12 @@ public class EmsCoolingData extends BaseEntity
/** */
private Long id;
/** 数据更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataUpdateTime;
/** 系统名称如1#液冷 */
@Excel(name = "系统名称如1#液冷")
private String systemName;
/** 工作模式0-正常 1-停止 */
@Excel(name = "工作模式0-正常 1-停止")
/** 工作模式 */
@Excel(name = "工作模式")
private String workMode;
/** 当前温度 (℃) */
@ -63,34 +56,6 @@ public class EmsCoolingData extends BaseEntity
@Excel(name = "低温告警点 (℃)")
private BigDecimal lowTempAlarmPoint;
/** 供水温度 */
@Excel(name = "供水温度")
private BigDecimal gsTemp;
/** 回水温度 */
@Excel(name = "回水温度")
private BigDecimal hsTemp;
/** 供水压力 */
@Excel(name = "供水压力")
private BigDecimal gsPressure;
/** 回水压力 */
@Excel(name = "回水压力")
private BigDecimal hsPressure;
/** 冷源水温度 */
@Excel(name = "冷源水温度")
private BigDecimal lysTemp;
/** VB01开度 */
@Excel(name = "VB01开度")
private BigDecimal vb01Kd;
/** VB02开度 */
@Excel(name = "VB02开度")
private BigDecimal vb02Kd;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
@ -109,14 +74,6 @@ public class EmsCoolingData extends BaseEntity
return id;
}
public Date getDataUpdateTime() {
return dataUpdateTime;
}
public void setDataUpdateTime(Date dataUpdateTime) {
this.dataUpdateTime = dataUpdateTime;
}
public void setSystemName(String systemName)
{
this.systemName = systemName;
@ -207,76 +164,6 @@ public class EmsCoolingData extends BaseEntity
return lowTempAlarmPoint;
}
public void setGsTemp(BigDecimal gsTemp)
{
this.gsTemp = gsTemp;
}
public BigDecimal getGsTemp()
{
return gsTemp;
}
public void setHsTemp(BigDecimal hsTemp)
{
this.hsTemp = hsTemp;
}
public BigDecimal getHsTemp()
{
return hsTemp;
}
public void setGsPressure(BigDecimal gsPressure)
{
this.gsPressure = gsPressure;
}
public BigDecimal getGsPressure()
{
return gsPressure;
}
public void setHsPressure(BigDecimal hsPressure)
{
this.hsPressure = hsPressure;
}
public BigDecimal getHsPressure()
{
return hsPressure;
}
public void setLysTemp(BigDecimal lysTemp)
{
this.lysTemp = lysTemp;
}
public BigDecimal getLysTemp()
{
return lysTemp;
}
public void setVb01Kd(BigDecimal vb01Kd)
{
this.vb01Kd = vb01Kd;
}
public BigDecimal getVb01Kd()
{
return vb01Kd;
}
public void setVb02Kd(BigDecimal vb02Kd)
{
this.vb02Kd = vb02Kd;
}
public BigDecimal getVb02Kd()
{
return vb02Kd;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
@ -310,13 +197,6 @@ public class EmsCoolingData extends BaseEntity
.append("heatingStopPoint", getHeatingStopPoint())
.append("coolingStopPoint", getCoolingStopPoint())
.append("lowTempAlarmPoint", getLowTempAlarmPoint())
.append("gsTemp", getGsTemp())
.append("hsTemp", getHsTemp())
.append("gsPressure", getGsPressure())
.append("hsPressure", getHsPressure())
.append("lysTemp", getLysTemp())
.append("vb01Kd", getVb01Kd())
.append("vb02Kd", getVb02Kd())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())

View File

@ -1,151 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 站点每日充放电数据对象 ems_daily_charge_data
*
* @author xzzn
* @date 2025-08-27
*/
public class EmsDailyChargeData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
/** 数据日期:yyyy-MM-dd */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
private Date dateTime;
/** 总充电量 */
@Excel(name = "总充电量")
private BigDecimal totalChargeData;
/** 总放电量 */
@Excel(name = "总放电量")
private BigDecimal totalDischargeData;
/** 当日充电量 */
@Excel(name = "当日充电量")
private BigDecimal chargeData;
/** 当日放电量 */
@Excel(name = "当日放电量")
private BigDecimal dischargeData;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setDateTime(Date dateTime)
{
this.dateTime = dateTime;
}
public Date getDateTime()
{
return dateTime;
}
public void setTotalChargeData(BigDecimal totalChargeData)
{
this.totalChargeData = totalChargeData;
}
public BigDecimal getTotalChargeData()
{
return totalChargeData;
}
public void setTotalDischargeData(BigDecimal totalDischargeData)
{
this.totalDischargeData = totalDischargeData;
}
public BigDecimal getTotalDischargeData()
{
return totalDischargeData;
}
public void setChargeData(BigDecimal chargeData)
{
this.chargeData = chargeData;
}
public BigDecimal getChargeData()
{
return chargeData;
}
public void setDischargeData(BigDecimal dischargeData)
{
this.dischargeData = dischargeData;
}
public BigDecimal getDischargeData()
{
return dischargeData;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("dateTime", getDateTime())
.append("totalChargeData", getTotalChargeData())
.append("totalDischargeData", getTotalDischargeData())
.append("chargeData", getChargeData())
.append("dischargeData", getDischargeData())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,241 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 站点电每日数据对象 ems_daily_energy_data
*
* @author xzzn
* @date 2025-10-09
*/
public class EmsDailyEnergyData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
private Long id;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 数据日期:yyyy-MM-dd */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataDate;
/** 总收入 */
@Excel(name = "总收入")
private BigDecimal totalRevenue;
/** 当日实时收入 */
@Excel(name = "当日实时收入")
private BigDecimal dayRevenue;
/** 尖峰时段充电差值 */
@Excel(name = "尖峰时段充电差值")
private BigDecimal peakChargeDiff;
/** 尖峰时段放电差值 */
@Excel(name = "尖峰时段放电差值")
private BigDecimal peakDischargeDiff;
/** 峰时时段充电差值 */
@Excel(name = "峰时时段充电差值")
private BigDecimal highChargeDiff;
/** 峰时时段放电差值 */
@Excel(name = "峰时时段放电差值")
private BigDecimal highDischargeDiff;
/** 平时时段充电差值 */
@Excel(name = "平时时段充电差值")
private BigDecimal flatChargeDiff;
/** 平时时段放电差值 */
@Excel(name = "平时时段放电差值")
private BigDecimal flatDischargeDiff;
/** 谷时时段充电差值 */
@Excel(name = "谷时时段充电差值")
private BigDecimal valleyChargeDiff;
/** 谷时时段放电差值 */
@Excel(name = "谷时时段放电差值")
private BigDecimal valleyDischargeDiff;
/** 差值计算时间如2025-10-10 23:59:00 */
@Excel(name = "差值计算时间", readConverterExp = "如=2025-10-10,2=3:59:00")
private Date calcTime;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDataDate(Date dataDate)
{
this.dataDate = dataDate;
}
public Date getDataDate()
{
return dataDate;
}
public void setTotalRevenue(BigDecimal totalRevenue)
{
this.totalRevenue = totalRevenue;
}
public BigDecimal getTotalRevenue()
{
return totalRevenue;
}
public void setDayRevenue(BigDecimal dayRevenue)
{
this.dayRevenue = dayRevenue;
}
public BigDecimal getDayRevenue()
{
return dayRevenue;
}
public void setPeakChargeDiff(BigDecimal peakChargeDiff)
{
this.peakChargeDiff = peakChargeDiff;
}
public BigDecimal getPeakChargeDiff()
{
return peakChargeDiff;
}
public void setPeakDischargeDiff(BigDecimal peakDischargeDiff)
{
this.peakDischargeDiff = peakDischargeDiff;
}
public BigDecimal getPeakDischargeDiff()
{
return peakDischargeDiff;
}
public void setHighChargeDiff(BigDecimal highChargeDiff)
{
this.highChargeDiff = highChargeDiff;
}
public BigDecimal getHighChargeDiff()
{
return highChargeDiff;
}
public void setHighDischargeDiff(BigDecimal highDischargeDiff)
{
this.highDischargeDiff = highDischargeDiff;
}
public BigDecimal getHighDischargeDiff()
{
return highDischargeDiff;
}
public void setFlatChargeDiff(BigDecimal flatChargeDiff)
{
this.flatChargeDiff = flatChargeDiff;
}
public BigDecimal getFlatChargeDiff()
{
return flatChargeDiff;
}
public void setFlatDischargeDiff(BigDecimal flatDischargeDiff)
{
this.flatDischargeDiff = flatDischargeDiff;
}
public BigDecimal getFlatDischargeDiff()
{
return flatDischargeDiff;
}
public void setValleyChargeDiff(BigDecimal valleyChargeDiff)
{
this.valleyChargeDiff = valleyChargeDiff;
}
public BigDecimal getValleyChargeDiff()
{
return valleyChargeDiff;
}
public void setValleyDischargeDiff(BigDecimal valleyDischargeDiff)
{
this.valleyDischargeDiff = valleyDischargeDiff;
}
public BigDecimal getValleyDischargeDiff()
{
return valleyDischargeDiff;
}
public void setCalcTime(Date calcTime)
{
this.calcTime = calcTime;
}
public Date getCalcTime()
{
return calcTime;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("siteId", getSiteId())
.append("dataDate", getDataDate())
.append("totalRevenue", getTotalRevenue())
.append("dayRevenue", getDayRevenue())
.append("peakChargeDiff", getPeakChargeDiff())
.append("peakDischargeDiff", getPeakDischargeDiff())
.append("highChargeDiff", getHighChargeDiff())
.append("highDischargeDiff", getHighDischargeDiff())
.append("flatChargeDiff", getFlatChargeDiff())
.append("flatDischargeDiff", getFlatDischargeDiff())
.append("valleyChargeDiff", getValleyChargeDiff())
.append("valleyDischargeDiff", getValleyDischargeDiff())
.append("calcTime", getCalcTime())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,134 +0,0 @@
package com.xzzn.ems.domain;
import java.util.Date;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 设备状态变更记录对象 ems_device_change_log
*
* @author xzzn
* @date 2025-11-15
*/
public class EmsDeviceChangeLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 日志IDUUID */
@Excel(name = "日志ID", readConverterExp = "U=UID")
private String logId;
/** 日志时间(精确到秒) */
@Excel(name = "日志时间", readConverterExp = "精=确到秒")
private Date logTime;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备id */
@Excel(name = "设备id")
private String deviceId;
/** 变更前状态0-离线、1-待机、2-运行、3-故障、4-停机 */
@Excel(name = "变更前状态0-离线、1-待机、2-运行、3-故障、4-停机")
private String beforeStatus;
/** 变更后状态0-离线、1-待机、2-运行、3-故障、4-停机 */
@Excel(name = "变更后状态0-离线、1-待机、2-运行、3-故障、4-停机")
private String afterStatus;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setLogId(String logId)
{
this.logId = logId;
}
public String getLogId()
{
return logId;
}
public void setLogTime(Date logTime)
{
this.logTime = logTime;
}
public Date getLogTime()
{
return logTime;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setBeforeStatus(String beforeStatus)
{
this.beforeStatus = beforeStatus;
}
public String getBeforeStatus()
{
return beforeStatus;
}
public void setAfterStatus(String afterStatus)
{
this.afterStatus = afterStatus;
}
public String getAfterStatus()
{
return afterStatus;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("logId", getLogId())
.append("logTime", getLogTime())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("beforeStatus", getBeforeStatus())
.append("afterStatus", getAfterStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,13 +1,11 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* Modbus设备配置对象 ems_devices_setting
@ -104,14 +102,6 @@ public class EmsDevicesSetting extends BaseEntity
@Excel(name = "设备类别例如“STACK/CLUSTER/PCS等”")
private String deviceCategory;
/** 设备运行状态0-离线、1-在线 */
@Excel(name = "设备运行状态0-离线、1-在线")
private String deviceStatus;
/** 设备运行状态0-离线、1-在线 */
@Excel(name = "工作状态0-运行 1-停机 2-故障")
private String workStatus;
/** 设备图像地址 */
@Excel(name = "设备图像地址")
private String pictureUrl;
@ -326,22 +316,6 @@ public class EmsDevicesSetting extends BaseEntity
return deviceCategory;
}
public String getDeviceStatus() {
return deviceStatus;
}
public void setDeviceStatus(String deviceStatus) {
this.deviceStatus = deviceStatus;
}
public String getWorkStatus() {
return workStatus;
}
public void setWorkStatus(String workStatus) {
this.workStatus = workStatus;
}
public void setPictureUrl(String pictureUrl)
{
this.pictureUrl = pictureUrl;
@ -376,7 +350,6 @@ public class EmsDevicesSetting extends BaseEntity
.append("deviceId", getDeviceId())
.append("parentId", getParentId())
.append("deviceCategory", getDeviceCategory())
.append("deviceStatus", getDeviceStatus())
.append("pictureUrl", getPictureUrl())
.toString();
}

View File

@ -1,9 +1,7 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@ -22,11 +20,6 @@ public class EmsDhData extends BaseEntity
/** $column.columnComment */
private Long id;
/** 数据更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataUpdateTime;
/** 湿度 */
@Excel(name = "湿度")
private BigDecimal humidity;
@ -53,14 +46,6 @@ public class EmsDhData extends BaseEntity
return id;
}
public Date getDataUpdateTime() {
return dataUpdateTime;
}
public void setDataUpdateTime(Date dataUpdateTime) {
this.dataUpdateTime = dataUpdateTime;
}
public void setHumidity(BigDecimal humidity)
{
this.humidity = humidity;

View File

@ -1,241 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
/**
* 数据对象 ems_ems_data
*
* @author xzzn
* @date 2025-12-09
*/
public class EmsEmsData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 数据采集时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据采集时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataUpdateTime;
/** EMS控制模式 */
@Excel(name = "EMS控制模式")
private BigDecimal emsStatus;
/** BMS1SOC */
@Excel(name = "BMS1SOC")
private BigDecimal bms1Soc;
/** BMS2SOC */
@Excel(name = "BMS2SOC")
private BigDecimal bms2Soc;
/** BMS3SOC */
@Excel(name = "BMS3SOC")
private BigDecimal bms3Soc;
/** BMS4SOC */
@Excel(name = "BMS4SOC")
private BigDecimal bms4Soc;
/** PCS-1有功功率 */
@Excel(name = "PCS-1有功功率")
private BigDecimal pcs1Yggl;
/** PCS-2有功功率 */
@Excel(name = "PCS-2有功功率")
private BigDecimal pcs2Yggl;
/** PCS-3有功功率 */
@Excel(name = "PCS-3有功功率")
private BigDecimal pcs3Yggl;
/** PCS-4有功功率 */
@Excel(name = "PCS-4有功功率")
private BigDecimal pcs4Yggl;
/** EMS有功功率 */
@Excel(name = "EMS有功功率")
private BigDecimal emsYggl;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDataUpdateTime(Date dataUpdateTime)
{
this.dataUpdateTime = dataUpdateTime;
}
public Date getDataUpdateTime()
{
return dataUpdateTime;
}
public void setEmsStatus(BigDecimal emsStatus)
{
this.emsStatus = emsStatus;
}
public BigDecimal getEmsStatus()
{
return emsStatus;
}
public void setBms1Soc(BigDecimal bms1Soc)
{
this.bms1Soc = bms1Soc;
}
public BigDecimal getBms1Soc()
{
return bms1Soc;
}
public void setBms2Soc(BigDecimal bms2Soc)
{
this.bms2Soc = bms2Soc;
}
public BigDecimal getBms2Soc()
{
return bms2Soc;
}
public void setBms3Soc(BigDecimal bms3Soc)
{
this.bms3Soc = bms3Soc;
}
public BigDecimal getBms3Soc()
{
return bms3Soc;
}
public void setBms4Soc(BigDecimal bms4Soc)
{
this.bms4Soc = bms4Soc;
}
public BigDecimal getBms4Soc()
{
return bms4Soc;
}
public void setPcs1Yggl(BigDecimal pcs1Yggl)
{
this.pcs1Yggl = pcs1Yggl;
}
public BigDecimal getPcs1Yggl()
{
return pcs1Yggl;
}
public void setPcs2Yggl(BigDecimal pcs2Yggl)
{
this.pcs2Yggl = pcs2Yggl;
}
public BigDecimal getPcs2Yggl()
{
return pcs2Yggl;
}
public void setPcs3Yggl(BigDecimal pcs3Yggl)
{
this.pcs3Yggl = pcs3Yggl;
}
public BigDecimal getPcs3Yggl()
{
return pcs3Yggl;
}
public void setPcs4Yggl(BigDecimal pcs4Yggl)
{
this.pcs4Yggl = pcs4Yggl;
}
public BigDecimal getPcs4Yggl()
{
return pcs4Yggl;
}
public void setEmsYggl(BigDecimal emsYggl)
{
this.emsYggl = emsYggl;
}
public BigDecimal getEmsYggl()
{
return emsYggl;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("dataUpdateTime", getDataUpdateTime())
.append("emsStatus", getEmsStatus())
.append("bms1Soc", getBms1Soc())
.append("bms2Soc", getBms2Soc())
.append("bms3Soc", getBms3Soc())
.append("bms4Soc", getBms4Soc())
.append("pcs1Yggl", getPcs1Yggl())
.append("pcs2Yggl", getPcs2Yggl())
.append("pcs3Yggl", getPcs3Yggl())
.append("pcs4Yggl", getPcs4Yggl())
.append("emsYggl", getEmsYggl())
.append("siteId", getSiteId())
.append("deviceId", getDeviceId())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,149 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 电价配置对象 ems_energy_price_config
*
* @author xzzn
* @date 2025-10-09
*/
public class EmsEnergyPriceConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
private Long id;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 年份如2025 */
@Excel(name = "年份如2025")
private String year;
/** 月份,如"9"表示9月 */
@Excel(name = "月份,如\"9\"表示9月")
private String month;
/** 尖-peak电价(元/kWh) */
@Excel(name = "尖-peak电价(元/kWh)")
private BigDecimal peak;
/** 峰-high电价(元/kWh) */
@Excel(name = "峰-high电价(元/kWh)")
private BigDecimal high;
/** 平-flat电价(元/kWh) */
@Excel(name = "平-flat电价(元/kWh)")
private BigDecimal flat;
/** 谷-valley电价(元/kWh) */
@Excel(name = "谷-valley电价(元/kWh)")
private BigDecimal valley;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setYear(String year)
{
this.year = year;
}
public String getYear()
{
return year;
}
public void setMonth(String month)
{
this.month = month;
}
public String getMonth()
{
return month;
}
public void setPeak(BigDecimal peak)
{
this.peak = peak;
}
public BigDecimal getPeak()
{
return peak;
}
public void setHigh(BigDecimal high)
{
this.high = high;
}
public BigDecimal getHigh()
{
return high;
}
public void setFlat(BigDecimal flat)
{
this.flat = flat;
}
public BigDecimal getFlat()
{
return flat;
}
public void setValley(BigDecimal valley)
{
this.valley = valley;
}
public BigDecimal getValley()
{
return valley;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("siteId", getSiteId())
.append("year", getYear())
.append("month", getMonth())
.append("peak", getPeak())
.append("high", getHigh())
.append("flat", getFlat())
.append("valley", getValley())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,150 +0,0 @@
package com.xzzn.ems.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 告警保护方案下发日志对象 ems_fault_issue_log
*
* @author xzzn
* @date 2025-11-15
*/
public class EmsFaultIssueLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 日志IDUUID */
@Excel(name = "日志ID", readConverterExp = "U=UID")
private String logId;
/** 日志时间(精确到秒) */
@Excel(name = "日志时间", readConverterExp = "精=确到秒")
private Date logTime;
/** 日志等级同方案等级1/2/3等 */
@Excel(name = "日志等级", readConverterExp = "同=方案等级1/2/3等")
private Integer logLevel;
/** 站点名称/编号 */
@Excel(name = "站点名称/编号")
private String siteId;
/** 设备ID */
@Excel(name = "设备ID")
private String deviceId;
/** 操作点位 */
@Excel(name = "操作点位")
private String point;
/** 设置数据 */
@Excel(name = "设置数据")
private BigDecimal value;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setLogId(String logId)
{
this.logId = logId;
}
public String getLogId()
{
return logId;
}
public void setLogTime(Date logTime)
{
this.logTime = logTime;
}
public Date getLogTime()
{
return logTime;
}
public void setLogLevel(Integer logLevel)
{
this.logLevel = logLevel;
}
public Integer getLogLevel()
{
return logLevel;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setPoint(String point)
{
this.point = point;
}
public String getPoint()
{
return point;
}
public void setValue(BigDecimal value)
{
this.value = value;
}
public BigDecimal getValue()
{
return value;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("logId", getLogId())
.append("logTime", getLogTime())
.append("logLevel", getLogLevel())
.append("site", getSiteId())
.append("deviceId", getDeviceId())
.append("point", getPoint())
.append("value", getValue())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,191 +0,0 @@
package com.xzzn.ems.domain;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 故障告警保护方案对象 ems_fault_protection_plan
*
* @author xzzn
* @date 2025-10-24
*/
public class EmsFaultProtectionPlan extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 故障名称(如:总压高、放电总压过低) */
@Excel(name = "故障名称", readConverterExp = "如=:总压高、放电总压过低")
private String faultName;
/** 故障等级1级/2级/3级 */
@Excel(name = "故障等级", readConverterExp = "1=级/2级/3级")
private Integer faultLevel;
/** 保护设置:点位/故障值/比较方式/释放值等 */
@Excel(name = "保护设置:点位/故障值/比较方式/释放值等")
private String protectionSettings;
/** 故障延时3S→3 */
@Excel(name = "故障延时", readConverterExp = "秒=3S→3")
private Long faultDelaySeconds;
/** 保护方案:修改目标点位和值 */
@Excel(name = "保护方案:修改目标点位和值")
private String protectionPlan;
/** 释放延时5S→53级可能无 */
@Excel(name = "释放延时", readConverterExp = "秒=5S→53级可能无")
private Long releaseDelaySeconds;
/** 处理方案描述例如报警降功率50%运行) */
@Excel(name = "处理方案描述", readConverterExp = "例=如报警降功率50%运行")
private String description;
/** 是否触发告警0 - 不告警1 - 告警) */
@Excel(name = "是否触发告警", readConverterExp = "0=不告警1=告警")
private Integer isAlert;
/** 方案是否启用 0-未启用 1-已启用 */
@Excel(name = "方案是否启用 0-未启用 1-已启用")
private Long status;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setFaultName(String faultName)
{
this.faultName = faultName;
}
public String getFaultName()
{
return faultName;
}
public void setFaultLevel(Integer faultLevel)
{
this.faultLevel = faultLevel;
}
public Integer getFaultLevel()
{
return faultLevel;
}
public void setProtectionSettings(String protectionSettings)
{
this.protectionSettings = protectionSettings;
}
public String getProtectionSettings()
{
return protectionSettings;
}
public void setFaultDelaySeconds(Long faultDelaySeconds)
{
this.faultDelaySeconds = faultDelaySeconds;
}
public Long getFaultDelaySeconds()
{
return faultDelaySeconds;
}
public void setProtectionPlan(String protectionPlan)
{
this.protectionPlan = protectionPlan;
}
public String getProtectionPlan()
{
return protectionPlan;
}
public void setReleaseDelaySeconds(Long releaseDelaySeconds)
{
this.releaseDelaySeconds = releaseDelaySeconds;
}
public Long getReleaseDelaySeconds()
{
return releaseDelaySeconds;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
public void setIsAlert(Integer isAlert)
{
this.isAlert = isAlert;
}
public Integer getIsAlert()
{
return isAlert;
}
public void setStatus(Long status)
{
this.status = status;
}
public Long getStatus()
{
return status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("siteId", getSiteId())
.append("faultName", getFaultName())
.append("faultLevel", getFaultLevel())
.append("protectionSettings", getProtectionSettings())
.append("faultDelaySeconds", getFaultDelaySeconds())
.append("protectionPlan", getProtectionPlan())
.append("releaseDelaySeconds", getReleaseDelaySeconds())
.append("description", getDescription())
.append("isAlert", getIsAlert())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -1,130 +0,0 @@
package com.xzzn.ems.domain;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 站点topic配置对象 ems_mqtt_topic_config
*
* @author xzzn
* @date 2025-11-06
*/
public class EmsMqttTopicConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 订阅topic */
@Excel(name = "订阅topic")
private String mqttTopic;
/** QoS等级0/1/2 */
@Excel(name = "QoS等级", readConverterExp = "0=/1/2")
private Integer qos;
/** topic描述 */
@Excel(name = "topic描述")
private String topicName;
/** 对应方法 */
@Excel(name = "对应方法")
private String handleMethod;
/** 处理器类型:(DEVICE=设备数据SYSTEM=系统状态ALARM=告警数据等) */
@Excel(name = "处理器类型:(DEVICE=设备数据SYSTEM=系统状态ALARM=告警数据等)")
private String handleType;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setMqttTopic(String mqttTopic)
{
this.mqttTopic = mqttTopic;
}
public String getMqttTopic()
{
return mqttTopic;
}
public void setQos(Integer qos)
{
this.qos = qos;
}
public Integer getQos()
{
return qos;
}
public void setTopicName(String topicName)
{
this.topicName = topicName;
}
public String getTopicName()
{
return topicName;
}
public void setHandleMethod(String handleMethod)
{
this.handleMethod = handleMethod;
}
public String getHandleMethod()
{
return handleMethod;
}
public void setHandleType(String handleType)
{
this.handleType = handleType;
}
public String getHandleType()
{
return handleType;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("mqttTopic", getMqttTopic())
.append("qos", getQos())
.append("topicName", getTopicName())
.append("handleMethod", getHandleMethod())
.append("handleType", getHandleType())
.append("siteId", getSiteId())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -1,20 +1,18 @@
package com.xzzn.ems.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* PCS数据对象 ems_pcs_data
*
* @author xzzn
* @date 2025-09-25
* @date 2025-07-07
*/
public class EmsPcsData extends BaseEntity
{
@ -28,16 +26,16 @@ public class EmsPcsData extends BaseEntity
@Excel(name = "数据更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date dataUpdateTime;
/** 工作状态0-运行 1-停机 2-故障 */
@Excel(name = "工作状态0-运行 1-停机 2-故障")
/** 工作状态0-正常 1-异常 2-停止 */
@Excel(name = "工作状态0-正常 1-异常 2-停止")
private String workStatus;
/** 并网状态0-并网 1-未并网 */
@Excel(name = "并网状态0-并网 1-未并网")
private String gridStatus;
/** 设备运行状态0-离线、1-在线 */
@Excel(name = "设备运行状态0-离线、1-在线")
/** 设备状态0-在线 1-离线 2-维修中 */
@Excel(name = "设备状态0-在线 1-离线 2-维修中")
private String deviceStatus;
/** 控制模式0-远程 1-本地 */
@ -208,34 +206,6 @@ public class EmsPcsData extends BaseEntity
@Excel(name = "电网频率")
private BigDecimal dwFrequency;
/** 单元1U相IGBT温度 */
@Excel(name = "单元1U相IGBT温度")
private BigDecimal uTemperature;
/** 单元1V相IGBT温度 */
@Excel(name = "单元1V相IGBT温度")
private BigDecimal vTemperature;
/** 单元1W相IGBT温度 */
@Excel(name = "单元1W相IGBT温度")
private BigDecimal wTemperature;
/** 1#模块IGBT最高温 */
@Excel(name = "1#模块IGBT最高温")
private BigDecimal module1Temp;
/** 2#模块IGBT最高温 */
@Excel(name = "2#模块IGBT最高温")
private BigDecimal module2Temp;
/** 3#模块IGBT最高温 */
@Excel(name = "3#模块IGBT最高温")
private BigDecimal module3Temp;
/** 4#模块IGBT最高温 */
@Excel(name = "4#模块IGBT最高温")
private BigDecimal module4Temp;
public void setId(Long id)
{
this.id = id;
@ -706,76 +676,6 @@ public class EmsPcsData extends BaseEntity
return dwFrequency;
}
public void setuTemperature(BigDecimal uTemperature)
{
this.uTemperature = uTemperature;
}
public BigDecimal getuTemperature()
{
return uTemperature;
}
public void setvTemperature(BigDecimal vTemperature)
{
this.vTemperature = vTemperature;
}
public BigDecimal getvTemperature()
{
return vTemperature;
}
public void setwTemperature(BigDecimal wTemperature)
{
this.wTemperature = wTemperature;
}
public BigDecimal getwTemperature()
{
return wTemperature;
}
public void setModule1Temp(BigDecimal module1Temp)
{
this.module1Temp = module1Temp;
}
public BigDecimal getModule1Temp()
{
return module1Temp;
}
public void setModule2Temp(BigDecimal module2Temp)
{
this.module2Temp = module2Temp;
}
public BigDecimal getModule2Temp()
{
return module2Temp;
}
public void setModule3Temp(BigDecimal module3Temp)
{
this.module3Temp = module3Temp;
}
public BigDecimal getModule3Temp()
{
return module3Temp;
}
public void setModule4Temp(BigDecimal module4Temp)
{
this.module4Temp = module4Temp;
}
public BigDecimal getModule4Temp()
{
return module4Temp;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -831,13 +731,6 @@ public class EmsPcsData extends BaseEntity
.append("sysVCurrent", getSysVCurrent())
.append("sysWCurrent", getSysWCurrent())
.append("dwFrequency", getDwFrequency())
.append("uTemperature", getuTemperature())
.append("vTemperature", getvTemperature())
.append("wTemperature", getwTemperature())
.append("module1Temp", getModule1Temp())
.append("module2Temp", getModule2Temp())
.append("module3Temp", getModule3Temp())
.append("module4Temp", getModule4Temp())
.toString();
}
}

View File

@ -1,177 +0,0 @@
package com.xzzn.ems.domain;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* PCS设备配置对象 ems_pcs_setting
*
* @author xzzn
* @date 2025-12-29
*/
public class EmsPcsSetting extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 设备ID主键自增长 */
private Long id;
/** 设备配置关联ID */
@Excel(name = "设备配置关联ID")
private Long deviceSettingId;
/** 开关机地址 */
@Excel(name = "开关机地址")
private String pointAddress;
/** 功率地址 */
@Excel(name = "功率地址")
private String powerAddress;
/** 开机指令 */
@Excel(name = "开机指令")
private String startCommand;
/** 关机指令 */
@Excel(name = "关机指令")
private String stopCommand;
/** 开机目标功率 */
@Excel(name = "开机目标功率")
private BigDecimal startPower;
/** 关机目标功率 */
@Excel(name = "关机目标功率")
private BigDecimal stopPower;
/** 电池簇数 */
@Excel(name = "电池簇数")
private Integer clusterNum;
/** 电池簇地址 */
@Excel(name = "电池簇地址")
private String clusterPointAddress;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDeviceSettingId(Long deviceSettingId)
{
this.deviceSettingId = deviceSettingId;
}
public Long getDeviceSettingId()
{
return deviceSettingId;
}
public String getPowerAddress() {
return powerAddress;
}
public void setPowerAddress(String powerAddress) {
this.powerAddress = powerAddress;
}
public void setPointAddress(String pointAddress)
{
this.pointAddress = pointAddress;
}
public String getPointAddress()
{
return pointAddress;
}
public void setStartCommand(String startCommand)
{
this.startCommand = startCommand;
}
public String getStartCommand()
{
return startCommand;
}
public void setStopCommand(String stopCommand)
{
this.stopCommand = stopCommand;
}
public String getStopCommand()
{
return stopCommand;
}
public void setStartPower(BigDecimal startPower)
{
this.startPower = startPower;
}
public BigDecimal getStartPower()
{
return startPower;
}
public void setStopPower(BigDecimal stopPower)
{
this.stopPower = stopPower;
}
public BigDecimal getStopPower()
{
return stopPower;
}
public void setClusterNum(Integer clusterNum)
{
this.clusterNum = clusterNum;
}
public Integer getClusterNum()
{
return clusterNum;
}
public void setClusterPointAddress(String clusterPointAddress)
{
this.clusterPointAddress = clusterPointAddress;
}
public String getClusterPointAddress()
{
return clusterPointAddress;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceSettingId", getDeviceSettingId())
.append("pointAddress", getPointAddress())
.append("startCommand", getStartCommand())
.append("stopCommand", getStopCommand())
.append("startPower", getStartPower())
.append("stopPower", getStopPower())
.append("clusterNum", getClusterNum())
.append("clusterPointAddress", getClusterPointAddress())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -1,147 +0,0 @@
package com.xzzn.ems.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.core.domain.BaseEntity;
/**
* 点位枚举匹配对象 ems_point_enum_match
*
* @author xzzn
* @date 2025-12-08
*/
public class EmsPointEnumMatch extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键自增长 */
private Long id;
/** 点位匹配字段 */
@Excel(name = "点位匹配字段")
private String matchField;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备类别例如“STACK/CLUSTER/PCS等” */
@Excel(name = "设备类别例如“STACK/CLUSTER/PCS等”")
private String deviceCategory;
/** 系统枚举代码 */
@Excel(name = "系统枚举代码")
private String enumCode;
/** 系统枚举名称 */
@Excel(name = "系统枚举名称")
private String enumName;
/** 系统枚举描述 */
@Excel(name = "系统枚举描述")
private String enumDesc;
/** 数据枚举代码 */
@Excel(name = "数据枚举代码")
private String dataEnumCode;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setMatchField(String matchField)
{
this.matchField = matchField;
}
public String getMatchField()
{
return matchField;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceCategory(String deviceCategory)
{
this.deviceCategory = deviceCategory;
}
public String getDeviceCategory()
{
return deviceCategory;
}
public void setEnumCode(String enumCode)
{
this.enumCode = enumCode;
}
public String getEnumCode()
{
return enumCode;
}
public void setEnumName(String enumName)
{
this.enumName = enumName;
}
public String getEnumName()
{
return enumName;
}
public void setEnumDesc(String enumDesc)
{
this.enumDesc = enumDesc;
}
public String getEnumDesc()
{
return enumDesc;
}
public void setDataEnumCode(String dataEnumCode)
{
this.dataEnumCode = dataEnumCode;
}
public String getDataEnumCode()
{
return dataEnumCode;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("matchField", getMatchField())
.append("siteId", getSiteId())
.append("deviceCategory", getDeviceCategory())
.append("enumCode", getEnumCode())
.append("enumName", getEnumName())
.append("enumDesc", getEnumDesc())
.append("dataEnumCode", getDataEnumCode())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

Some files were not shown because too many files have changed in this diff Show More