Compare commits
19 Commits
9f2c303047
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 056e06b00a | |||
| 515f440298 | |||
| e4cfd15cb4 | |||
| 5ab2cb8f90 | |||
| 4e7d387edf | |||
| 49ed5f218a | |||
| 8806473080 | |||
| 71d0b0f609 | |||
| 6253fb6b2d | |||
| 21673ecd1e | |||
| 66de6fe77c | |||
| 63ed2641ee | |||
| 5d5a7137fc | |||
| 6545b4f947 | |||
| 8a44009c42 | |||
| 2b22b70baa | |||
| 5a86769b40 | |||
| eeccd19f0a | |||
| d19f07c4e8 |
@ -55,4 +55,21 @@ public class EmsAlarmRecordsController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭告警
|
||||||
|
*/
|
||||||
|
@PostMapping("/closeAlarm")
|
||||||
|
public AjaxResult closeAlarm(@RequestBody EmsAlarmRecords emsAlarmRecords)
|
||||||
|
{
|
||||||
|
Long id = emsAlarmRecords.getId();
|
||||||
|
if (id == null) {
|
||||||
|
return error("告警id不能为空");
|
||||||
|
}
|
||||||
|
String result = iEmsAlarmRecordsService.closeAlarm(id, getUserId());
|
||||||
|
if ("success".equals(result) || "告警已关闭".equals(result)) {
|
||||||
|
return AjaxResult.success("操作成功");
|
||||||
|
}
|
||||||
|
return error(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Log;
|
||||||
|
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.ems.domain.EmsDailyChargeData;
|
||||||
|
import com.xzzn.ems.service.IEmsDailyChargeDataService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点管理-充放电修正 Controller
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ems/dailyChargeData")
|
||||||
|
public class EmsDailyChargeDataController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IEmsDailyChargeDataService emsDailyChargeDataService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(EmsDailyChargeData emsDailyChargeData) {
|
||||||
|
startPage();
|
||||||
|
List<EmsDailyChargeData> list = emsDailyChargeDataService.selectEmsDailyChargeDataList(emsDailyChargeData);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||||
|
return success(emsDailyChargeDataService.selectEmsDailyChargeDataById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-充放电修正", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody EmsDailyChargeData emsDailyChargeData) {
|
||||||
|
return toAjax(emsDailyChargeDataService.insertEmsDailyChargeData(emsDailyChargeData, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-充放电修正", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody EmsDailyChargeData emsDailyChargeData) {
|
||||||
|
return toAjax(emsDailyChargeDataService.updateEmsDailyChargeData(emsDailyChargeData, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-充放电修正", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
|
return toAjax(emsDailyChargeDataService.deleteEmsDailyChargeDataByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Log;
|
||||||
|
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.ems.domain.EmsDailyEnergyData;
|
||||||
|
import com.xzzn.ems.service.IEmsDailyEnergyDataService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点管理-数据修正 Controller
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ems/dailyEnergyData")
|
||||||
|
public class EmsDailyEnergyDataController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IEmsDailyEnergyDataService emsDailyEnergyDataService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(EmsDailyEnergyData emsDailyEnergyData) {
|
||||||
|
startPage();
|
||||||
|
List<EmsDailyEnergyData> list = emsDailyEnergyDataService.selectEmsDailyEnergyDataList(emsDailyEnergyData);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||||
|
return success(emsDailyEnergyDataService.selectEmsDailyEnergyDataById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-数据修正", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody EmsDailyEnergyData emsDailyEnergyData) {
|
||||||
|
return toAjax(emsDailyEnergyDataService.insertEmsDailyEnergyData(emsDailyEnergyData, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-数据修正", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody EmsDailyEnergyData emsDailyEnergyData) {
|
||||||
|
return toAjax(emsDailyEnergyDataService.updateEmsDailyEnergyData(emsDailyEnergyData, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "站点管理-数据修正", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
|
return toAjax(emsDailyEnergyDataService.deleteEmsDailyEnergyDataByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Log;
|
||||||
|
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.ems.domain.EmsPointCalcConfig;
|
||||||
|
import com.xzzn.ems.service.IEmsPointCalcConfigService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ems/pointCalcConfig")
|
||||||
|
public class EmsPointCalcConfigController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IEmsPointCalcConfigService pointCalcConfigService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(EmsPointCalcConfig pointCalcConfig) {
|
||||||
|
startPage();
|
||||||
|
List<EmsPointCalcConfig> list = pointCalcConfigService.selectPointCalcConfigList(pointCalcConfig);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||||
|
return success(pointCalcConfigService.selectPointCalcConfigById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "计算点配置", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody EmsPointCalcConfig pointCalcConfig) {
|
||||||
|
return toAjax(pointCalcConfigService.insertPointCalcConfig(pointCalcConfig, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "计算点配置", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody EmsPointCalcConfig pointCalcConfig) {
|
||||||
|
return toAjax(pointCalcConfigService.updatePointCalcConfig(pointCalcConfig, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "计算点配置", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
|
return toAjax(pointCalcConfigService.deletePointCalcConfigByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Log;
|
||||||
|
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.ems.domain.EmsPointConfig;
|
||||||
|
import com.xzzn.ems.domain.vo.ImportPointTemplateRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigCurveRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigGenerateRecentRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigLatestValueRequest;
|
||||||
|
import com.xzzn.ems.service.IEmsPointConfigService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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.PutMapping;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ems/pointConfig")
|
||||||
|
public class EmsPointConfigController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IEmsPointConfigService pointConfigService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(EmsPointConfig pointConfig) {
|
||||||
|
startPage();
|
||||||
|
List<EmsPointConfig> list = pointConfigService.selectPointConfigList(pointConfig);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||||
|
return success(pointConfigService.selectPointConfigById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody EmsPointConfig pointConfig) {
|
||||||
|
return toAjax(pointConfigService.insertPointConfig(pointConfig, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody EmsPointConfig pointConfig) {
|
||||||
|
return toAjax(pointConfigService.updatePointConfig(pointConfig, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
|
return toAjax(pointConfigService.deletePointConfigByIds(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.IMPORT)
|
||||||
|
@PostMapping("/importTemplateBySite")
|
||||||
|
public AjaxResult importTemplateBySite(@Valid @RequestBody ImportPointTemplateRequest request) {
|
||||||
|
return success(pointConfigService.importTemplateBySite(request, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.IMPORT)
|
||||||
|
@PostMapping("/importCsv")
|
||||||
|
public AjaxResult importCsv(@RequestParam String siteId,
|
||||||
|
@RequestParam(required = false) Boolean overwrite,
|
||||||
|
@RequestParam("file") MultipartFile file) {
|
||||||
|
return success(pointConfigService.importCsvBySite(siteId, overwrite, file, getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/registerAddress")
|
||||||
|
public AjaxResult getRegisterAddress(@RequestParam String siteId,
|
||||||
|
@RequestParam String deviceCategory,
|
||||||
|
@RequestParam String deviceId,
|
||||||
|
@RequestParam String dataKey) {
|
||||||
|
return success(pointConfigService.getRegisterAddress(siteId, deviceCategory, deviceId, dataKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/latestValues")
|
||||||
|
public AjaxResult latestValues(@RequestBody PointConfigLatestValueRequest request) {
|
||||||
|
return success(pointConfigService.getLatestValues(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/curve")
|
||||||
|
public AjaxResult curve(@RequestBody PointConfigCurveRequest request) {
|
||||||
|
return success(pointConfigService.getCurveData(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping("/generateRecent7Days")
|
||||||
|
public AjaxResult generateRecent7Days(@Valid @RequestBody PointConfigGenerateRecentRequest request) {
|
||||||
|
return success(pointConfigService.generateRecent7DaysData(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,8 +7,12 @@ import javax.validation.Valid;
|
|||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.xzzn.common.annotation.Log;
|
import com.xzzn.common.annotation.Log;
|
||||||
@ -19,6 +23,7 @@ import com.xzzn.ems.domain.EmsPointMatch;
|
|||||||
import com.xzzn.ems.domain.vo.DevicePointMatchExportVo;
|
import com.xzzn.ems.domain.vo.DevicePointMatchExportVo;
|
||||||
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
|
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
|
||||||
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
|
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.ImportPointTemplateRequest;
|
||||||
import com.xzzn.ems.service.IEmsPointMatchService;
|
import com.xzzn.ems.service.IEmsPointMatchService;
|
||||||
import com.xzzn.common.utils.poi.ExcelUtil;
|
import com.xzzn.common.utils.poi.ExcelUtil;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
@ -49,6 +54,58 @@ public class EmsPointMatchController extends BaseController
|
|||||||
util.exportExcel(response, list, "点位匹配数据");
|
util.exportExcel(response, list, "点位匹配数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询点位配置列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public com.xzzn.common.core.page.TableDataInfo list(EmsPointMatch emsPointMatch)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<EmsPointMatch> list = emsPointMatchService.selectPointMatchConfigList(emsPointMatch);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询点位配置详情
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||||
|
{
|
||||||
|
return success(emsPointMatchService.selectPointMatchById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增点位配置
|
||||||
|
*/
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody EmsPointMatch emsPointMatch)
|
||||||
|
{
|
||||||
|
emsPointMatch.setCreateBy(getUsername());
|
||||||
|
return toAjax(emsPointMatchService.insertPointMatch(emsPointMatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改点位配置
|
||||||
|
*/
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody EmsPointMatch emsPointMatch)
|
||||||
|
{
|
||||||
|
emsPointMatch.setUpdateBy(getUsername());
|
||||||
|
return toAjax(emsPointMatchService.updatePointMatch(emsPointMatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除点位配置
|
||||||
|
*/
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(emsPointMatchService.deletePointMatchByIds(ids));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传点位清单
|
* 上传点位清单
|
||||||
* @param file
|
* @param file
|
||||||
@ -85,4 +142,18 @@ public class EmsPointMatchController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据站点导入模板点位配置
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 导入结果
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:user:import')")
|
||||||
|
@Log(title = "点位配置", businessType = BusinessType.IMPORT)
|
||||||
|
@PostMapping("/importTemplateBySite")
|
||||||
|
public AjaxResult importTemplateBySite(@Valid @RequestBody ImportPointTemplateRequest request)
|
||||||
|
{
|
||||||
|
String message = emsPointMatchService.importTemplateBySite(request, getUsername());
|
||||||
|
return success(message);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,9 @@ import com.xzzn.ems.domain.vo.DeviceUpdateRequest;
|
|||||||
import com.xzzn.ems.domain.vo.DevicesSettingVo;
|
import com.xzzn.ems.domain.vo.DevicesSettingVo;
|
||||||
import com.xzzn.ems.domain.vo.PointDataRequest;
|
import com.xzzn.ems.domain.vo.PointDataRequest;
|
||||||
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||||
import com.xzzn.ems.domain.vo.SiteDeviceListVo;
|
import com.xzzn.ems.domain.vo.SiteDeviceListVo;
|
||||||
|
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingSaveRequest;
|
||||||
import com.xzzn.ems.service.IEmsDeviceSettingService;
|
import com.xzzn.ems.service.IEmsDeviceSettingService;
|
||||||
import com.xzzn.ems.service.IEmsSiteService;
|
import com.xzzn.ems.service.IEmsSiteService;
|
||||||
|
|
||||||
@ -59,6 +61,26 @@ public class EmsSiteConfigController extends BaseController{
|
|||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增站点
|
||||||
|
*/
|
||||||
|
@PostMapping("/addSite")
|
||||||
|
public AjaxResult addSite(@RequestBody EmsSiteSetting emsSiteSetting)
|
||||||
|
{
|
||||||
|
emsSiteSetting.setCreateBy(getUsername());
|
||||||
|
return toAjax(iEmsSiteService.addSite(emsSiteSetting));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑站点
|
||||||
|
*/
|
||||||
|
@PostMapping("/updateSite")
|
||||||
|
public AjaxResult updateSite(@RequestBody EmsSiteSetting emsSiteSetting)
|
||||||
|
{
|
||||||
|
emsSiteSetting.setUpdateBy(getUsername());
|
||||||
|
return toAjax(iEmsSiteService.updateSite(emsSiteSetting));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取设备列表-分页
|
* 获取设备列表-分页
|
||||||
*/
|
*/
|
||||||
@ -192,6 +214,44 @@ public class EmsSiteConfigController extends BaseController{
|
|||||||
return success(iEmsDeviceSettingService.getDeviceListBySiteAndCategory(siteId, deviceCategory));
|
return success(iEmsDeviceSettingService.getDeviceListBySiteAndCategory(siteId, deviceCategory));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单站监控项目点位映射
|
||||||
|
*/
|
||||||
|
@GetMapping("/getSingleMonitorProjectPointMapping")
|
||||||
|
public AjaxResult getSingleMonitorProjectPointMapping(@RequestParam String siteId)
|
||||||
|
{
|
||||||
|
return success(iEmsDeviceSettingService.getSiteMonitorProjectPointMapping(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存单站监控项目点位映射
|
||||||
|
*/
|
||||||
|
@PostMapping("/saveSingleMonitorProjectPointMapping")
|
||||||
|
public AjaxResult saveSingleMonitorProjectPointMapping(@RequestBody SiteMonitorProjectPointMappingSaveRequest request)
|
||||||
|
{
|
||||||
|
int rows = iEmsDeviceSettingService.saveSiteMonitorProjectPointMapping(request, getUsername());
|
||||||
|
return AjaxResult.success(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单站监控工作状态枚举映射(PCS)
|
||||||
|
*/
|
||||||
|
@GetMapping("/getSingleMonitorWorkStatusEnumMappings")
|
||||||
|
public AjaxResult getSingleMonitorWorkStatusEnumMappings(@RequestParam String siteId)
|
||||||
|
{
|
||||||
|
return success(iEmsDeviceSettingService.getSiteWorkStatusEnumMappings(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存单站监控工作状态枚举映射(PCS)
|
||||||
|
*/
|
||||||
|
@PostMapping("/saveSingleMonitorWorkStatusEnumMappings")
|
||||||
|
public AjaxResult saveSingleMonitorWorkStatusEnumMappings(@RequestBody WorkStatusEnumMappingSaveRequest request)
|
||||||
|
{
|
||||||
|
int rows = iEmsDeviceSettingService.saveSiteWorkStatusEnumMappings(request.getSiteId(), request.getMappings(), getUsername());
|
||||||
|
return AjaxResult.success(rows);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PCS设备开关机
|
* PCS设备开关机
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,9 +9,14 @@ import com.xzzn.ems.domain.vo.BatteryDataStatsListVo;
|
|||||||
import com.xzzn.ems.domain.vo.DateSearchRequest;
|
import com.xzzn.ems.domain.vo.DateSearchRequest;
|
||||||
import com.xzzn.ems.domain.vo.RunningGraphRequest;
|
import com.xzzn.ems.domain.vo.RunningGraphRequest;
|
||||||
import com.xzzn.ems.domain.vo.SiteBatteryDataList;
|
import com.xzzn.ems.domain.vo.SiteBatteryDataList;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorDataSaveRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorRuningInfoVo;
|
||||||
|
import com.xzzn.ems.service.IEmsDeviceSettingService;
|
||||||
import com.xzzn.ems.service.IEmsSiteService;
|
import com.xzzn.ems.service.IEmsSiteService;
|
||||||
import com.xzzn.ems.service.IEmsStatsReportService;
|
import com.xzzn.ems.service.IEmsStatsReportService;
|
||||||
import com.xzzn.ems.service.ISingleSiteService;
|
import com.xzzn.ems.service.ISingleSiteService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -26,6 +31,8 @@ import java.util.List;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/ems/siteMonitor")
|
@RequestMapping("/ems/siteMonitor")
|
||||||
public class EmsSiteMonitorController extends BaseController{
|
public class EmsSiteMonitorController extends BaseController{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(EmsSiteMonitorController.class);
|
||||||
|
private static final String RUNNING_GRAPH_CTRL_DEBUG = "RunningGraphCtrlDebug";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISingleSiteService iSingleSiteService;
|
private ISingleSiteService iSingleSiteService;
|
||||||
@ -33,6 +40,8 @@ public class EmsSiteMonitorController extends BaseController{
|
|||||||
private IEmsSiteService iEmsSiteService;
|
private IEmsSiteService iEmsSiteService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEmsStatsReportService iemsStatsReportService;
|
private IEmsStatsReportService iemsStatsReportService;
|
||||||
|
@Autowired
|
||||||
|
private IEmsDeviceSettingService iEmsDeviceSettingService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取单站首页数据
|
* 获取单站首页数据
|
||||||
@ -43,6 +52,15 @@ public class EmsSiteMonitorController extends BaseController{
|
|||||||
return success(iSingleSiteService.getSiteMonitorDataVo(siteId));
|
return success(iSingleSiteService.getSiteMonitorDataVo(siteId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单站首页总累计运行数据(基于日表)
|
||||||
|
*/
|
||||||
|
@GetMapping("/homeTotalView")
|
||||||
|
public AjaxResult getSingleSiteHomeTotalView(@RequestParam String siteId)
|
||||||
|
{
|
||||||
|
return success(iSingleSiteService.getSiteMonitorTotalDataVo(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单站监控-设备监控-实时运行头部数据
|
* 单站监控-设备监控-实时运行头部数据
|
||||||
*/
|
*/
|
||||||
@ -56,27 +74,75 @@ public class EmsSiteMonitorController extends BaseController{
|
|||||||
* 单站监控-设备监控-实时运行曲线图数据
|
* 单站监控-设备监控-实时运行曲线图数据
|
||||||
*/
|
*/
|
||||||
@GetMapping("/runningGraph/storagePower")
|
@GetMapping("/runningGraph/storagePower")
|
||||||
public AjaxResult getRunningGraphStorage(RunningGraphRequest request)
|
public AjaxResult getRunningGraphStorage(RunningGraphRequest request,
|
||||||
|
@RequestParam(required = false) String startDate,
|
||||||
|
@RequestParam(required = false) String endDate)
|
||||||
{
|
{
|
||||||
return success(iSingleSiteService.getRunningGraphStorage(request));
|
SiteMonitorRuningInfoVo data = iSingleSiteService.getRunningGraphStorage(request);
|
||||||
|
int deviceCount = data == null || data.getPcsPowerList() == null ? 0 : data.getPcsPowerList().size();
|
||||||
|
log.info("{} storage, siteId={}, rawStartDate={}, rawEndDate={}, bindStartDate={}, bindEndDate={}, deviceCount={}",
|
||||||
|
RUNNING_GRAPH_CTRL_DEBUG,
|
||||||
|
request == null ? null : request.getSiteId(),
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
request == null ? null : request.getStartDate(),
|
||||||
|
request == null ? null : request.getEndDate(),
|
||||||
|
deviceCount);
|
||||||
|
return success(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/runningGraph/pcsMaxTemp")
|
@GetMapping("/runningGraph/pcsMaxTemp")
|
||||||
public AjaxResult getRunningGraphPcsMaxTemp(RunningGraphRequest request)
|
public AjaxResult getRunningGraphPcsMaxTemp(RunningGraphRequest request,
|
||||||
|
@RequestParam(required = false) String startDate,
|
||||||
|
@RequestParam(required = false) String endDate)
|
||||||
{
|
{
|
||||||
return success(iSingleSiteService.getRunningGraphPcsMaxTemp(request));
|
SiteMonitorRuningInfoVo data = iSingleSiteService.getRunningGraphPcsMaxTemp(request);
|
||||||
|
int deviceCount = data == null || data.getPcsMaxTempList() == null ? 0 : data.getPcsMaxTempList().size();
|
||||||
|
log.info("{} pcsMaxTemp, siteId={}, rawStartDate={}, rawEndDate={}, bindStartDate={}, bindEndDate={}, deviceCount={}",
|
||||||
|
RUNNING_GRAPH_CTRL_DEBUG,
|
||||||
|
request == null ? null : request.getSiteId(),
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
request == null ? null : request.getStartDate(),
|
||||||
|
request == null ? null : request.getEndDate(),
|
||||||
|
deviceCount);
|
||||||
|
return success(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/runningGraph/batteryAveSoc")
|
@GetMapping("/runningGraph/batteryAveSoc")
|
||||||
public AjaxResult getRunningGraphBatterySoc(RunningGraphRequest request)
|
public AjaxResult getRunningGraphBatterySoc(RunningGraphRequest request,
|
||||||
|
@RequestParam(required = false) String startDate,
|
||||||
|
@RequestParam(required = false) String endDate)
|
||||||
{
|
{
|
||||||
return success(iSingleSiteService.getRunningGraphBatterySoc(request));
|
SiteMonitorRuningInfoVo data = iSingleSiteService.getRunningGraphBatterySoc(request);
|
||||||
|
int pointCount = data == null || data.getBatteryAveSOCList() == null ? 0 : data.getBatteryAveSOCList().size();
|
||||||
|
log.info("{} batteryAveSoc, siteId={}, rawStartDate={}, rawEndDate={}, bindStartDate={}, bindEndDate={}, pointCount={}",
|
||||||
|
RUNNING_GRAPH_CTRL_DEBUG,
|
||||||
|
request == null ? null : request.getSiteId(),
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
request == null ? null : request.getStartDate(),
|
||||||
|
request == null ? null : request.getEndDate(),
|
||||||
|
pointCount);
|
||||||
|
return success(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/runningGraph/batteryAveTemp")
|
@GetMapping("/runningGraph/batteryAveTemp")
|
||||||
public AjaxResult getRunningGraphBatteryTemp(RunningGraphRequest request)
|
public AjaxResult getRunningGraphBatteryTemp(RunningGraphRequest request,
|
||||||
|
@RequestParam(required = false) String startDate,
|
||||||
|
@RequestParam(required = false) String endDate)
|
||||||
{
|
{
|
||||||
return success(iSingleSiteService.getRunningGraphBatteryTemp(request));
|
SiteMonitorRuningInfoVo data = iSingleSiteService.getRunningGraphBatteryTemp(request);
|
||||||
|
int pointCount = data == null || data.getBatteryAveTempList() == null ? 0 : data.getBatteryAveTempList().size();
|
||||||
|
log.info("{} batteryAveTemp, siteId={}, rawStartDate={}, rawEndDate={}, bindStartDate={}, bindEndDate={}, pointCount={}",
|
||||||
|
RUNNING_GRAPH_CTRL_DEBUG,
|
||||||
|
request == null ? null : request.getSiteId(),
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
request == null ? null : request.getStartDate(),
|
||||||
|
request == null ? null : request.getEndDate(),
|
||||||
|
pointCount);
|
||||||
|
return success(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,9 +217,7 @@ public class EmsSiteMonitorController extends BaseController{
|
|||||||
{
|
{
|
||||||
startPage();
|
startPage();
|
||||||
SiteBatteryDataList siteBatteryDataList = new SiteBatteryDataList();
|
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);
|
List<BatteryDataStatsListVo> List = iSingleSiteService.getClusterDataInfoList(clusterDeviceId,siteId,stackDeviceId,batteryId);
|
||||||
// 对batteryList进行分页处理
|
// 对batteryList进行分页处理
|
||||||
@ -228,4 +292,31 @@ public class EmsSiteMonitorController extends BaseController{
|
|||||||
return error("缺少必传项");
|
return error("缺少必传项");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控项目点位配置查询
|
||||||
|
*/
|
||||||
|
@GetMapping("/getProjectPointMapping")
|
||||||
|
public AjaxResult getProjectPointMapping(@RequestParam String siteId)
|
||||||
|
{
|
||||||
|
return success(iEmsDeviceSettingService.getSiteMonitorProjectPointMapping(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控项目展示数据查询(配置字段 + 字段值)
|
||||||
|
*/
|
||||||
|
@GetMapping("/getProjectDisplayData")
|
||||||
|
public AjaxResult getProjectDisplayData(@RequestParam String siteId)
|
||||||
|
{
|
||||||
|
return success(iEmsDeviceSettingService.getSiteMonitorProjectDisplay(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控项目展示数据写入
|
||||||
|
*/
|
||||||
|
@PostMapping("/saveProjectDisplayData")
|
||||||
|
public AjaxResult saveProjectDisplayData(@RequestBody SiteMonitorDataSaveRequest request)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(iEmsDeviceSettingService.saveSiteMonitorProjectData(request, getUsername()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,33 @@
|
|||||||
package com.xzzn.web.controller.ems;
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Log;
|
||||||
import com.xzzn.common.core.controller.BaseController;
|
import com.xzzn.common.core.controller.BaseController;
|
||||||
import com.xzzn.common.core.domain.AjaxResult;
|
import com.xzzn.common.core.domain.AjaxResult;
|
||||||
import com.xzzn.common.core.page.TableDataInfo;
|
import com.xzzn.common.core.page.TableDataInfo;
|
||||||
|
import com.xzzn.common.enums.BusinessType;
|
||||||
import com.xzzn.common.utils.StringUtils;
|
import com.xzzn.common.utils.StringUtils;
|
||||||
import com.xzzn.ems.domain.vo.*;
|
import com.xzzn.ems.domain.vo.AmmeterRevenueStatisListVo;
|
||||||
|
import com.xzzn.ems.domain.vo.AmmeterStatisListVo;
|
||||||
|
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.domain.vo.WeatherSyncResultVo;
|
||||||
import com.xzzn.ems.service.IEmsStatsReportService;
|
import com.xzzn.ems.service.IEmsStatsReportService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import com.xzzn.ems.service.IEmsWeatherSyncService;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单站监控-统计报表
|
* 单站监控-统计报表
|
||||||
*
|
*
|
||||||
@ -26,6 +40,8 @@ public class EmsStatisticalReportController extends BaseController
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEmsStatsReportService ieEmsStatsReportService;
|
private IEmsStatsReportService ieEmsStatsReportService;
|
||||||
|
@Autowired
|
||||||
|
private IEmsWeatherSyncService iEmsWeatherSyncService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 概率统计-收益指标查询
|
* 概率统计-收益指标查询
|
||||||
@ -118,6 +134,39 @@ public class EmsStatisticalReportController extends BaseController
|
|||||||
return getDataTable(dataList);
|
return getDataTable(dataList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计报表-电表报表(直接基于 ems_daily_energy_data)
|
||||||
|
*/
|
||||||
|
@GetMapping("/getAmmeterDataFromDaily")
|
||||||
|
public TableDataInfo getAmmeterDataFromDaily(StatisAmmeterDateRequest requestVo)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<AmmeterStatisListVo> dataList = ieEmsStatsReportService.getAmmeterDataResult(requestVo);
|
||||||
|
return getDataTable(dataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出电表报表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:ammeterData:export')")
|
||||||
|
@Log(title = "电表报表", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/exportAmmeterData")
|
||||||
|
public void exportAmmeterData(HttpServletResponse response, StatisAmmeterDateRequest requestVo)
|
||||||
|
{
|
||||||
|
ieEmsStatsReportService.exportAmmeterData(response, requestVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出电表报表(直接基于 ems_daily_energy_data)
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:ammeterData:export')")
|
||||||
|
@Log(title = "电表报表", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/exportAmmeterDataFromDaily")
|
||||||
|
public void exportAmmeterDataFromDaily(HttpServletResponse response, StatisAmmeterDateRequest requestVo)
|
||||||
|
{
|
||||||
|
ieEmsStatsReportService.exportAmmeterData(response, requestVo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 概率统计-电表收益报表
|
* 概率统计-电表收益报表
|
||||||
*/
|
*/
|
||||||
@ -129,6 +178,17 @@ public class EmsStatisticalReportController extends BaseController
|
|||||||
return getDataTable(dataList);
|
return getDataTable(dataList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出收益报表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:ammeterRevenueData:export')")
|
||||||
|
@Log(title = "收益报表", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/exportAmmeterRevenueData")
|
||||||
|
public void exportAmmeterRevenueData(HttpServletResponse response, StatisAmmeterDateRequest requestVo)
|
||||||
|
{
|
||||||
|
ieEmsStatsReportService.exportAmmeterRevenueData(response, requestVo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 概率统计-功率曲线
|
* 概率统计-功率曲线
|
||||||
*/
|
*/
|
||||||
@ -142,4 +202,19 @@ public class EmsStatisticalReportController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手动触发天气同步
|
||||||
|
*/
|
||||||
|
@PostMapping("/syncWeatherByDateRange")
|
||||||
|
public AjaxResult syncWeatherByDateRange(StatisAmmeterDateRequest requestVo)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(requestVo.getSiteId())
|
||||||
|
|| StringUtils.isEmpty(requestVo.getStartTime())
|
||||||
|
|| StringUtils.isEmpty(requestVo.getEndTime())) {
|
||||||
|
return error("缺少必传项: siteId/startTime/endTime");
|
||||||
|
}
|
||||||
|
WeatherSyncResultVo resultVo = iEmsWeatherSyncService.syncWeatherByDateRange(requestVo);
|
||||||
|
return success(resultVo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.xzzn.web.controller.ems;
|
||||||
|
|
||||||
|
import com.xzzn.common.core.controller.BaseController;
|
||||||
|
import com.xzzn.common.core.domain.AjaxResult;
|
||||||
|
import com.xzzn.common.utils.StringUtils;
|
||||||
|
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||||
|
import com.xzzn.ems.service.IEmsStrategyRuntimeConfigService;
|
||||||
|
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.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略运行参数配置Controller
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/strategyRuntimeConfig")
|
||||||
|
public class EmsStrategyRuntimeConfigController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IEmsStrategyRuntimeConfigService runtimeConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按站点ID获取策略运行参数
|
||||||
|
*/
|
||||||
|
@GetMapping("/getBySiteId")
|
||||||
|
public AjaxResult getBySiteId(String siteId) {
|
||||||
|
if (StringUtils.isEmpty(siteId)) {
|
||||||
|
return error("缺少必填字段siteId");
|
||||||
|
}
|
||||||
|
return success(runtimeConfigService.getBySiteId(siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存策略运行参数(按siteId新增/更新)
|
||||||
|
*/
|
||||||
|
@PostMapping("/save")
|
||||||
|
public AjaxResult save(@RequestBody EmsStrategyRuntimeConfig config) {
|
||||||
|
if (config == null || StringUtils.isEmpty(config.getSiteId())) {
|
||||||
|
return error("缺少必填字段siteId");
|
||||||
|
}
|
||||||
|
config.setCreateBy(getUsername());
|
||||||
|
config.setUpdateBy(getUsername());
|
||||||
|
return toAjax(runtimeConfigService.saveBySiteId(config));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,12 +6,7 @@ import com.xzzn.common.enums.TopicHandleType;
|
|||||||
import com.xzzn.common.utils.StringUtils;
|
import com.xzzn.common.utils.StringUtils;
|
||||||
import com.xzzn.ems.domain.EmsMqttTopicConfig;
|
import com.xzzn.ems.domain.EmsMqttTopicConfig;
|
||||||
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
|
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
|
||||||
import com.xzzn.ems.service.IDDSDataProcessService;
|
|
||||||
import com.xzzn.ems.service.IDeviceDataProcessService;
|
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.ems.service.IMqttSyncLogService;
|
||||||
import com.xzzn.framework.manager.MqttLifecycleManager;
|
import com.xzzn.framework.manager.MqttLifecycleManager;
|
||||||
import com.xzzn.framework.web.service.MqttPublisher;
|
import com.xzzn.framework.web.service.MqttPublisher;
|
||||||
@ -27,6 +22,7 @@ import org.eclipse.paho.client.mqttv3.MqttException;
|
|||||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -38,29 +34,19 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
|||||||
|
|
||||||
private final MqttLifecycleManager mqttLifecycleManager;
|
private final MqttLifecycleManager mqttLifecycleManager;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IEmsMqttMessageService emsMqttMessageService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IFXXDataProcessService fXXDataProcessService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDDSDataProcessService dDSDataProcessService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IDeviceDataProcessService deviceDataProcessService;
|
private IDeviceDataProcessService deviceDataProcessService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IFXXAlarmDataProcessService fXXAlarmDataProcessService;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
|
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEmsStrategyService emsStrategyService;
|
|
||||||
@Autowired
|
|
||||||
private IMqttSyncLogService iMqttSyncLogService;
|
private IMqttSyncLogService iMqttSyncLogService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
@Autowired
|
||||||
|
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public MqttMessageController(MqttLifecycleManager mqttLifecycleManager) {
|
public MqttMessageController(MqttLifecycleManager mqttLifecycleManager) {
|
||||||
@ -136,51 +122,32 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
|||||||
private void handleSystemStatus(String topic, MqttMessage message) {
|
private void handleSystemStatus(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[SYSTEM] Status update: " + payload);
|
System.out.println("[SYSTEM] Status update: " + payload);
|
||||||
|
|
||||||
try {
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to process system status message: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理设备数据
|
// 处理设备数据
|
||||||
private void handleDeviceData(String topic, MqttMessage message) {
|
private void handleDeviceData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
log.error("[DEVICE] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
|
log.debug("[DEVICE] data: {}", payload);
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
// if (topic.startsWith("021_DDS")) {
|
|
||||||
// dDSDataProcessService.handleDdsData(payload);
|
|
||||||
// } else if (topic.startsWith("021_FXX")) {
|
|
||||||
// fXXDataProcessService.handleFxData(payload);
|
|
||||||
// }
|
|
||||||
deviceDataProcessService.handleDeviceData(payload, getSiteIdByTopic(topic));
|
deviceDataProcessService.handleDeviceData(payload, getSiteIdByTopic(topic));
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process device data message: " + e.getMessage(), e);
|
log.error("Failed to process device data message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理告警数据
|
// 处理告警数据
|
||||||
private void handleAlarmData(String topic, MqttMessage message) {
|
private void handleAlarmData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[DEVICE] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
// if (topic.startsWith("021_FXX")) {
|
|
||||||
// fXXAlarmDataProcessService.handleFxAlarmData(payload);
|
|
||||||
// }
|
|
||||||
deviceDataProcessService.handleAlarmData(payload, getSiteIdByTopic(topic));
|
deviceDataProcessService.handleAlarmData(payload, getSiteIdByTopic(topic));
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
log.error("Failed to process device alarm data message: {}", e.getMessage(), e);
|
||||||
log.error("Failed to process device alarm data message: " + e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,78 +158,67 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
|||||||
siteId = topicConfig.getSiteId();
|
siteId = topicConfig.getSiteId();
|
||||||
redisCache.setCacheObject(RedisKeyConstants.SITE_ID + topic, siteId);
|
redisCache.setCacheObject(RedisKeyConstants.SITE_ID + topic, siteId);
|
||||||
}
|
}
|
||||||
log.info("当前处理数据站点:" + siteId + ",topic: " + topic);
|
|
||||||
return siteId;
|
return siteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理运行策略数据:云端-本地
|
// 处理运行策略数据:云端-本地
|
||||||
private void handleStrategyData(String topic, MqttMessage message) {
|
private void handleStrategyData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[处理运行策略数据] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
iMqttSyncLogService.handleMqttStrategyData(payload);
|
iMqttSyncLogService.handleMqttStrategyData(payload);
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process strategy data message: " + e.getMessage(), e);
|
log.error("Failed to process strategy data message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理设备保护告警策略数据:云端-本地
|
// 处理设备保护告警策略数据:云端-本地
|
||||||
private void handleFaultProtPlanData(String topic, MqttMessage message) {
|
private void handleFaultProtPlanData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[处理设备保护告警策略数据] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
iMqttSyncLogService.handleMqttPlanData(payload);
|
iMqttSyncLogService.handleMqttPlanData(payload);
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process fault plan data message: " + e.getMessage(), e);
|
log.error("Failed to process fault plan data message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理保护策略告警信息:本地-云端
|
// 处理保护策略告警信息:本地-云端
|
||||||
private void handleFaultAlarmData(String topic, MqttMessage message) {
|
private void handleFaultAlarmData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[处理本地保护策略告警信息到云端] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
iMqttSyncLogService.handleFaultAlarmData(payload);
|
iMqttSyncLogService.handleFaultAlarmData(payload);
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process fault plan alarm data message: " + e.getMessage(), e);
|
log.error("Failed to process fault plan alarm data message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理保护策略下发日志:本地-云端
|
// 处理保护策略下发日志:本地-云端
|
||||||
private void handleFaultPlanIssueData(String topic, MqttMessage message) {
|
private void handleFaultPlanIssueData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[处理本地保护策略下发日志到云端] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
iMqttSyncLogService.handleFaultPlanIssueData(payload);
|
iMqttSyncLogService.handleFaultPlanIssueData(payload);
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process fault plan issue log message: " + e.getMessage(), e);
|
log.error("Failed to process fault plan issue log message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理设备状态变更日志:本地-云端
|
// 处理设备状态变更日志:本地-云端
|
||||||
private void handleDeviceChangeLogData(String topic, MqttMessage message) {
|
private void handleDeviceChangeLogData(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
System.out.println("[处理本地的保护策略告警信息到云端] data: " + payload);
|
threadPoolTaskExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// 业务处理逻辑
|
|
||||||
iMqttSyncLogService.handleDeviceChangeLogData(payload);
|
iMqttSyncLogService.handleDeviceChangeLogData(payload);
|
||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic,payload);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process device change log message: " + e.getMessage(), e);
|
log.error("Failed to process device change log message: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -205,3 +205,10 @@ modbus:
|
|||||||
poll:
|
poll:
|
||||||
interval: "0 */5 * * * *" # 5分钟间隔
|
interval: "0 */5 * * * *" # 5分钟间隔
|
||||||
timeout: 30000 # 30秒超时
|
timeout: 30000 # 30秒超时
|
||||||
|
|
||||||
|
weather:
|
||||||
|
api:
|
||||||
|
enabled: true
|
||||||
|
base-url: https://archive-api.open-meteo.com/v1/archive
|
||||||
|
api-key:
|
||||||
|
timezone: Asia/Shanghai
|
||||||
|
|||||||
@ -205,3 +205,10 @@ modbus:
|
|||||||
poll:
|
poll:
|
||||||
interval: "0 */5 * * * *" # 5分钟间隔
|
interval: "0 */5 * * * *" # 5分钟间隔
|
||||||
timeout: 30000 # 30秒超时
|
timeout: 30000 # 30秒超时
|
||||||
|
|
||||||
|
weather:
|
||||||
|
api:
|
||||||
|
enabled: true
|
||||||
|
base-url: https://archive-api.open-meteo.com/v1/archive
|
||||||
|
api-key:
|
||||||
|
timezone: Asia/Shanghai
|
||||||
|
|||||||
@ -199,6 +199,20 @@ mqtt:
|
|||||||
topic:
|
topic:
|
||||||
siteId:
|
siteId:
|
||||||
|
|
||||||
|
influxdb:
|
||||||
|
enabled: true
|
||||||
|
url: http://122.51.194.184:8086/
|
||||||
|
api-token: F2XcmBzZsWcz90ikU2_t7UXY2fzWuf2ruVp1BkusNkIS_gwrQZuiaIjl33XQMQajm7vSI6TQSRnpPSx5CXThlA==
|
||||||
|
write-method: POST
|
||||||
|
read-method: GET
|
||||||
|
write-path: /api/v2/write
|
||||||
|
query-path: /query
|
||||||
|
org: ems
|
||||||
|
bucket: point_data
|
||||||
|
database: ems_point_data
|
||||||
|
retention-policy: autogen
|
||||||
|
measurement: mqtt_point_data
|
||||||
|
|
||||||
modbus:
|
modbus:
|
||||||
pool:
|
pool:
|
||||||
max-total: 20
|
max-total: 20
|
||||||
@ -207,3 +221,10 @@ modbus:
|
|||||||
poll:
|
poll:
|
||||||
interval: "0 */5 * * * *" # 5分钟间隔
|
interval: "0 */5 * * * *" # 5分钟间隔
|
||||||
timeout: 30000 # 30秒超时
|
timeout: 30000 # 30秒超时
|
||||||
|
|
||||||
|
weather:
|
||||||
|
api:
|
||||||
|
enabled: true
|
||||||
|
base-url: https://archive-api.open-meteo.com/v1/archive
|
||||||
|
api-key:
|
||||||
|
timezone: Asia/Shanghai
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- 日志存放路径 -->
|
<!-- 日志存放路径 -->
|
||||||
<property name="log.path" value="/etc/xzzn/logs" />
|
<property name="log.path" value="logs" />
|
||||||
<!-- 日志输出格式 -->
|
<!-- 日志输出格式 -->
|
||||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||||
|
|
||||||
|
|||||||
@ -103,6 +103,9 @@ public class RedisKeyConstants
|
|||||||
|
|
||||||
/** 设备信息初始化 */
|
/** 设备信息初始化 */
|
||||||
public static final String INIT_DEVICE_INFO = "init_device_info";
|
public static final String INIT_DEVICE_INFO = "init_device_info";
|
||||||
|
|
||||||
|
/** 设备配置缓存(按站点+设备) */
|
||||||
|
public static final String DEVICE_SETTING = "DEVICE_SETTING_";
|
||||||
/** 告警匹配信息 */
|
/** 告警匹配信息 */
|
||||||
public static final String ALARM_MATCH_INFO = "alarm_message_info";
|
public static final String ALARM_MATCH_INFO = "alarm_message_info";
|
||||||
|
|
||||||
@ -122,4 +125,19 @@ public class RedisKeyConstants
|
|||||||
|
|
||||||
/** 每个设备最新数据-设置失效时间-判断是否正常同步数据 */
|
/** 每个设备最新数据-设置失效时间-判断是否正常同步数据 */
|
||||||
public static final String SYNC_DATA_ALARM = "SYNC_DATA_ALARM_";
|
public static final String SYNC_DATA_ALARM = "SYNC_DATA_ALARM_";
|
||||||
|
|
||||||
|
/** 点位配置缓存(按站点+设备) */
|
||||||
|
public static final String POINT_CONFIG_DEVICE = "POINT_CONFIG_DEVICE_";
|
||||||
|
|
||||||
|
/** 点位配置缓存(按站点+pointId) */
|
||||||
|
public static final String POINT_CONFIG_POINT = "POINT_CONFIG_POINT_";
|
||||||
|
|
||||||
|
/** 单站监控最新数据(按站点+模块) */
|
||||||
|
public static final String SITE_MONITOR_LATEST = "SITE_MONITOR_LATEST_";
|
||||||
|
|
||||||
|
/** 单站监控点位映射(按站点) */
|
||||||
|
public static final String SITE_MONITOR_POINT_MATCH = "SITE_MONITOR_POINT_MATCH_";
|
||||||
|
|
||||||
|
/** 站点保护约束(按站点) */
|
||||||
|
public static final String PROTECTION_CONSTRAINT = "PROTECTION_CONSTRAINT_";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,21 +3,37 @@ package com.xzzn.framework.manager;
|
|||||||
import com.xzzn.ems.service.IEmsAlarmRecordsService;
|
import com.xzzn.ems.service.IEmsAlarmRecordsService;
|
||||||
import org.eclipse.paho.client.mqttv3.*;
|
import org.eclipse.paho.client.mqttv3.*;
|
||||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.context.SmartLifecycle;
|
import org.springframework.context.SmartLifecycle;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle, MqttCallback {
|
public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle, MqttCallbackExtended {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MqttLifecycleManager.class);
|
||||||
|
private static final long RECONNECT_DELAY_SECONDS = 5;
|
||||||
|
|
||||||
private final MqttConnectOptions connectOptions;
|
private final MqttConnectOptions connectOptions;
|
||||||
private final IEmsAlarmRecordsService iEmsAlarmRecordsService;
|
private final IEmsAlarmRecordsService iEmsAlarmRecordsService;
|
||||||
|
private final ScheduledExecutorService reconnectExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||||
|
Thread thread = new Thread(r);
|
||||||
|
thread.setName("mqtt-reconnect");
|
||||||
|
thread.setDaemon(true);
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
private final AtomicBoolean reconnectScheduled = new AtomicBoolean(false);
|
||||||
|
private volatile ScheduledFuture<?> reconnectFuture;
|
||||||
private MqttClient mqttClient;
|
private MqttClient mqttClient;
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
|
|
||||||
@ -41,7 +57,9 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
|
|||||||
if (running) return;
|
if (running) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String clientId = connectOptions.getUserName() + "-" + System.currentTimeMillis();
|
String prefix = connectOptions.getUserName() == null || connectOptions.getUserName().isEmpty()
|
||||||
|
? "mqtt-client" : connectOptions.getUserName();
|
||||||
|
String clientId = prefix + "-" + System.currentTimeMillis();
|
||||||
mqttClient = new MqttClient(
|
mqttClient = new MqttClient(
|
||||||
connectOptions.getServerURIs()[0],
|
connectOptions.getServerURIs()[0],
|
||||||
clientId,
|
clientId,
|
||||||
@ -51,27 +69,28 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
|
|||||||
mqttClient.setCallback(this);
|
mqttClient.setCallback(this);
|
||||||
mqttClient.connect(connectOptions);
|
mqttClient.connect(connectOptions);
|
||||||
|
|
||||||
// 重连后自动重新订阅
|
|
||||||
resubscribeAll();
|
resubscribeAll();
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
System.out.println("MQTT client connected to: " + connectOptions.getServerURIs()[0]);
|
log.info("MQTT client connected to: {}", connectOptions.getServerURIs()[0]);
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
System.err.println("MQTT connection failed: " + e.getMessage());
|
running = false;
|
||||||
// 添加重试逻辑
|
log.error("MQTT connection failed: {}", e.getMessage(), e);
|
||||||
|
scheduleReconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
cancelReconnectTask();
|
||||||
if (mqttClient != null && mqttClient.isConnected()) {
|
if (mqttClient != null && mqttClient.isConnected()) {
|
||||||
try {
|
try {
|
||||||
mqttClient.disconnect();
|
mqttClient.disconnect();
|
||||||
mqttClient.close();
|
mqttClient.close();
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
System.err.println("Error disconnecting MQTT client: " + e.getMessage());
|
log.warn("Error disconnecting MQTT client: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
reconnectExecutor.shutdownNow();
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,9 +102,17 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
|
|||||||
// MQTT 回调方法
|
// MQTT 回调方法
|
||||||
@Override
|
@Override
|
||||||
public void connectionLost(Throwable cause) {
|
public void connectionLost(Throwable cause) {
|
||||||
System.err.println("MQTT connection lost: " + cause.getMessage());
|
log.warn("MQTT connection lost: {}", cause == null ? "unknown" : cause.getMessage(), cause);
|
||||||
running = false;
|
running = false;
|
||||||
// 自动重连由 MqttConnectOptions 处理
|
scheduleReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectComplete(boolean reconnect, String serverURI) {
|
||||||
|
running = true;
|
||||||
|
cancelReconnectTask();
|
||||||
|
log.info("MQTT connection complete, reconnect: {}, serverURI: {}", reconnect, serverURI);
|
||||||
|
resubscribeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -106,14 +133,16 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
|
|||||||
try {
|
try {
|
||||||
if (mqttClient != null && mqttClient.isConnected()) {
|
if (mqttClient != null && mqttClient.isConnected()) {
|
||||||
mqttClient.subscribe(topic, qos);
|
mqttClient.subscribe(topic, qos);
|
||||||
|
log.info("MQTT subscribe success, topic: {}, qos: {}", topic, qos);
|
||||||
|
} else {
|
||||||
|
log.warn("MQTT subscribe deferred, client not connected, topic: {}", topic);
|
||||||
}
|
}
|
||||||
subscriptions.put(topic, new SubscriptionInfo(listener, qos));
|
subscriptions.put(topic, new SubscriptionInfo(listener, qos));
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
System.err.println("Subscribe failed: " + e.getMessage());
|
log.error("Subscribe failed, topic: {}, err: {}", topic, e.getMessage(), e);
|
||||||
// 订阅失败-增加告警
|
|
||||||
iEmsAlarmRecordsService.addSubFailedAlarmRecord(topic);
|
iEmsAlarmRecordsService.addSubFailedAlarmRecord(topic);
|
||||||
|
scheduleReconnect();
|
||||||
}
|
}
|
||||||
// 订阅成功了-校验是否存在未处理或者处理中的订阅失败信息
|
|
||||||
iEmsAlarmRecordsService.checkFailedRecord(topic);
|
iEmsAlarmRecordsService.checkFailedRecord(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,12 +164,52 @@ public class MqttLifecycleManager implements ApplicationRunner, SmartLifecycle,
|
|||||||
subscriptions.forEach((topic, info) -> {
|
subscriptions.forEach((topic, info) -> {
|
||||||
try {
|
try {
|
||||||
mqttClient.subscribe(topic, info.getQos());
|
mqttClient.subscribe(topic, info.getQos());
|
||||||
|
log.info("MQTT resubscribe success, topic: {}, qos: {}", topic, info.getQos());
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
System.err.println("Resubscribe failed for topic: " + topic);
|
log.error("Resubscribe failed for topic: {}, err: {}", topic, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scheduleReconnect() {
|
||||||
|
if (mqttClient == null || reconnectExecutor.isShutdown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!reconnectScheduled.compareAndSet(false, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnectFuture = reconnectExecutor.scheduleWithFixedDelay(() -> {
|
||||||
|
if (mqttClient == null) {
|
||||||
|
cancelReconnectTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mqttClient.isConnected()) {
|
||||||
|
cancelReconnectTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
log.info("MQTT reconnecting...");
|
||||||
|
mqttClient.connect(connectOptions);
|
||||||
|
running = true;
|
||||||
|
cancelReconnectTask();
|
||||||
|
resubscribeAll();
|
||||||
|
log.info("MQTT reconnect success.");
|
||||||
|
} catch (MqttException e) {
|
||||||
|
running = false;
|
||||||
|
log.warn("MQTT reconnect failed: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}, RECONNECT_DELAY_SECONDS, RECONNECT_DELAY_SECONDS, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelReconnectTask() {
|
||||||
|
reconnectScheduled.set(false);
|
||||||
|
ScheduledFuture<?> future = reconnectFuture;
|
||||||
|
if (future != null && !future.isCancelled()) {
|
||||||
|
future.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 订阅信息内部类
|
// 订阅信息内部类
|
||||||
private static class SubscriptionInfo {
|
private static class SubscriptionInfo {
|
||||||
private final IMqttMessageListener listener;
|
private final IMqttMessageListener listener;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.xzzn.generator.controller;
|
package com.xzzn.generator.controller;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -18,10 +17,6 @@ import org.springframework.web.bind.annotation.PutMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.alibaba.druid.DbType;
|
|
||||||
import com.alibaba.druid.sql.SQLUtils;
|
|
||||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
|
||||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
|
||||||
import com.xzzn.common.annotation.Log;
|
import com.xzzn.common.annotation.Log;
|
||||||
import com.xzzn.common.core.controller.BaseController;
|
import com.xzzn.common.core.controller.BaseController;
|
||||||
import com.xzzn.common.core.domain.AjaxResult;
|
import com.xzzn.common.core.domain.AjaxResult;
|
||||||
@ -29,7 +24,6 @@ import com.xzzn.common.core.page.TableDataInfo;
|
|||||||
import com.xzzn.common.core.text.Convert;
|
import com.xzzn.common.core.text.Convert;
|
||||||
import com.xzzn.common.enums.BusinessType;
|
import com.xzzn.common.enums.BusinessType;
|
||||||
import com.xzzn.common.utils.SecurityUtils;
|
import com.xzzn.common.utils.SecurityUtils;
|
||||||
import com.xzzn.common.utils.sql.SqlUtil;
|
|
||||||
import com.xzzn.generator.config.GenConfig;
|
import com.xzzn.generator.config.GenConfig;
|
||||||
import com.xzzn.generator.domain.GenTable;
|
import com.xzzn.generator.domain.GenTable;
|
||||||
import com.xzzn.generator.domain.GenTableColumn;
|
import com.xzzn.generator.domain.GenTableColumn;
|
||||||
@ -121,43 +115,6 @@ public class GenController extends BaseController
|
|||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表结构(保存)
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasRole('admin')")
|
|
||||||
@Log(title = "创建表", businessType = BusinessType.OTHER)
|
|
||||||
@PostMapping("/createTable")
|
|
||||||
public AjaxResult createTableSave(String sql)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SqlUtil.filterKeyword(sql);
|
|
||||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
|
|
||||||
List<String> tableNames = new ArrayList<>();
|
|
||||||
for (SQLStatement sqlStatement : sqlStatements)
|
|
||||||
{
|
|
||||||
if (sqlStatement instanceof MySqlCreateTableStatement)
|
|
||||||
{
|
|
||||||
MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
|
|
||||||
if (genTableService.createTable(createTableStatement.toString()))
|
|
||||||
{
|
|
||||||
String tableName = createTableStatement.getTableName().replaceAll("`", "");
|
|
||||||
tableNames.add(tableName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
|
|
||||||
String operName = SecurityUtils.getUsername();
|
|
||||||
genTableService.importGenTable(tableList, operName);
|
|
||||||
return AjaxResult.success();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return AjaxResult.error("创建表结构异常");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改保存代码生成业务
|
* 修改保存代码生成业务
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -81,11 +81,4 @@ public interface GenTableMapper
|
|||||||
*/
|
*/
|
||||||
public int deleteGenTableByIds(Long[] ids);
|
public int deleteGenTableByIds(Long[] ids);
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表
|
|
||||||
*
|
|
||||||
* @param sql 表结构
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
public int createTable(String sql);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,18 +149,6 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
|
genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表
|
|
||||||
*
|
|
||||||
* @param sql 创建表语句
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean createTable(String sql)
|
|
||||||
{
|
|
||||||
return genTableMapper.createTable(sql) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入表结构
|
* 导入表结构
|
||||||
*
|
*
|
||||||
|
|||||||
@ -66,14 +66,6 @@ public interface IGenTableService
|
|||||||
*/
|
*/
|
||||||
public void deleteGenTableByIds(Long[] tableIds);
|
public void deleteGenTableByIds(Long[] tableIds);
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表
|
|
||||||
*
|
|
||||||
* @param sql 创建表语句
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
public boolean createTable(String sql);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入表结构
|
* 导入表结构
|
||||||
*
|
*
|
||||||
|
|||||||
@ -171,10 +171,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="createTable">
|
|
||||||
${sql}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateGenTable" parameterType="GenTable">
|
<update id="updateGenTable" parameterType="GenTable">
|
||||||
update gen_table
|
update gen_table
|
||||||
<set>
|
<set>
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.xzzn.quartz.task;
|
||||||
|
|
||||||
|
import com.xzzn.common.utils.StringUtils;
|
||||||
|
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("calcPointTask")
|
||||||
|
public class CalcPointTask {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CalcPointTask.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceDataProcessServiceImpl deviceDataProcessService;
|
||||||
|
|
||||||
|
public void syncAllSites() {
|
||||||
|
log.info("开始执行计算点轮询任务-全站点");
|
||||||
|
deviceDataProcessService.syncCalcPointDataFromInfluxByQuartz();
|
||||||
|
log.info("结束执行计算点轮询任务-全站点");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncBySite(String siteId) {
|
||||||
|
if (StringUtils.isBlank(siteId)) {
|
||||||
|
log.warn("计算点轮询任务参数为空,转为全站点执行");
|
||||||
|
syncAllSites();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String normalizedSiteId = siteId.trim();
|
||||||
|
log.info("开始执行计算点轮询任务-单站点, siteId: {}", normalizedSiteId);
|
||||||
|
deviceDataProcessService.syncCalcPointDataFromInfluxByQuartz(normalizedSiteId);
|
||||||
|
log.info("结束执行计算点轮询任务-单站点, siteId: {}", normalizedSiteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.xzzn.quartz.task;
|
||||||
|
|
||||||
|
import com.xzzn.common.utils.StringUtils;
|
||||||
|
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("dailyChargeDataTask")
|
||||||
|
public class DailyChargeDataTask {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DailyChargeDataTask.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceDataProcessServiceImpl deviceDataProcessService;
|
||||||
|
|
||||||
|
public void syncAllSites() {
|
||||||
|
log.info("开始执行每日充放电数据轮询任务-全站点");
|
||||||
|
deviceDataProcessService.syncDailyChargeDataFromInfluxByQuartz();
|
||||||
|
log.info("结束执行每日充放电数据轮询任务-全站点");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncBySite(String siteId) {
|
||||||
|
if (StringUtils.isBlank(siteId)) {
|
||||||
|
log.warn("每日充放电数据轮询任务参数为空,转为全站点执行");
|
||||||
|
syncAllSites();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String normalizedSiteId = siteId.trim();
|
||||||
|
log.info("开始执行每日充放电数据轮询任务-单站点, siteId: {}", normalizedSiteId);
|
||||||
|
deviceDataProcessService.syncDailyChargeDataFromInfluxByQuartz(normalizedSiteId);
|
||||||
|
log.info("结束执行每日充放电数据轮询任务-单站点, siteId: {}", normalizedSiteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,31 +2,25 @@ package com.xzzn.quartz.task;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.serotonin.modbus4j.ModbusMaster;
|
import com.serotonin.modbus4j.ModbusMaster;
|
||||||
import com.xzzn.common.constant.RedisKeyConstants;
|
import com.xzzn.common.constant.RedisKeyConstants;
|
||||||
import com.xzzn.common.core.modbus.ModbusProcessor;
|
import com.xzzn.common.core.modbus.ModbusProcessor;
|
||||||
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
||||||
|
import com.xzzn.common.core.modbus.domain.TagConfig;
|
||||||
import com.xzzn.common.core.redis.RedisCache;
|
import com.xzzn.common.core.redis.RedisCache;
|
||||||
import com.xzzn.common.enums.DeviceRunningStatus;
|
import com.xzzn.common.enums.DeviceRunningStatus;
|
||||||
import com.xzzn.common.utils.DateUtils;
|
import com.xzzn.common.utils.StringUtils;
|
||||||
import com.xzzn.ems.domain.EmsDevicesSetting;
|
import com.xzzn.ems.domain.EmsDevicesSetting;
|
||||||
|
import com.xzzn.ems.domain.EmsPointConfig;
|
||||||
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
||||||
|
import com.xzzn.ems.mapper.EmsPointConfigMapper;
|
||||||
import com.xzzn.ems.service.IEmsAlarmRecordsService;
|
import com.xzzn.ems.service.IEmsAlarmRecordsService;
|
||||||
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
|
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
|
||||||
import com.xzzn.framework.manager.MqttLifecycleManager;
|
|
||||||
import com.xzzn.framework.web.service.MqttPublisher;
|
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.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -36,9 +30,9 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -54,10 +48,8 @@ import org.springframework.util.CollectionUtils;
|
|||||||
@Component("modbusPoller")
|
@Component("modbusPoller")
|
||||||
public class ModbusPoller {
|
public class ModbusPoller {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ModbusPoller.class);
|
private static final Logger log = LoggerFactory.getLogger(ModbusPoller.class);
|
||||||
|
private static final int SITE_DEVICE_OFFLINE_THRESHOLD = 6;
|
||||||
|
|
||||||
private final MqttLifecycleManager mqttLifecycleManager;
|
|
||||||
private final ScheduledTask scheduledTask;
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
private final Map<String, Integer> deviceFailureCounts = new ConcurrentHashMap<>();
|
private final Map<String, Integer> deviceFailureCounts = new ConcurrentHashMap<>();
|
||||||
private final AtomicBoolean polling = new AtomicBoolean(false);
|
private final AtomicBoolean polling = new AtomicBoolean(false);
|
||||||
|
|
||||||
@ -69,77 +61,46 @@ public class ModbusPoller {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IEmsAlarmRecordsService iEmsAlarmRecordsService;
|
private IEmsAlarmRecordsService iEmsAlarmRecordsService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysJobService iSysJobService;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceDataProcessServiceImpl deviceDataProcessServiceImpl;
|
private DeviceDataProcessServiceImpl deviceDataProcessServiceImpl;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmsDevicesSettingMapper emsDevicesSettingMapper;
|
private EmsDevicesSettingMapper emsDevicesSettingMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private EmsPointConfigMapper emsPointConfigMapper;
|
||||||
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
@Autowired
|
@Autowired
|
||||||
private MqttPublisher mqttPublisher;
|
private MqttPublisher mqttPublisher;
|
||||||
|
|
||||||
@Value("${mqtt.topic}")
|
@Value("${mqtt.topic}")
|
||||||
private String 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() {
|
public void pollAllDevices() {
|
||||||
if (!polling.compareAndSet(false, true)) {
|
if (!polling.compareAndSet(false, true)) {
|
||||||
log.warn("上一次轮询尚未完成,本次轮询跳过");
|
log.warn("上一次轮询尚未完成,本次轮询跳过");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Path devicesDir = Paths.get(System.getProperty("user.dir"), "devices");
|
List<PollingTask> pollingTasks = buildPollingTasks();
|
||||||
if (!Files.exists(devicesDir)) {
|
if (CollectionUtils.isEmpty(pollingTasks)) {
|
||||||
log.error("Devices目录不存在: {}", devicesDir);
|
log.warn("未查询到可用的Modbus采集点位配置,跳过本轮轮询");
|
||||||
polling.set(false);
|
polling.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Path> jsonFiles = null;
|
// 按主机IP分组,同一网关串行访问,避免连接抖动
|
||||||
try {
|
Map<String, List<PollingTask>> groupedByHost = pollingTasks.stream()
|
||||||
jsonFiles = Files.list(devicesDir)
|
.collect(Collectors.groupingBy(
|
||||||
.filter(path -> path.toString().endsWith(".json"))
|
task -> task.getDeviceConfig().getHost(),
|
||||||
.collect(Collectors.toList());
|
HashMap::new,
|
||||||
} catch (IOException e) {
|
Collectors.toList()));
|
||||||
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(() -> {
|
Future<?> future = modbusExecutor.submit(() -> {
|
||||||
for (Map.Entry<String, List<DeviceConfig>> entry : groupedByHost.entrySet()) {
|
for (Map.Entry<String, List<PollingTask>> entry : groupedByHost.entrySet()) {
|
||||||
String hostKey = entry.getKey();
|
String hostKey = entry.getKey();
|
||||||
List<DeviceConfig> configs = entry.getValue();
|
List<PollingTask> tasks = entry.getValue();
|
||||||
for (DeviceConfig config : configs) {
|
for (PollingTask task : tasks) {
|
||||||
try {
|
try {
|
||||||
scheduledStart(config);
|
scheduledStart(task.getSiteId(), task.getDeviceConfig());
|
||||||
// 每次读取后等待200ms,给Modbus网关足够的处理时间
|
// 每次读取后等待200ms,给Modbus网关足够的处理时间
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
@ -147,7 +108,8 @@ public class ModbusPoller {
|
|||||||
log.warn("Modbus轮询被中断");
|
log.warn("Modbus轮询被中断");
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("采集设备数据异常: {}", config.getDeviceName(), e);
|
log.error("采集设备数据异常: siteId={}, deviceId={}",
|
||||||
|
task.getSiteId(), task.getDeviceConfig().getDeviceNumber(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.info("采集设备数据{}轮询任务执行完成", hostKey);
|
log.info("采集设备数据{}轮询任务执行完成", hostKey);
|
||||||
@ -165,7 +127,139 @@ public class ModbusPoller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scheduledStart(DeviceConfig config) {
|
private List<PollingTask> buildPollingTasks() {
|
||||||
|
List<EmsPointConfig> pointConfigs = emsPointConfigMapper.selectModbusCollectPointConfigs(null);
|
||||||
|
if (CollectionUtils.isEmpty(pointConfigs)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EmsDevicesSetting> allDevices = emsDevicesSettingMapper.selectEmsDevicesSettingList(null);
|
||||||
|
Map<String, EmsDevicesSetting> deviceMap = allDevices.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(device -> StringUtils.isNoneBlank(device.getSiteId(), device.getDeviceId()))
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
this::buildSiteDeviceKey,
|
||||||
|
device -> device,
|
||||||
|
(left, right) -> left));
|
||||||
|
|
||||||
|
Map<String, List<EmsPointConfig>> pointsByDevice = pointConfigs.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(point -> StringUtils.isNoneBlank(point.getSiteId(), point.getDeviceId()))
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
point -> point.getSiteId() + "_" + point.getDeviceId(),
|
||||||
|
HashMap::new,
|
||||||
|
Collectors.toList()));
|
||||||
|
|
||||||
|
List<PollingTask> tasks = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, List<EmsPointConfig>> entry : pointsByDevice.entrySet()) {
|
||||||
|
String siteDeviceKey = entry.getKey();
|
||||||
|
EmsDevicesSetting device = deviceMap.get(siteDeviceKey);
|
||||||
|
if (device == null) {
|
||||||
|
log.warn("未找到设备连接配置,跳过采集: key={}", siteDeviceKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DeviceConfig deviceConfig = buildDeviceConfig(device, entry.getValue());
|
||||||
|
if (deviceConfig == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tasks.add(new PollingTask(device.getSiteId(), deviceConfig));
|
||||||
|
}
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeviceConfig buildDeviceConfig(EmsDevicesSetting device, List<EmsPointConfig> pointConfigs) {
|
||||||
|
if (device == null || CollectionUtils.isEmpty(pointConfigs)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(device.getIpAddress()) || device.getIpPort() == null || device.getSlaveId() == null) {
|
||||||
|
log.warn("设备连接参数不完整,跳过采集: siteId={}, deviceId={}", device.getSiteId(), device.getDeviceId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<TagConfig> tags = pointConfigs.stream()
|
||||||
|
.sorted(Comparator.comparing(point -> point.getModbusReadOrder() == null ? 0 : point.getModbusReadOrder()))
|
||||||
|
.map(this::toTagConfig)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isEmpty(tags)) {
|
||||||
|
log.warn("设备无有效Modbus点位配置,跳过采集: siteId={}, deviceId={}", device.getSiteId(), device.getDeviceId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceConfig deviceConfig = new DeviceConfig();
|
||||||
|
deviceConfig.setEnabled(true);
|
||||||
|
deviceConfig.setDeviceName(device.getDeviceName());
|
||||||
|
deviceConfig.setDeviceNumber(device.getDeviceId());
|
||||||
|
deviceConfig.setHost(device.getIpAddress());
|
||||||
|
deviceConfig.setPort(device.getIpPort().intValue());
|
||||||
|
deviceConfig.setSlaveId(device.getSlaveId().intValue());
|
||||||
|
deviceConfig.setTags(tags);
|
||||||
|
return deviceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TagConfig toTagConfig(EmsPointConfig pointConfig) {
|
||||||
|
if (pointConfig == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(pointConfig.getDataKey())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String address = normalizeAddress(pointConfig.getRegisterAddress(), pointConfig.getModbusRegisterType());
|
||||||
|
if (StringUtils.isBlank(address)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(pointConfig.getModbusDataType())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagConfig tag = new TagConfig();
|
||||||
|
tag.setKey(pointConfig.getDataKey().trim());
|
||||||
|
tag.setAddress(address);
|
||||||
|
tag.setDataType(pointConfig.getModbusDataType().trim());
|
||||||
|
tag.setA(pointConfig.getDataA() == null ? 0F : pointConfig.getDataA().floatValue());
|
||||||
|
tag.setK(pointConfig.getDataK() == null ? 1F : pointConfig.getDataK().floatValue());
|
||||||
|
tag.setB(pointConfig.getDataB() == null ? 0F : pointConfig.getDataB().floatValue());
|
||||||
|
tag.setBit(pointConfig.getDataBit());
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeAddress(String registerAddress, String registerType) {
|
||||||
|
if (StringUtils.isBlank(registerAddress)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String normalizedAddress = registerAddress.trim();
|
||||||
|
if (!normalizedAddress.chars().allMatch(Character::isDigit)) {
|
||||||
|
log.warn("寄存器地址必须为数字,当前值: {}", normalizedAddress);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (normalizedAddress.length() > 1) {
|
||||||
|
char first = normalizedAddress.charAt(0);
|
||||||
|
if (first >= '0' && first <= '4') {
|
||||||
|
return normalizedAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getRegisterPrefix(registerType) + normalizedAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRegisterPrefix(String registerType) {
|
||||||
|
String normalized = StringUtils.defaultString(registerType).trim().toUpperCase();
|
||||||
|
switch (normalized) {
|
||||||
|
case "COIL":
|
||||||
|
return "0";
|
||||||
|
case "DISCRETE_INPUT":
|
||||||
|
return "1";
|
||||||
|
case "INPUT_REGISTER":
|
||||||
|
return "3";
|
||||||
|
case "HOLDING_REGISTER":
|
||||||
|
default:
|
||||||
|
return "4";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildSiteDeviceKey(EmsDevicesSetting device) {
|
||||||
|
return device.getSiteId() + "_" + device.getDeviceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduledStart(String siteId, DeviceConfig config) {
|
||||||
if (config.isEnabled()) {
|
if (config.isEnabled()) {
|
||||||
log.info("Reading data from devices: {}", config.getDeviceName());
|
log.info("Reading data from devices: {}", config.getDeviceName());
|
||||||
|
|
||||||
@ -205,7 +299,7 @@ public class ModbusPoller {
|
|||||||
log.info("Data from {}: {}", config.getDeviceName(), data);
|
log.info("Data from {}: {}", config.getDeviceName(), data);
|
||||||
String deviceNumber = config.getDeviceNumber();
|
String deviceNumber = config.getDeviceNumber();
|
||||||
//处理数据并发送MQTT消息、保存Redis数据和数据入库
|
//处理数据并发送MQTT消息、保存Redis数据和数据入库
|
||||||
processingData(data, deviceNumber);
|
processingData(siteId, data, deviceNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,25 +348,27 @@ public class ModbusPoller {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processingData(Map<String, Object> data, String deviceNumber) {
|
private void processingData(String siteId, Map<String, Object> data, String deviceNumber) {
|
||||||
|
String siteDeviceKey = siteId + "_" + deviceNumber;
|
||||||
if (CollectionUtils.isEmpty(data)) {
|
if (CollectionUtils.isEmpty(data)) {
|
||||||
// 增加失败计数
|
// 增加失败计数
|
||||||
int failureCount = deviceFailureCounts.getOrDefault(deviceNumber, 0) + 1;
|
int failureCount = deviceFailureCounts.getOrDefault(siteDeviceKey, 0) + 1;
|
||||||
deviceFailureCounts.put(deviceNumber, failureCount);
|
deviceFailureCounts.put(siteDeviceKey, failureCount);
|
||||||
|
|
||||||
log.warn("设备 {} 数据读取失败,当前连续失败次数: {}", deviceNumber, failureCount);
|
log.warn("设备 {} 数据读取失败,当前连续失败次数: {}", siteDeviceKey, failureCount);
|
||||||
|
|
||||||
// 连续6次失败触发报警
|
// 连续6次失败触发报警
|
||||||
if (failureCount >= 6) {
|
if (failureCount >= SITE_DEVICE_OFFLINE_THRESHOLD) {
|
||||||
addDeviceOfflineRecord(siteId, deviceNumber);
|
addDeviceOfflineRecord(siteId, deviceNumber);
|
||||||
log.error("设备 {} 连续 {} 次未读取到数据,触发报警", deviceNumber, failureCount);
|
log.error("设备 {} 连续 {} 次未读取到数据,触发报警", siteDeviceKey, failureCount);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据读取成功,重置计数器
|
// 数据读取成功,重置计数器
|
||||||
deviceFailureCounts.remove(deviceNumber);
|
deviceFailureCounts.remove(siteDeviceKey);
|
||||||
updateDeviceStatus(siteId, deviceNumber, DeviceRunningStatus.ONLINE.getCode());
|
// 读取到数据后告警自恢复
|
||||||
|
deleteDeviceOfflineRecord(siteId, deviceNumber);
|
||||||
|
|
||||||
// 发送MQTT消息、保存Redis数据和数据入库
|
// 发送MQTT消息、保存Redis数据和数据入库
|
||||||
Long timestamp = System.currentTimeMillis();
|
Long timestamp = System.currentTimeMillis();
|
||||||
@ -280,9 +376,42 @@ public class ModbusPoller {
|
|||||||
json.put("Data", data);
|
json.put("Data", data);
|
||||||
json.put("timestamp", timestamp);
|
json.put("timestamp", timestamp);
|
||||||
json.put("Device", deviceNumber);
|
json.put("Device", deviceNumber);
|
||||||
|
if (shouldSendMqttOnChange(siteId, deviceNumber, data)) {
|
||||||
sendMqttMsg(json);
|
sendMqttMsg(json);
|
||||||
saveRedisData(json, deviceNumber);
|
} else {
|
||||||
saveDataToDatabase(data, deviceNumber, timestamp);
|
sendMqttHeartbeat(deviceNumber, timestamp);
|
||||||
|
log.info("设备 {} 数据无变化,已发送心跳MQTT", siteDeviceKey);
|
||||||
|
}
|
||||||
|
saveRedisData(siteId, json, deviceNumber);
|
||||||
|
saveDataToDatabase(siteId, data, deviceNumber, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逢变上送:仅当Data发生变化时才发送MQTT
|
||||||
|
*/
|
||||||
|
private boolean shouldSendMqttOnChange(String siteId, String deviceNumber, Map<String, Object> currentData) {
|
||||||
|
JSONObject lastPayload = redisCache.getCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber);
|
||||||
|
if (lastPayload == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object lastDataObj = lastPayload.get("Data");
|
||||||
|
if (lastDataObj == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject lastData = JSON.parseObject(JSON.toJSONString(lastDataObj));
|
||||||
|
JSONObject currentDataJson = JSON.parseObject(JSON.toJSONString(currentData));
|
||||||
|
return !Objects.equals(lastData, currentDataJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMqttHeartbeat(String deviceNumber, Long timestamp) {
|
||||||
|
JSONObject heartbeat = new JSONObject();
|
||||||
|
heartbeat.put("Device", deviceNumber);
|
||||||
|
heartbeat.put("timestamp", timestamp);
|
||||||
|
heartbeat.put("Heartbeat", 1);
|
||||||
|
heartbeat.put("Data", new JSONObject());
|
||||||
|
sendMqttMsg(heartbeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMqttMsg(JSONObject json) {
|
public void sendMqttMsg(JSONObject json) {
|
||||||
@ -295,7 +424,7 @@ public class ModbusPoller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveRedisData(JSONObject obj, String deviceNumber) {
|
public void saveRedisData(String siteId, JSONObject obj, String deviceNumber) {
|
||||||
try {
|
try {
|
||||||
// 存放mqtt原始每个设备最晚一次数据,便于后面点位获取数据
|
// 存放mqtt原始每个设备最晚一次数据,便于后面点位获取数据
|
||||||
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj);
|
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj);
|
||||||
@ -307,8 +436,12 @@ public class ModbusPoller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveDataToDatabase(Map<String, Object> data, String deviceNumber, Long timestamp) {
|
private void saveDataToDatabase(String siteId, Map<String, Object> data, String deviceNumber, Long timestamp) {
|
||||||
deviceDataProcessServiceImpl.processingDeviceData(siteId, deviceNumber, JSON.toJSONString(data), DateUtils.convertUpdateTime(timestamp));
|
JSONObject payload = new JSONObject();
|
||||||
|
payload.put("Device", deviceNumber);
|
||||||
|
payload.put("Data", JSON.toJSONString(data));
|
||||||
|
payload.put("timestamp", timestamp);
|
||||||
|
deviceDataProcessServiceImpl.handleDeviceData(Collections.singletonList(payload).toString(), siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//处理设备连接失败的情况,更新设备状态为离线,添加报警记录
|
//处理设备连接失败的情况,更新设备状态为离线,添加报警记录
|
||||||
@ -317,6 +450,12 @@ public class ModbusPoller {
|
|||||||
iEmsAlarmRecordsService.addDeviceOfflineRecord(siteId, deviceNumber);
|
iEmsAlarmRecordsService.addDeviceOfflineRecord(siteId, deviceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//处理设备读取到数据的情况,更新设备状态为在线,报警记录自恢复
|
||||||
|
private void deleteDeviceOfflineRecord(String siteId, String deviceNumber) {
|
||||||
|
updateDeviceStatus(siteId, deviceNumber, DeviceRunningStatus.ONLINE.getCode());
|
||||||
|
iEmsAlarmRecordsService.deleteDeviceOfflineRecord(siteId, deviceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
// 更新设备状态为在线或离线
|
// 更新设备状态为在线或离线
|
||||||
private void updateDeviceStatus(String siteId, String deviceNumber, String deviceStatus) {
|
private void updateDeviceStatus(String siteId, String deviceNumber, String deviceStatus) {
|
||||||
EmsDevicesSetting emsDevicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceNumber, siteId);
|
EmsDevicesSetting emsDevicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceNumber, siteId);
|
||||||
@ -326,11 +465,22 @@ public class ModbusPoller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getScheduledTaskInterval() {
|
private static class PollingTask {
|
||||||
SysJob query = new SysJob();
|
private final String siteId;
|
||||||
query.setInvokeTarget("modbusPoller.pollAllDevices");
|
private final DeviceConfig deviceConfig;
|
||||||
List<SysJob> sysJobs = iSysJobService.selectJobList(query);
|
|
||||||
return Math.toIntExact(CronUtils.getNextExecutionIntervalMillis(sysJobs.get(0).getCronExpression()));
|
private PollingTask(String siteId, DeviceConfig deviceConfig) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
this.deviceConfig = deviceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceConfig getDeviceConfig() {
|
||||||
|
return deviceConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,40 +10,16 @@ import com.xzzn.common.core.redis.RedisCache;
|
|||||||
import com.xzzn.common.enums.AlarmLevelStatus;
|
import com.xzzn.common.enums.AlarmLevelStatus;
|
||||||
import com.xzzn.common.enums.AlarmStatus;
|
import com.xzzn.common.enums.AlarmStatus;
|
||||||
import com.xzzn.common.enums.ProtPlanStatus;
|
import com.xzzn.common.enums.ProtPlanStatus;
|
||||||
import com.xzzn.common.enums.StrategyStatus;
|
|
||||||
import com.xzzn.common.utils.StringUtils;
|
import com.xzzn.common.utils.StringUtils;
|
||||||
import com.xzzn.ems.domain.EmsAlarmRecords;
|
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.EmsFaultProtectionPlan;
|
||||||
import com.xzzn.ems.domain.EmsStrategyRunning;
|
import com.xzzn.ems.domain.vo.ProtectionConstraintVo;
|
||||||
import com.xzzn.ems.domain.vo.ProtectionPlanVo;
|
import com.xzzn.ems.domain.vo.ProtectionPlanVo;
|
||||||
import com.xzzn.ems.domain.vo.ProtectionSettingVo;
|
import com.xzzn.ems.domain.vo.ProtectionSettingVo;
|
||||||
|
import com.xzzn.ems.domain.vo.ProtectionSettingsGroupVo;
|
||||||
import com.xzzn.ems.mapper.EmsAlarmRecordsMapper;
|
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.EmsFaultProtectionPlanMapper;
|
||||||
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
|
|
||||||
import com.xzzn.ems.service.IEmsFaultProtectionPlanService;
|
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.apache.commons.collections4.CollectionUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -51,14 +27,29 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警保护方案轮询
|
* 告警保护方案轮询
|
||||||
*
|
|
||||||
* @author xzzn
|
|
||||||
*/
|
*/
|
||||||
@Component("protectionPlanTask")
|
@Component("protectionPlanTask")
|
||||||
public class ProtectionPlanTask {
|
public class ProtectionPlanTask {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ProtectionPlanTask.class);
|
private static final Logger logger = LoggerFactory.getLogger(ProtectionPlanTask.class);
|
||||||
|
private static final BigDecimal DEFAULT_L1_POWER_RATIO = new BigDecimal("0.5");
|
||||||
|
private static final int CONSTRAINT_TTL_SECONDS = 120;
|
||||||
|
|
||||||
@Resource(name = "scheduledExecutorService")
|
@Resource(name = "scheduledExecutorService")
|
||||||
private ScheduledExecutorService scheduledExecutorService;
|
private ScheduledExecutorService scheduledExecutorService;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -66,18 +57,11 @@ public class ProtectionPlanTask {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EmsAlarmRecordsMapper emsAlarmRecordsMapper;
|
private EmsAlarmRecordsMapper emsAlarmRecordsMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmsStrategyRunningMapper emsStrategyRunningMapper;
|
|
||||||
@Autowired
|
|
||||||
private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;
|
private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
|
||||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
@Autowired
|
|
||||||
private EmsDevicesSettingMapper emsDevicesSettingMapper;
|
|
||||||
@Autowired
|
|
||||||
private ModbusProcessor modbusProcessor;
|
|
||||||
@Autowired
|
|
||||||
private EmsFaultIssueLogMapper emsFaultIssueLogMapper;
|
|
||||||
|
|
||||||
public ProtectionPlanTask(IEmsFaultProtectionPlanService iEmsFaultProtectionPlanService) {
|
public ProtectionPlanTask(IEmsFaultProtectionPlanService iEmsFaultProtectionPlanService) {
|
||||||
this.iEmsFaultProtectionPlanService = iEmsFaultProtectionPlanService;
|
this.iEmsFaultProtectionPlanService = iEmsFaultProtectionPlanService;
|
||||||
@ -86,303 +70,456 @@ public class ProtectionPlanTask {
|
|||||||
public void pollPlanList() {
|
public void pollPlanList() {
|
||||||
Long planId = 0L;
|
Long planId = 0L;
|
||||||
try {
|
try {
|
||||||
// 获取所有方案,轮询
|
|
||||||
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
|
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
|
||||||
|
|
||||||
for (EmsFaultProtectionPlan plan : planList) {
|
for (EmsFaultProtectionPlan plan : planList) {
|
||||||
planId = plan.getId();
|
planId = plan.getId();
|
||||||
String siteId = plan.getSiteId();
|
String siteId = plan.getSiteId();
|
||||||
if (StringUtils.isEmpty(siteId)) {
|
if (StringUtils.isEmpty(siteId)) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
// 保护前提
|
ProtectionSettingsGroupVo settingGroup = parseProtectionSettings(plan.getProtectionSettings());
|
||||||
String protectionSettings = plan.getProtectionSettings();
|
if (CollectionUtils.isEmpty(settingGroup.getFaultSettings())
|
||||||
final List<ProtectionSettingVo> protSettings = objectMapper.readValue(
|
&& CollectionUtils.isEmpty(settingGroup.getReleaseSettings())) {
|
||||||
protectionSettings,
|
continue;
|
||||||
new TypeReference<List<ProtectionSettingVo>>() {}
|
|
||||||
);
|
|
||||||
if (protSettings == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理告警保护方案
|
|
||||||
boolean isHighLevel = dealWithProtectionPlan(plan, protSettings);
|
|
||||||
if (isHighLevel) {
|
|
||||||
// 触发最高故障等级-结束循环
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
dealWithProtectionPlan(plan, settingGroup);
|
||||||
}
|
}
|
||||||
|
refreshProtectionConstraintCache(planList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("轮询失败,方案id为:{}", planId, e);
|
logger.error("轮询失败,方案id为:{}", planId, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理告警保护方案-返回触发下发方案时是否最高等级
|
|
||||||
// 需要同步云端
|
|
||||||
@SyncAfterInsert
|
@SyncAfterInsert
|
||||||
private boolean dealWithProtectionPlan(EmsFaultProtectionPlan plan, List<ProtectionSettingVo> protSettings) {
|
private void dealWithProtectionPlan(EmsFaultProtectionPlan plan, ProtectionSettingsGroupVo settingGroup) {
|
||||||
logger.info("<轮询保护方案> 站点:{},方案ID:{}", plan.getSiteId(), plan.getId());
|
logger.info("<轮询保护方案> 站点:{},方案ID:{}", plan.getSiteId(), plan.getId());
|
||||||
boolean isHighLevel = false;
|
|
||||||
|
|
||||||
String siteId = plan.getSiteId();
|
String siteId = plan.getSiteId();
|
||||||
final Integer isAlertAlarm = plan.getIsAlert();
|
Integer isAlertAlarm = plan.getIsAlert();
|
||||||
final Long status = plan.getStatus();
|
List<ProtectionSettingVo> faultSettings = settingGroup.getFaultSettings();
|
||||||
// 看方案是否启用,走不同判断
|
List<ProtectionSettingVo> releaseSettings = settingGroup.getReleaseSettings();
|
||||||
if (Objects.equals(status, ProtPlanStatus.STOP.getCode())) {
|
Long status = plan.getStatus();
|
||||||
logger.info("<方案未启用> 站点:{},方案ID:{}", siteId, plan.getId());
|
if (status == null) {
|
||||||
// 未启用,获取方案的故障值与最新数据判断是否需要下发方案
|
status = ProtPlanStatus.STOP.getCode();
|
||||||
if(checkIsNeedIssuedPlan(protSettings, siteId)){
|
|
||||||
if("3".equals(plan.getFaultLevel())){
|
|
||||||
isHighLevel = true;//最高故障等级
|
|
||||||
}
|
}
|
||||||
// 延时
|
|
||||||
final int faultDelay = plan.getFaultDelaySeconds().intValue();
|
if (Objects.equals(status, ProtPlanStatus.STOP.getCode())) {
|
||||||
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
|
if (checkIsNeedIssuedPlan(faultSettings, siteId)) {
|
||||||
// 延时后再次确认是否仍满足触发条件(防止期间状态变化)
|
int faultDelay = safeDelaySeconds(plan.getFaultDelaySeconds(), 0);
|
||||||
if (checkIsNeedIssuedPlan(protSettings, siteId)) {
|
scheduledExecutorService.schedule(() -> {
|
||||||
// 判断是否需要生成告警
|
if (!checkIsNeedIssuedPlan(faultSettings, siteId)) {
|
||||||
if (isAlertAlarm == 1) {
|
return;
|
||||||
logger.info("<生成告警> 方案ID:{},站点:{}", plan.getId(), siteId);
|
}
|
||||||
EmsAlarmRecords alarmRecords = addAlarmRecord(siteId,plan.getFaultName(),
|
if (Integer.valueOf(1).equals(isAlertAlarm)) {
|
||||||
getAlarmLevel(plan.getFaultLevel()));
|
EmsAlarmRecords alarmRecords = addAlarmRecord(siteId, plan.getFaultName(), getAlarmLevel(plan.getFaultLevel()));
|
||||||
emsAlarmRecordsMapper.insertEmsAlarmRecords(alarmRecords);
|
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());
|
plan.setStatus(ProtPlanStatus.RUNNING.getCode());
|
||||||
|
plan.setUpdateBy("system");
|
||||||
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
||||||
|
refreshSiteProtectionConstraint(siteId);
|
||||||
// 更新该站点策略为暂停状态
|
|
||||||
updateStrategyRunningStatus(siteId, StrategyStatus.SUSPENDED.getCode());
|
|
||||||
}
|
|
||||||
}, faultDelay, TimeUnit.SECONDS);
|
}, faultDelay, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
logger.info("<方案已启用> 站点:{},方案ID:{}", siteId, plan.getId());
|
}
|
||||||
// 已启用,则获取方案的释放值与最新数据判断是否需要取消方案
|
|
||||||
if(checkIsNeedCancelPlan(protSettings, siteId)){
|
if (checkIsNeedCancelPlan(releaseSettings, siteId)) {
|
||||||
// 延时,
|
int releaseDelay = safeDelaySeconds(plan.getReleaseDelaySeconds(), 0);
|
||||||
int releaseDelay = plan.getReleaseDelaySeconds().intValue();
|
scheduledExecutorService.schedule(() -> {
|
||||||
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
|
if (Integer.valueOf(1).equals(isAlertAlarm)) {
|
||||||
// 判断是否已存在未处理告警,有着取消
|
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.getFailedRecord(
|
||||||
if(isAlertAlarm == 1){
|
siteId,
|
||||||
logger.info("<取消告警>");
|
plan.getFaultName(),
|
||||||
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.getFailedRecord(siteId,
|
getAlarmLevel(plan.getFaultLevel())
|
||||||
plan.getFaultName(),getAlarmLevel(plan.getFaultLevel()));
|
);
|
||||||
if(emsAlarmRecords != null){
|
if (emsAlarmRecords != null) {
|
||||||
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
||||||
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 更新方案状态为“未启用”
|
|
||||||
logger.info("<方案变更为未启用> 方案ID:{}", plan.getId());
|
|
||||||
plan.setStatus(ProtPlanStatus.STOP.getCode());
|
plan.setStatus(ProtPlanStatus.STOP.getCode());
|
||||||
plan.setUpdateBy("system");
|
plan.setUpdateBy("system");
|
||||||
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
||||||
// 更新该站点策略为启用状态
|
refreshSiteProtectionConstraint(siteId);
|
||||||
updateStrategyRunningStatus(siteId, StrategyStatus.RUNNING.getCode());
|
|
||||||
}, releaseDelay, TimeUnit.SECONDS);
|
}, releaseDelay, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isHighLevel;
|
private int safeDelaySeconds(Long delay, int defaultSeconds) {
|
||||||
|
if (delay == null || delay < 0) {
|
||||||
|
return defaultSeconds;
|
||||||
|
}
|
||||||
|
return delay.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下发保护方案
|
private ProtectionSettingsGroupVo parseProtectionSettings(String settingsJson) {
|
||||||
private void executeProtectionActions(String protPlanJson, String siteId, Long planId, Integer faultLevel){
|
if (StringUtils.isEmpty(settingsJson)) {
|
||||||
final List<ProtectionPlanVo> protPlanList;
|
return ProtectionSettingsGroupVo.empty();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
protPlanList = objectMapper.readValue(
|
if (settingsJson.trim().startsWith("[")) {
|
||||||
protPlanJson,
|
List<ProtectionSettingVo> legacy = objectMapper.readValue(
|
||||||
|
settingsJson,
|
||||||
|
new TypeReference<List<ProtectionSettingVo>>() {}
|
||||||
|
);
|
||||||
|
ProtectionSettingsGroupVo groupVo = ProtectionSettingsGroupVo.empty();
|
||||||
|
groupVo.setFaultSettings(legacy);
|
||||||
|
groupVo.setReleaseSettings(legacy);
|
||||||
|
return groupVo;
|
||||||
|
}
|
||||||
|
ProtectionSettingsGroupVo groupVo = objectMapper.readValue(settingsJson, ProtectionSettingsGroupVo.class);
|
||||||
|
if (groupVo == null) {
|
||||||
|
return ProtectionSettingsGroupVo.empty();
|
||||||
|
}
|
||||||
|
if (groupVo.getFaultSettings() == null) {
|
||||||
|
groupVo.setFaultSettings(new ArrayList<>());
|
||||||
|
}
|
||||||
|
if (groupVo.getReleaseSettings() == null) {
|
||||||
|
groupVo.setReleaseSettings(new ArrayList<>());
|
||||||
|
}
|
||||||
|
return groupVo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("解析保护前提失败,json:{}", settingsJson, e);
|
||||||
|
return ProtectionSettingsGroupVo.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProtectionPlanVo> parseProtectionPlan(String planJson) {
|
||||||
|
if (StringUtils.isEmpty(planJson)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (planJson.trim().startsWith("[")) {
|
||||||
|
List<ProtectionPlanVo> plans = objectMapper.readValue(
|
||||||
|
planJson,
|
||||||
new TypeReference<List<ProtectionPlanVo>>() {}
|
new TypeReference<List<ProtectionPlanVo>>() {}
|
||||||
);
|
);
|
||||||
if (protPlanList == null) {
|
return plans == null ? new ArrayList<>() : plans;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
ProtectionPlanVo plan = objectMapper.readValue(planJson, ProtectionPlanVo.class);
|
||||||
// 遍历保护方案
|
List<ProtectionPlanVo> plans = new ArrayList<>();
|
||||||
for (ProtectionPlanVo plan : protPlanList) {
|
if (plan != null) {
|
||||||
if (StringUtils.isEmpty(plan.getDeviceId()) || StringUtils.isEmpty(plan.getPoint())) {
|
plans.add(plan);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// 给设备发送指令记录日志,并同步云端
|
return plans;
|
||||||
EmsFaultIssueLog faultIssueLog = createLogEntity(plan,siteId);
|
|
||||||
faultIssueLog.setLogLevel(faultLevel);
|
|
||||||
emsFaultIssueLogMapper.insertEmsFaultIssueLog(faultIssueLog);
|
|
||||||
|
|
||||||
// 通过modbus连接设备,发送数据
|
|
||||||
executeSinglePlan(plan,siteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("下发保护方案失败,方案id为:", planId, e);
|
logger.error("解析执行保护失败,json:{}", planJson, e);
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmsFaultIssueLog createLogEntity(ProtectionPlanVo plan,String siteId) {
|
private void refreshProtectionConstraintCache(List<EmsFaultProtectionPlan> allPlans) {
|
||||||
EmsFaultIssueLog faultIssueLog = new EmsFaultIssueLog();
|
Map<String, List<EmsFaultProtectionPlan>> planBySite = new HashMap<>();
|
||||||
faultIssueLog.setLogId(UUID.randomUUID().toString());
|
for (EmsFaultProtectionPlan plan : allPlans) {
|
||||||
faultIssueLog.setLogTime(new Date());
|
if (StringUtils.isEmpty(plan.getSiteId())) {
|
||||||
faultIssueLog.setSiteId(siteId);
|
continue;
|
||||||
faultIssueLog.setDeviceId(plan.getDeviceId());
|
}
|
||||||
faultIssueLog.setPoint(plan.getPoint());
|
planBySite.computeIfAbsent(plan.getSiteId(), k -> new ArrayList<>()).add(plan);
|
||||||
faultIssueLog.setValue(plan.getValue());
|
}
|
||||||
faultIssueLog.setCreateBy("sys");
|
for (Map.Entry<String, List<EmsFaultProtectionPlan>> entry : planBySite.entrySet()) {
|
||||||
faultIssueLog.setCreateTime(new Date());
|
writeSiteProtectionConstraint(entry.getKey(), entry.getValue());
|
||||||
return faultIssueLog;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeSinglePlan(ProtectionPlanVo plan, String siteId) throws Exception {
|
private void refreshSiteProtectionConstraint(String siteId) {
|
||||||
String deviceId = plan.getDeviceId();
|
if (StringUtils.isEmpty(siteId)) {
|
||||||
// 获取设备地址信息
|
return;
|
||||||
EmsDevicesSetting device = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
|
}
|
||||||
if (device == null || StringUtils.isEmpty(device.getIpAddress()) || device.getIpPort()==null) {
|
EmsFaultProtectionPlan query = new EmsFaultProtectionPlan();
|
||||||
logger.warn("设备信息不完整,deviceId:{}", deviceId);
|
query.setSiteId(siteId);
|
||||||
|
List<EmsFaultProtectionPlan> sitePlans = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(query);
|
||||||
|
writeSiteProtectionConstraint(siteId, sitePlans);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeSiteProtectionConstraint(String siteId, List<EmsFaultProtectionPlan> sitePlans) {
|
||||||
|
List<EmsFaultProtectionPlan> runningPlans = new ArrayList<>();
|
||||||
|
for (EmsFaultProtectionPlan plan : sitePlans) {
|
||||||
|
if (Objects.equals(plan.getStatus(), ProtPlanStatus.RUNNING.getCode())) {
|
||||||
|
runningPlans.add(plan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = RedisKeyConstants.PROTECTION_CONSTRAINT + siteId;
|
||||||
|
if (runningPlans.isEmpty()) {
|
||||||
|
redisCache.deleteObject(key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建设备配置
|
ProtectionConstraintVo merged = ProtectionConstraintVo.empty();
|
||||||
DeviceConfig config = new DeviceConfig();
|
for (EmsFaultProtectionPlan runningPlan : runningPlans) {
|
||||||
config.setHost(device.getIpAddress());
|
ProtectionConstraintVo single = buildConstraintFromPlan(runningPlan);
|
||||||
config.setPort(device.getIpPort().intValue());
|
mergeConstraint(merged, single);
|
||||||
config.setSlaveId(device.getSlaveId().intValue());
|
}
|
||||||
config.setDeviceName(device.getDeviceName());
|
merged.setUpdateAt(System.currentTimeMillis());
|
||||||
config.setDeviceNumber(device.getDeviceId());
|
redisCache.setCacheObject(key, merged, CONSTRAINT_TTL_SECONDS, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
// 构建写入标签配置
|
private ProtectionConstraintVo buildConstraintFromPlan(EmsFaultProtectionPlan plan) {
|
||||||
WriteTagConfig writeTag = new WriteTagConfig();
|
ProtectionConstraintVo vo = ProtectionConstraintVo.empty();
|
||||||
writeTag.setAddress(plan.getPoint());
|
int level = plan.getFaultLevel() == null ? 0 : plan.getFaultLevel();
|
||||||
writeTag.setValue(plan.getValue());
|
vo.setLevel(level);
|
||||||
|
vo.setSourcePlanIds(new ArrayList<>());
|
||||||
|
vo.getSourcePlanIds().add(plan.getId());
|
||||||
|
|
||||||
List<WriteTagConfig> writeTags = new ArrayList<>();
|
if (level == 1) {
|
||||||
writeTags.add(writeTag);
|
vo.setPowerLimitRatio(DEFAULT_L1_POWER_RATIO);
|
||||||
config.setWriteTags(writeTags);
|
} else if (level >= 3) {
|
||||||
|
vo.setForceStop(true);
|
||||||
|
vo.setForceStandby(true);
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
vo.setPowerLimitRatio(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
// 写入数据到设备
|
String description = StringUtils.isEmpty(plan.getDescription()) ? "" : plan.getDescription();
|
||||||
boolean success = modbusProcessor.writeDataToDeviceWithRetry(config);
|
BigDecimal ratioByDesc = parseDerateRatio(description);
|
||||||
|
if (ratioByDesc != null) {
|
||||||
|
vo.setPowerLimitRatio(minRatio(vo.getPowerLimitRatio(), ratioByDesc));
|
||||||
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (description.contains("禁止充放电")) {
|
||||||
logger.error("写入失败,设备地址:{}", device.getIpAddress());
|
vo.setAllowCharge(false);
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
} else {
|
||||||
|
if (description.contains("禁止充电")) {
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
}
|
||||||
|
if (description.contains("禁止放电")) {
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
}
|
||||||
|
if (description.contains("允许充电")) {
|
||||||
|
vo.setAllowCharge(true);
|
||||||
|
}
|
||||||
|
if (description.contains("允许放电")) {
|
||||||
|
vo.setAllowDischarge(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验释放值是否取消方案
|
if (description.contains("待机")) {
|
||||||
|
vo.setForceStandby(true);
|
||||||
|
}
|
||||||
|
if (description.contains("停机") || description.contains("切断") || level >= 3) {
|
||||||
|
vo.setForceStop(true);
|
||||||
|
vo.setForceStandby(true);
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
vo.setPowerLimitRatio(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行保护配置优先于描述文本配置
|
||||||
|
List<ProtectionPlanVo> protectionPlans = parseProtectionPlan(plan.getProtectionPlan());
|
||||||
|
applyCapabilityByProtectionPlan(vo, protectionPlans);
|
||||||
|
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCapabilityByProtectionPlan(ProtectionConstraintVo vo, List<ProtectionPlanVo> protectionPlans) {
|
||||||
|
if (CollectionUtils.isEmpty(protectionPlans)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ProtectionPlanVo item : protectionPlans) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String marker = ((item.getPointName() == null ? "" : item.getPointName()) + " "
|
||||||
|
+ (item.getPoint() == null ? "" : item.getPoint())).toLowerCase();
|
||||||
|
if (StringUtils.isEmpty(marker)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsAny(marker, "降功率", "derate", "power_limit", "powerlimit")) {
|
||||||
|
BigDecimal ratio = parseDerateRatioByPlan(item);
|
||||||
|
if (ratio != null) {
|
||||||
|
vo.setPowerLimitRatio(minRatio(vo.getPowerLimitRatio(), ratio));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCapabilityEnabled(item.getValue())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsAny(marker, "禁止充放电", "forbid_charge_discharge", "disable_charge_discharge")) {
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "禁止充电", "forbid_charge", "disable_charge")) {
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "禁止放电", "forbid_discharge", "disable_discharge")) {
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "允许充电", "allow_charge")) {
|
||||||
|
vo.setAllowCharge(true);
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "允许放电", "allow_discharge")) {
|
||||||
|
vo.setAllowDischarge(true);
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "待机", "standby")) {
|
||||||
|
vo.setForceStandby(true);
|
||||||
|
}
|
||||||
|
if (containsAny(marker, "关机", "停机", "切断", "shutdown", "stop")) {
|
||||||
|
vo.setForceStop(true);
|
||||||
|
vo.setForceStandby(true);
|
||||||
|
vo.setAllowCharge(false);
|
||||||
|
vo.setAllowDischarge(false);
|
||||||
|
vo.setPowerLimitRatio(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal parseDerateRatioByPlan(ProtectionPlanVo planVo) {
|
||||||
|
BigDecimal value = planVo.getValue();
|
||||||
|
if (value == null || value.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value.compareTo(BigDecimal.ONE) <= 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (value.compareTo(new BigDecimal("100")) <= 0) {
|
||||||
|
return value.divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCapabilityEnabled(BigDecimal value) {
|
||||||
|
return value == null || value.compareTo(BigDecimal.ZERO) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsAny(String text, String... markers) {
|
||||||
|
if (StringUtils.isEmpty(text) || markers == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String marker : markers) {
|
||||||
|
if (!StringUtils.isEmpty(marker) && text.contains(marker)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal parseDerateRatio(String text) {
|
||||||
|
if (StringUtils.isEmpty(text)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Matcher m = Pattern.compile("降功率\\s*(\\d+(?:\\.\\d+)?)%")
|
||||||
|
.matcher(text);
|
||||||
|
if (!m.find()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BigDecimal percent = new BigDecimal(m.group(1));
|
||||||
|
if (percent.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return percent.divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeConstraint(ProtectionConstraintVo merged, ProtectionConstraintVo incoming) {
|
||||||
|
if (incoming == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
merged.setLevel(Math.max(nullSafeInt(merged.getLevel()), nullSafeInt(incoming.getLevel())));
|
||||||
|
merged.setAllowCharge(boolAnd(merged.getAllowCharge(), incoming.getAllowCharge()));
|
||||||
|
merged.setAllowDischarge(boolAnd(merged.getAllowDischarge(), incoming.getAllowDischarge()));
|
||||||
|
merged.setForceStandby(boolOr(merged.getForceStandby(), incoming.getForceStandby()));
|
||||||
|
merged.setForceStop(boolOr(merged.getForceStop(), incoming.getForceStop()));
|
||||||
|
merged.setPowerLimitRatio(minRatio(merged.getPowerLimitRatio(), incoming.getPowerLimitRatio()));
|
||||||
|
|
||||||
|
if (incoming.getSourcePlanIds() != null && !incoming.getSourcePlanIds().isEmpty()) {
|
||||||
|
if (merged.getSourcePlanIds() == null) {
|
||||||
|
merged.setSourcePlanIds(new ArrayList<>());
|
||||||
|
}
|
||||||
|
merged.getSourcePlanIds().addAll(incoming.getSourcePlanIds());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal minRatio(BigDecimal a, BigDecimal b) {
|
||||||
|
BigDecimal left = a == null ? BigDecimal.ONE : a;
|
||||||
|
BigDecimal right = b == null ? BigDecimal.ONE : b;
|
||||||
|
return left.min(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nullSafeInt(Integer value) {
|
||||||
|
return value == null ? 0 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean boolAnd(Boolean a, Boolean b) {
|
||||||
|
boolean left = a == null || a;
|
||||||
|
boolean right = b == null || b;
|
||||||
|
return left && right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean boolOr(Boolean a, Boolean b) {
|
||||||
|
boolean left = a != null && a;
|
||||||
|
boolean right = b != null && b;
|
||||||
|
return left || right;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkIsNeedCancelPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
private boolean checkIsNeedCancelPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
||||||
BigDecimal releaseValue = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
StringBuilder conditionSb = new StringBuilder();
|
StringBuilder conditionSb = new StringBuilder();
|
||||||
for (int i = 0; i < protSettings.size(); i++) {
|
for (int i = 0; i < protSettings.size(); i++) {
|
||||||
ProtectionSettingVo vo = protSettings.get(i);
|
ProtectionSettingVo vo = protSettings.get(i);
|
||||||
String deviceId = vo.getDeviceId();
|
String deviceId = vo.getDeviceId();
|
||||||
String point = vo.getPoint();
|
String point = vo.getPoint();
|
||||||
releaseValue = vo.getFaultValue();
|
BigDecimal releaseValue = vo.getReleaseValue();
|
||||||
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || releaseValue == null
|
if (StringUtils.isEmpty(deviceId)
|
||||||
|| StringUtils.isEmpty(vo.getReleaseOperator())){
|
|| StringUtils.isEmpty(point)
|
||||||
|
|| releaseValue == null
|
||||||
|
|| StringUtils.isEmpty(vo.getReleaseOperator())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 获取点位最新值
|
|
||||||
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
||||||
logger.info("checkIsNeedCancelPlan 点位:{},最新值:{},比较方式:{},释放值:{}", point, lastPointValue, vo.getReleaseOperator(), releaseValue);
|
if (lastPointValue == null) {
|
||||||
if(lastPointValue == null){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
|
|
||||||
conditionSb.append(lastPointValue).append(vo.getReleaseOperator()).append(releaseValue);
|
conditionSb.append(lastPointValue).append(vo.getReleaseOperator()).append(releaseValue);
|
||||||
if (i < protSettings.size() - 1) {
|
if (i < protSettings.size() - 1) {
|
||||||
String relation = vo.getRelationNext();
|
conditionSb.append(" ").append(vo.getRelationNext()).append(" ");
|
||||||
conditionSb.append(" ").append(relation).append(" ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 执行比较语句
|
|
||||||
return executeWithParser(conditionSb.toString());
|
return executeWithParser(conditionSb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验故障值是否需要下发方案
|
|
||||||
private boolean checkIsNeedIssuedPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
private boolean checkIsNeedIssuedPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
||||||
BigDecimal faultValue = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
StringBuilder conditionSb = new StringBuilder();
|
StringBuilder conditionSb = new StringBuilder();
|
||||||
for (int i = 0; i < protSettings.size(); i++) {
|
for (int i = 0; i < protSettings.size(); i++) {
|
||||||
ProtectionSettingVo vo = protSettings.get(i);
|
ProtectionSettingVo vo = protSettings.get(i);
|
||||||
String deviceId = vo.getDeviceId();
|
String deviceId = vo.getDeviceId();
|
||||||
String point = vo.getPoint();
|
String point = vo.getPoint();
|
||||||
faultValue = vo.getFaultValue();
|
BigDecimal faultValue = vo.getFaultValue();
|
||||||
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || faultValue == null
|
if (StringUtils.isEmpty(deviceId)
|
||||||
|| StringUtils.isEmpty(vo.getFaultOperator())){
|
|| StringUtils.isEmpty(point)
|
||||||
|
|| faultValue == null
|
||||||
|
|| StringUtils.isEmpty(vo.getFaultOperator())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 获取点位最新值
|
|
||||||
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
||||||
logger.info("checkIsNeedIssuedPlan 点位:{},最新值:{},比较方式:{},故障值:{}", point, lastPointValue, vo.getFaultOperator(), faultValue);
|
if (lastPointValue == null) {
|
||||||
if(lastPointValue == null){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
|
|
||||||
conditionSb.append(lastPointValue).append(vo.getFaultOperator()).append(faultValue);
|
conditionSb.append(lastPointValue).append(vo.getFaultOperator()).append(faultValue);
|
||||||
if (i < protSettings.size() - 1) {
|
if (i < protSettings.size() - 1) {
|
||||||
String relation = vo.getRelationNext();
|
conditionSb.append(" ").append(vo.getRelationNext()).append(" ");
|
||||||
conditionSb.append(" ").append(relation).append(" ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 执行比较语句
|
|
||||||
return executeWithParser(conditionSb.toString());
|
return executeWithParser(conditionSb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal getPointLastValue(String deviceId, String point, String siteId) {
|
private BigDecimal getPointLastValue(String deviceId, String point, String siteId) {
|
||||||
JSONObject mqttJson = redisCache.getCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceId);
|
JSONObject mqttJson = redisCache.getCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceId);
|
||||||
if(mqttJson == null){
|
if (mqttJson == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String jsonData = mqttJson.get("Data").toString();
|
String jsonData = mqttJson.get("Data").toString();
|
||||||
if(StringUtils.isEmpty(jsonData)){
|
if (StringUtils.isEmpty(jsonData)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, Object> obj = JSON.parseObject(jsonData, new com.alibaba.fastjson2.TypeReference<Map<String, Object>>() {});
|
Map<String, Object> obj = JSON.parseObject(jsonData, new com.alibaba.fastjson2.TypeReference<Map<String, Object>>() {});
|
||||||
return StringUtils.getBigDecimal(obj.get(point));
|
return StringUtils.getBigDecimal(obj.get(point));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新站点策略为启用
|
private EmsAlarmRecords addAlarmRecord(String siteId, String content, String level) {
|
||||||
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 emsAlarmRecords = new EmsAlarmRecords();
|
||||||
emsAlarmRecords.setSiteId(siteId);
|
emsAlarmRecords.setSiteId(siteId);
|
||||||
emsAlarmRecords.setAlarmContent(content);
|
emsAlarmRecords.setAlarmContent(content);
|
||||||
@ -395,29 +532,31 @@ public class ProtectionPlanTask {
|
|||||||
return emsAlarmRecords;
|
return emsAlarmRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 故障等级-告警等级匹配
|
|
||||||
private String getAlarmLevel(Integer faultLevel) {
|
private String getAlarmLevel(Integer faultLevel) {
|
||||||
if (ObjectUtils.isEmpty(faultLevel) || faultLevel < 1 || faultLevel > 3) {
|
if (ObjectUtils.isEmpty(faultLevel) || faultLevel < 1 || faultLevel > 3) {
|
||||||
logger.warn("非法故障等级:{},默认返回普通告警", faultLevel);
|
logger.warn("非法故障等级:{},默认返回紧急告警", faultLevel);
|
||||||
return AlarmLevelStatus.EMERGENCY.getCode();
|
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||||
}
|
}
|
||||||
switch (faultLevel) {
|
switch (faultLevel) {
|
||||||
case 1: return AlarmLevelStatus.GENERAL.getCode();
|
case 1:
|
||||||
case 2: return AlarmLevelStatus.SERIOUS.getCode();
|
return AlarmLevelStatus.GENERAL.getCode();
|
||||||
case 3: return AlarmLevelStatus.EMERGENCY.getCode();
|
case 2:
|
||||||
|
return AlarmLevelStatus.SERIOUS.getCode();
|
||||||
|
case 3:
|
||||||
|
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||||
default:
|
default:
|
||||||
logger.error("未匹配的故障等级:{}", faultLevel);
|
|
||||||
return AlarmLevelStatus.EMERGENCY.getCode();
|
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义表达式解析器(仅支持简单运算符和逻辑关系)
|
/**
|
||||||
|
* 自定义表达式解析器(仅支持简单运算符和逻辑关系)
|
||||||
|
*/
|
||||||
public boolean executeWithParser(String conditionStr) {
|
public boolean executeWithParser(String conditionStr) {
|
||||||
if (conditionStr == null || conditionStr.isEmpty()) {
|
if (conditionStr == null || conditionStr.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 拆分逻辑关系(提取 && 或 ||)
|
|
||||||
List<String> logicRelations = new ArrayList<>();
|
List<String> logicRelations = new ArrayList<>();
|
||||||
Pattern logicPattern = Pattern.compile("(&&|\\|\\|)");
|
Pattern logicPattern = Pattern.compile("(&&|\\|\\|)");
|
||||||
Matcher logicMatcher = logicPattern.matcher(conditionStr);
|
Matcher logicMatcher = logicPattern.matcher(conditionStr);
|
||||||
@ -425,10 +564,7 @@ public class ProtectionPlanTask {
|
|||||||
logicRelations.add(logicMatcher.group());
|
logicRelations.add(logicMatcher.group());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 拆分原子条件(如 "3.55>3.52")
|
|
||||||
String[] atomicConditions = logicPattern.split(conditionStr);
|
String[] atomicConditions = logicPattern.split(conditionStr);
|
||||||
|
|
||||||
// 3. 解析每个原子条件并计算结果
|
|
||||||
List<Boolean> atomicResults = new ArrayList<>();
|
List<Boolean> atomicResults = new ArrayList<>();
|
||||||
Pattern conditionPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*([><]=?|==)\\s*(\\d+\\.?\\d*)");
|
Pattern conditionPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*([><]=?|==)\\s*(\\d+\\.?\\d*)");
|
||||||
for (String atomic : atomicConditions) {
|
for (String atomic : atomicConditions) {
|
||||||
@ -437,11 +573,10 @@ public class ProtectionPlanTask {
|
|||||||
logger.error("无效的原子条件:{}", atomic);
|
logger.error("无效的原子条件:{}", atomic);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
double left = Double.parseDouble(matcher.group(1)); // 左值(最新值)
|
double left = Double.parseDouble(matcher.group(1));
|
||||||
String operator = matcher.group(2); // 运算符
|
String operator = matcher.group(2);
|
||||||
double right = Double.parseDouble(matcher.group(3)); // 右值(故障值)
|
double right = Double.parseDouble(matcher.group(3));
|
||||||
|
|
||||||
// 执行比较
|
|
||||||
boolean result;
|
boolean result;
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case ">":
|
case ">":
|
||||||
@ -466,11 +601,10 @@ public class ProtectionPlanTask {
|
|||||||
atomicResults.add(result);
|
atomicResults.add(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 组合原子结果(根据逻辑关系)
|
|
||||||
boolean finalResult = atomicResults.get(0);
|
boolean finalResult = atomicResults.get(0);
|
||||||
for (int i = 0; i < logicRelations.size(); i++) {
|
for (int i = 0; i < logicRelations.size(); i++) {
|
||||||
String relation = logicRelations.get(i);
|
String relation = logicRelations.get(i);
|
||||||
boolean nextResult = atomicResults.get(i+1);
|
boolean nextResult = atomicResults.get(i + 1);
|
||||||
if ("&&".equals(relation)) {
|
if ("&&".equals(relation)) {
|
||||||
finalResult = finalResult && nextResult;
|
finalResult = finalResult && nextResult;
|
||||||
} else if ("||".equals(relation)) {
|
} else if ("||".equals(relation)) {
|
||||||
|
|||||||
@ -2,11 +2,16 @@ package com.xzzn.quartz.task;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.xzzn.common.constant.RedisKeyConstants;
|
||||||
import com.xzzn.common.core.modbus.ModbusProcessor;
|
import com.xzzn.common.core.modbus.ModbusProcessor;
|
||||||
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
||||||
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
|
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
|
||||||
|
import com.xzzn.common.core.redis.RedisCache;
|
||||||
|
import com.xzzn.common.enums.BusinessStatus;
|
||||||
|
import com.xzzn.common.enums.BusinessType;
|
||||||
import com.xzzn.common.enums.ChargeStatus;
|
import com.xzzn.common.enums.ChargeStatus;
|
||||||
import com.xzzn.common.enums.DeviceCategory;
|
import com.xzzn.common.enums.DeviceCategory;
|
||||||
|
import com.xzzn.common.enums.OperatorType;
|
||||||
import com.xzzn.common.enums.SiteDevice;
|
import com.xzzn.common.enums.SiteDevice;
|
||||||
import com.xzzn.common.enums.SocLimit;
|
import com.xzzn.common.enums.SocLimit;
|
||||||
import com.xzzn.common.enums.WorkStatus;
|
import com.xzzn.common.enums.WorkStatus;
|
||||||
@ -16,26 +21,33 @@ import com.xzzn.ems.domain.EmsAmmeterData;
|
|||||||
import com.xzzn.ems.domain.EmsBatteryStack;
|
import com.xzzn.ems.domain.EmsBatteryStack;
|
||||||
import com.xzzn.ems.domain.EmsDevicesSetting;
|
import com.xzzn.ems.domain.EmsDevicesSetting;
|
||||||
import com.xzzn.ems.domain.EmsPcsSetting;
|
import com.xzzn.ems.domain.EmsPcsSetting;
|
||||||
|
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||||
import com.xzzn.ems.domain.EmsStrategyLog;
|
import com.xzzn.ems.domain.EmsStrategyLog;
|
||||||
import com.xzzn.ems.domain.EmsStrategyTemp;
|
import com.xzzn.ems.domain.EmsStrategyTemp;
|
||||||
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
|
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
|
||||||
|
import com.xzzn.ems.domain.vo.ProtectionConstraintVo;
|
||||||
import com.xzzn.ems.domain.vo.StrategyRunningVo;
|
import com.xzzn.ems.domain.vo.StrategyRunningVo;
|
||||||
import com.xzzn.ems.mapper.EmsAmmeterDataMapper;
|
import com.xzzn.ems.mapper.EmsAmmeterDataMapper;
|
||||||
import com.xzzn.ems.mapper.EmsBatteryStackMapper;
|
import com.xzzn.ems.mapper.EmsBatteryStackMapper;
|
||||||
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
||||||
import com.xzzn.ems.mapper.EmsPcsSettingMapper;
|
import com.xzzn.ems.mapper.EmsPcsSettingMapper;
|
||||||
import com.xzzn.ems.mapper.EmsStrategyLogMapper;
|
import com.xzzn.ems.mapper.EmsStrategyLogMapper;
|
||||||
|
import com.xzzn.ems.mapper.EmsStrategyRuntimeConfigMapper;
|
||||||
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
|
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
|
||||||
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
|
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
|
||||||
import com.xzzn.ems.mapper.EmsStrategyTimeConfigMapper;
|
import com.xzzn.ems.mapper.EmsStrategyTimeConfigMapper;
|
||||||
|
import com.xzzn.system.domain.SysOperLog;
|
||||||
|
import com.xzzn.system.service.ISysOperLogService;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -57,16 +69,34 @@ public class StrategyPoller {
|
|||||||
private static final ConcurrentHashMap<Long, Boolean> strategyLocks = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Long, Boolean> strategyLocks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// SOC 上下限值,默认为0%-100%
|
// SOC 上下限值,默认为0%-100%
|
||||||
private static final BigDecimal SOC_DOWN = new BigDecimal(0);
|
private static final BigDecimal DEFAULT_SOC_DOWN = BigDecimal.ZERO;
|
||||||
private static final BigDecimal SOC_UP = new BigDecimal(100);
|
private static final BigDecimal DEFAULT_SOC_UP = new BigDecimal(100);
|
||||||
// 逆变器功率下限值,默认为30kW
|
// 逆变器功率下限值,默认为30kW
|
||||||
private static final BigDecimal ANTI_REVERSE_THRESHOLD = new BigDecimal(30);
|
private static final BigDecimal DEFAULT_ANTI_REVERSE_THRESHOLD = new BigDecimal(30);
|
||||||
// 逆变器下限值范围,默认为20%
|
// 逆变器下限值范围,默认为20%
|
||||||
private static final BigDecimal ANTI_REVERSE_RANGE_PERCENT = new BigDecimal(20);
|
private static final BigDecimal DEFAULT_ANTI_REVERSE_RANGE_PERCENT = new BigDecimal(20);
|
||||||
// 逆变器功率上限值,默认为100kW
|
// 逆变器功率上限值,默认为100kW
|
||||||
private static final BigDecimal ANTI_REVERSE_UP = new BigDecimal(100);
|
private static final BigDecimal DEFAULT_ANTI_REVERSE_UP = new BigDecimal(100);
|
||||||
// PCS功率降幅,默认为10%
|
// PCS功率降幅,默认为10%
|
||||||
private static final BigDecimal ANTI_REVERSE_POWER_DOWN_PERCENT = new BigDecimal(10);
|
private static final BigDecimal DEFAULT_ANTI_REVERSE_POWER_DOWN_PERCENT = new BigDecimal(10);
|
||||||
|
// 电网有功功率低于20kW时,强制待机
|
||||||
|
private static final BigDecimal DEFAULT_ANTI_REVERSE_HARD_STOP_THRESHOLD = new BigDecimal(20);
|
||||||
|
// 设定功率倍率,默认10
|
||||||
|
private static final BigDecimal DEFAULT_POWER_SET_MULTIPLIER = new BigDecimal(10);
|
||||||
|
// 保护介入默认开启
|
||||||
|
private static final Integer DEFAULT_PROTECT_INTERVENE_ENABLE = 1;
|
||||||
|
// 一级保护默认降额50%
|
||||||
|
private static final BigDecimal DEFAULT_PROTECT_L1_DERATE_PERCENT = new BigDecimal("50");
|
||||||
|
// 保护约束失效保护时长(秒)
|
||||||
|
private static final Integer DEFAULT_PROTECT_RECOVERY_STABLE_SECONDS = 5;
|
||||||
|
// 三级保护默认锁存开启
|
||||||
|
private static final Integer DEFAULT_PROTECT_L3_LATCH_ENABLE = 1;
|
||||||
|
// 保护冲突策略默认值
|
||||||
|
private static final String DEFAULT_PROTECT_CONFLICT_POLICY = "MAX_LEVEL_WIN";
|
||||||
|
// 保护约束默认功率比例
|
||||||
|
private static final BigDecimal DEFAULT_PROTECTION_RATIO = BigDecimal.ONE;
|
||||||
|
// 除法精度,避免BigDecimal除不尽异常
|
||||||
|
private static final int POWER_SCALE = 4;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmsStrategyRunningMapper emsStrategyRunningMapper;
|
private EmsStrategyRunningMapper emsStrategyRunningMapper;
|
||||||
@ -85,7 +115,13 @@ public class StrategyPoller {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EmsStrategyLogMapper emsStrategyLogMapper;
|
private EmsStrategyLogMapper emsStrategyLogMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private EmsStrategyRuntimeConfigMapper runtimeConfigMapper;
|
||||||
|
@Autowired
|
||||||
|
private RedisCache redisCache;
|
||||||
|
@Autowired
|
||||||
private ModbusProcessor modbusProcessor;
|
private ModbusProcessor modbusProcessor;
|
||||||
|
@Autowired
|
||||||
|
private ISysOperLogService operLogService;
|
||||||
|
|
||||||
@Resource(name = "modbusExecutor")
|
@Resource(name = "modbusExecutor")
|
||||||
private ExecutorService modbusExecutor;
|
private ExecutorService modbusExecutor;
|
||||||
@ -132,6 +168,7 @@ public class StrategyPoller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void dealStrategyCurveData(Long strategyId, String siteId) {
|
private void dealStrategyCurveData(Long strategyId, String siteId) {
|
||||||
|
EmsStrategyRuntimeConfig runtimeConfig = getRuntimeConfig(siteId);
|
||||||
// 1.获取当前策略的所有模板
|
// 1.获取当前策略的所有模板
|
||||||
List<Map<String, String>> temps = emsStrategyTempMapper.getTempNameList(strategyId, siteId);
|
List<Map<String, String>> temps = emsStrategyTempMapper.getTempNameList(strategyId, siteId);
|
||||||
if (CollectionUtils.isEmpty(temps)) {
|
if (CollectionUtils.isEmpty(temps)) {
|
||||||
@ -174,24 +211,53 @@ public class StrategyPoller {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 判断SOC上下限
|
// 判断SOC上下限
|
||||||
if (isSocInRange(emsStrategyTemp)) {
|
if (isSocInRange(emsStrategyTemp, runtimeConfig)) {
|
||||||
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower().divide(new BigDecimal(pcsDeviceList.size()));
|
ProtectionConstraintVo protectionConstraint = getProtectionConstraint(siteId);
|
||||||
|
Map<Long, EmsPcsSetting> pcsSettingCache = new HashMap<>();
|
||||||
|
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower()
|
||||||
|
.divide(new BigDecimal(pcsDeviceList.size()), POWER_SCALE, RoundingMode.HALF_UP);
|
||||||
|
BigDecimal totalActivePower = null;
|
||||||
|
if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
||||||
|
// 同一站点同一轮执行只读取一次电网电表,降低重复查库和数据抖动
|
||||||
|
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
|
||||||
|
if (emsAmmeterData != null) {
|
||||||
|
totalActivePower = emsAmmeterData.getTotalActivePower();
|
||||||
|
}
|
||||||
|
}
|
||||||
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
|
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
|
||||||
EmsPcsSetting pcsSetting = emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(pcsDevice.getId());
|
EmsPcsSetting pcsSetting = pcsSettingCache.computeIfAbsent(
|
||||||
|
pcsDevice.getId(),
|
||||||
|
id -> emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(id)
|
||||||
|
);
|
||||||
if (pcsSetting == null || pcsSetting.getClusterNum() < 1) {
|
if (pcsSetting == null || pcsSetting.getClusterNum() < 1) {
|
||||||
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
|
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 功率默认放大10倍,平均功率值,根据电池簇数量进行平均分配
|
// 平均功率值根据倍率放大后,再按电池簇数量平均分配
|
||||||
avgChargeDischargePower = avgChargeDischargePower.multiply(new BigDecimal(10)).divide(new BigDecimal(pcsSetting.getClusterNum()));
|
BigDecimal strategyPower = avgChargeDischargePower.multiply(runtimeConfig.getPowerSetMultiplier())
|
||||||
|
.divide(new BigDecimal(pcsSetting.getClusterNum()), POWER_SCALE, RoundingMode.HALF_UP);
|
||||||
// 根据充电状态,处理数据
|
// 根据充电状态,处理数据
|
||||||
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
||||||
|
StrategyCommandDecision decision = applyProtectionConstraint(
|
||||||
|
strategyPower,
|
||||||
|
ChargeStatus.CHARGING,
|
||||||
|
runtimeConfig,
|
||||||
|
protectionConstraint
|
||||||
|
);
|
||||||
// 发送Modbus命令控制设备-充电
|
// 发送Modbus命令控制设备-充电
|
||||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.CHARGING, avgChargeDischargePower, emsStrategyTemp, false, null);
|
sendModbusCommand(
|
||||||
|
Collections.singletonList(pcsDevice),
|
||||||
|
pcsSetting,
|
||||||
|
decision.getChargeStatus(),
|
||||||
|
decision.getPower(),
|
||||||
|
emsStrategyTemp,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
} else if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
} else if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
||||||
boolean needAntiReverseFlow = false;
|
boolean needAntiReverseFlow = false;
|
||||||
Integer powerDownType = null;
|
Integer powerDownType = null;
|
||||||
BigDecimal chargeDischargePower = avgChargeDischargePower;
|
BigDecimal chargeDischargePower = strategyPower;
|
||||||
// 查询策略运行日志
|
// 查询策略运行日志
|
||||||
EmsStrategyLog lastStrategyLog = getLastStrategyLog(pcsDevice.getDeviceId(), emsStrategyTemp);
|
EmsStrategyLog lastStrategyLog = getLastStrategyLog(pcsDevice.getDeviceId(), emsStrategyTemp);
|
||||||
if (lastStrategyLog != null) {
|
if (lastStrategyLog != null) {
|
||||||
@ -204,39 +270,69 @@ public class StrategyPoller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询电网电表的正向有功功率,36kW-50kW范围内,稳定运行,低于36kW,降功率,高于50kW,增加功率
|
// 查询电网电表的正向有功功率,36kW-50kW范围内,稳定运行,低于36kW,降功率,高于50kW,增加功率
|
||||||
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
|
if (totalActivePower == null) {
|
||||||
if (emsAmmeterData == null || emsAmmeterData.getTotalActivePower() == null) {
|
logger.warn("当前站点: {}, 未获取到最新电表数据,执行保守策略并切换待机", emsStrategyTemp.getSiteId());
|
||||||
logger.info("当前站点: {}, 未获取到最新电表数据", emsStrategyTemp.getSiteId());
|
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, true, 0);
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
// 电网功率过低,直接待机,不再放电
|
||||||
|
if (totalActivePower.compareTo(runtimeConfig.getAntiReverseHardStopThreshold()) < 0) {
|
||||||
|
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, true, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 放电开始先按差值限幅:差值=电网功率-防逆流阈值
|
||||||
|
BigDecimal diffPower = totalActivePower.subtract(runtimeConfig.getAntiReverseThreshold());
|
||||||
|
BigDecimal targetPower = diffPower.compareTo(BigDecimal.ZERO) > 0 ? diffPower : BigDecimal.ZERO;
|
||||||
|
if (targetPower.compareTo(strategyPower) > 0) {
|
||||||
|
targetPower = strategyPower;
|
||||||
|
}
|
||||||
|
if (chargeDischargePower.compareTo(targetPower) > 0) {
|
||||||
|
chargeDischargePower = targetPower;
|
||||||
|
}
|
||||||
// 判断是否需要防逆流
|
// 判断是否需要防逆流
|
||||||
needAntiReverseFlow = isNeedAntiReverseFlow(emsAmmeterData.getTotalActivePower());
|
needAntiReverseFlow = isNeedAntiReverseFlow(totalActivePower, runtimeConfig);
|
||||||
BigDecimal power = avgChargeDischargePower.multiply(ANTI_REVERSE_POWER_DOWN_PERCENT).divide(new BigDecimal(100));
|
BigDecimal power = strategyPower.multiply(runtimeConfig.getAntiReversePowerDownPercent())
|
||||||
|
.divide(new BigDecimal(100), POWER_SCALE, RoundingMode.HALF_UP);
|
||||||
if (needAntiReverseFlow) {
|
if (needAntiReverseFlow) {
|
||||||
// 降功率
|
// 降功率
|
||||||
chargeDischargePower = chargeDischargePower.subtract(power);
|
chargeDischargePower = chargeDischargePower.subtract(power);
|
||||||
powerDownType = 0;
|
powerDownType = 0;
|
||||||
} else {
|
} else {
|
||||||
// 判断是否需要增加功率,
|
// 判断是否需要增加功率,
|
||||||
if (powerDownType != null && emsAmmeterData.getTotalActivePower().compareTo(ANTI_REVERSE_UP) > 0) {
|
if (powerDownType != null && totalActivePower.compareTo(runtimeConfig.getAntiReverseUp()) > 0) {
|
||||||
if (chargeDischargePower.compareTo(avgChargeDischargePower) == 0) {
|
if (chargeDischargePower.compareTo(targetPower) >= 0) {
|
||||||
// 功率增加到平均值则停止
|
// 功率增加到限幅值则停止
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 增加功率
|
// 增加功率
|
||||||
chargeDischargePower = chargeDischargePower.add(power);
|
chargeDischargePower = chargeDischargePower.add(power);
|
||||||
|
if (chargeDischargePower.compareTo(targetPower) > 0) {
|
||||||
|
chargeDischargePower = targetPower;
|
||||||
|
}
|
||||||
powerDownType = 1;
|
powerDownType = 1;
|
||||||
needAntiReverseFlow = true;
|
needAntiReverseFlow = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BigDecimal.ZERO.compareTo(chargeDischargePower) == 0) {
|
if (chargeDischargePower.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
chargeDischargePower = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
StrategyCommandDecision decision = applyProtectionConstraint(
|
||||||
|
chargeDischargePower,
|
||||||
|
ChargeStatus.DISCHARGING,
|
||||||
|
runtimeConfig,
|
||||||
|
protectionConstraint
|
||||||
|
);
|
||||||
|
ChargeStatus finalStatus = decision.getChargeStatus();
|
||||||
|
BigDecimal finalPower = decision.getPower();
|
||||||
|
if (ChargeStatus.STANDBY.equals(finalStatus) || BigDecimal.ZERO.compareTo(finalPower) == 0) {
|
||||||
// 如果已经降功率到0,则设备直接待机
|
// 如果已经降功率到0,则设备直接待机
|
||||||
// 发送Modbus命令控制设备-待机
|
// 发送Modbus命令控制设备-待机
|
||||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||||
} else {
|
} else {
|
||||||
// 发送Modbus命令控制设备-放电
|
// 发送Modbus命令控制设备-放电
|
||||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.DISCHARGING, chargeDischargePower, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, finalStatus, finalPower, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 发送Modbus命令控制设备-待机
|
// 发送Modbus命令控制设备-待机
|
||||||
@ -297,11 +393,11 @@ public class StrategyPoller {
|
|||||||
return emsStrategyLogMapper.getLastStrategyLog(query);
|
return emsStrategyLogMapper.getLastStrategyLog(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNeedAntiReverseFlow(BigDecimal totalActivePower) {
|
private boolean isNeedAntiReverseFlow(BigDecimal totalActivePower, EmsStrategyRuntimeConfig runtimeConfig) {
|
||||||
// 获取当前设定的防逆流阈值(30kW)
|
// 获取当前设定的防逆流阈值(30kW)
|
||||||
BigDecimal threshold = ANTI_REVERSE_THRESHOLD;
|
BigDecimal threshold = runtimeConfig.getAntiReverseThreshold();
|
||||||
// 计算20%范围的上限(36kW)
|
// 计算20%范围的上限(36kW)
|
||||||
BigDecimal upperLimit = threshold.multiply(ANTI_REVERSE_RANGE_PERCENT).divide(new BigDecimal(100)).add(threshold);
|
BigDecimal upperLimit = threshold.multiply(runtimeConfig.getAntiReverseRangePercent()).divide(new BigDecimal(100)).add(threshold);
|
||||||
|
|
||||||
// 判断电网电表正向有功功率是否小于36kW(接近30kW的20%范围)
|
// 判断电网电表正向有功功率是否小于36kW(接近30kW的20%范围)
|
||||||
return totalActivePower.compareTo(upperLimit) < 0;
|
return totalActivePower.compareTo(upperLimit) < 0;
|
||||||
@ -409,10 +505,11 @@ public class StrategyPoller {
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// 充、放电,则先开机设备
|
// 充、放电,则先开机设备
|
||||||
switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL);
|
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting, chargeDischargePower, 0);
|
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting, chargeDischargePower, 0);
|
||||||
if (deviceConfig == null) {
|
if (deviceConfig == null) {
|
||||||
@ -421,8 +518,10 @@ public class StrategyPoller {
|
|||||||
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
||||||
|
recordDeviceOperationLog(siteId, deviceId, "写功率", chargeDischargePower, false, chargeStatus.getInfo() + "功率下发失败");
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
recordDeviceOperationLog(siteId, deviceId, "写功率", chargeDischargePower, true, null);
|
||||||
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
||||||
// 待机,先写功率值,再关机
|
// 待机,先写功率值,再关机
|
||||||
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP)) {
|
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP)) {
|
||||||
@ -440,18 +539,147 @@ public class StrategyPoller {
|
|||||||
private boolean switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
|
private boolean switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
|
||||||
String siteId = pcsDevice.getSiteId();
|
String siteId = pcsDevice.getSiteId();
|
||||||
String deviceId = pcsDevice.getDeviceId();
|
String deviceId = pcsDevice.getDeviceId();
|
||||||
|
String originalWorkStatus = pcsDevice.getWorkStatus();
|
||||||
pcsDevice.setWorkStatus(workStatus.getCode());
|
pcsDevice.setWorkStatus(workStatus.getCode());
|
||||||
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
|
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
|
||||||
if (deviceConfig == null) {
|
if (deviceConfig == null) {
|
||||||
|
pcsDevice.setWorkStatus(originalWorkStatus);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceConfig, workStatus.getInfo());
|
pcsDevice.setWorkStatus(originalWorkStatus);
|
||||||
|
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, workStatus.getInfo());
|
||||||
|
recordDeviceOperationLog(siteId, deviceId, "开关机", workStatus.getInfo(), false, workStatus.getInfo() + "指令发送失败");
|
||||||
|
} else {
|
||||||
|
recordDeviceOperationLog(siteId, deviceId, "开关机", workStatus.getInfo(), true, null);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recordDeviceOperationLog(String siteId, String deviceId, String action, Object param, boolean success, String errorMsg) {
|
||||||
|
try {
|
||||||
|
SysOperLog operLog = new SysOperLog();
|
||||||
|
operLog.setTitle("策略设备控制-" + action);
|
||||||
|
operLog.setBusinessType(BusinessType.UPDATE.ordinal());
|
||||||
|
operLog.setMethod(this.getClass().getName() + "." + action);
|
||||||
|
operLog.setRequestMethod("SCHEDULE");
|
||||||
|
operLog.setOperatorType(OperatorType.OTHER.ordinal());
|
||||||
|
operLog.setOperName("system");
|
||||||
|
operLog.setOperIp("127.0.0.1");
|
||||||
|
operLog.setOperUrl("/quartz/strategyPoller");
|
||||||
|
operLog.setOperTime(DateUtils.getNowDate());
|
||||||
|
Map<String, Object> operParam = new HashMap<>();
|
||||||
|
operParam.put("siteId", siteId);
|
||||||
|
operParam.put("deviceId", deviceId);
|
||||||
|
operParam.put("action", action);
|
||||||
|
operParam.put("param", param);
|
||||||
|
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(operParam), 0, 2000));
|
||||||
|
operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(Collections.singletonMap("success", success)), 0, 2000));
|
||||||
|
operLog.setStatus(success ? BusinessStatus.SUCCESS.ordinal() : BusinessStatus.FAIL.ordinal());
|
||||||
|
if (!success) {
|
||||||
|
operLog.setErrorMsg(StringUtils.substring(errorMsg, 0, 2000));
|
||||||
|
}
|
||||||
|
operLogService.insertOperlog(operLog);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("记录sys_oper_log失败, siteId={}, deviceId={}, action={}", siteId, deviceId, action, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtectionConstraintVo getProtectionConstraint(String siteId) {
|
||||||
|
ProtectionConstraintVo constraint = redisCache.getCacheObject(RedisKeyConstants.PROTECTION_CONSTRAINT + siteId);
|
||||||
|
if (constraint == null) {
|
||||||
|
return ProtectionConstraintVo.empty();
|
||||||
|
}
|
||||||
|
if (constraint.getPowerLimitRatio() == null) {
|
||||||
|
constraint.setPowerLimitRatio(DEFAULT_PROTECTION_RATIO);
|
||||||
|
}
|
||||||
|
if (constraint.getAllowCharge() == null) {
|
||||||
|
constraint.setAllowCharge(true);
|
||||||
|
}
|
||||||
|
if (constraint.getAllowDischarge() == null) {
|
||||||
|
constraint.setAllowDischarge(true);
|
||||||
|
}
|
||||||
|
if (constraint.getForceStandby() == null) {
|
||||||
|
constraint.setForceStandby(false);
|
||||||
|
}
|
||||||
|
if (constraint.getForceStop() == null) {
|
||||||
|
constraint.setForceStop(false);
|
||||||
|
}
|
||||||
|
if (constraint.getLevel() == null) {
|
||||||
|
constraint.setLevel(0);
|
||||||
|
}
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StrategyCommandDecision applyProtectionConstraint(BigDecimal targetPower,
|
||||||
|
ChargeStatus targetStatus,
|
||||||
|
EmsStrategyRuntimeConfig runtimeConfig,
|
||||||
|
ProtectionConstraintVo constraint) {
|
||||||
|
if (constraint == null || nullSafeInt(constraint.getLevel()) <= 0) {
|
||||||
|
return new StrategyCommandDecision(targetStatus, safePower(targetPower));
|
||||||
|
}
|
||||||
|
if (Boolean.TRUE.equals(constraint.getForceStop()) || Boolean.TRUE.equals(constraint.getForceStandby())) {
|
||||||
|
return new StrategyCommandDecision(ChargeStatus.STANDBY, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
if (ChargeStatus.CHARGING.equals(targetStatus) && Boolean.FALSE.equals(constraint.getAllowCharge())) {
|
||||||
|
return new StrategyCommandDecision(ChargeStatus.STANDBY, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
if (ChargeStatus.DISCHARGING.equals(targetStatus) && Boolean.FALSE.equals(constraint.getAllowDischarge())) {
|
||||||
|
return new StrategyCommandDecision(ChargeStatus.STANDBY, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
BigDecimal ratio = getPowerLimitRatio(constraint, runtimeConfig);
|
||||||
|
BigDecimal finalPower = safePower(targetPower).multiply(ratio).setScale(POWER_SCALE, RoundingMode.HALF_UP);
|
||||||
|
if (finalPower.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return new StrategyCommandDecision(ChargeStatus.STANDBY, BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
return new StrategyCommandDecision(targetStatus, finalPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getPowerLimitRatio(ProtectionConstraintVo constraint, EmsStrategyRuntimeConfig runtimeConfig) {
|
||||||
|
BigDecimal ratio = constraint.getPowerLimitRatio();
|
||||||
|
if (ratio == null || ratio.compareTo(BigDecimal.ZERO) < 0 || ratio.compareTo(BigDecimal.ONE) > 0) {
|
||||||
|
ratio = DEFAULT_PROTECTION_RATIO;
|
||||||
|
}
|
||||||
|
if (nullSafeInt(constraint.getLevel()) == 1 && DEFAULT_PROTECTION_RATIO.compareTo(ratio) == 0) {
|
||||||
|
BigDecimal deratePercent = runtimeConfig.getProtectL1DeratePercent();
|
||||||
|
if (deratePercent == null || deratePercent.compareTo(BigDecimal.ZERO) < 0 || deratePercent.compareTo(new BigDecimal("100")) > 0) {
|
||||||
|
deratePercent = DEFAULT_PROTECT_L1_DERATE_PERCENT;
|
||||||
|
}
|
||||||
|
ratio = deratePercent.divide(new BigDecimal("100"), POWER_SCALE, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
return ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal safePower(BigDecimal power) {
|
||||||
|
if (power == null || power.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nullSafeInt(Integer value) {
|
||||||
|
return value == null ? 0 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StrategyCommandDecision {
|
||||||
|
private final ChargeStatus chargeStatus;
|
||||||
|
private final BigDecimal power;
|
||||||
|
|
||||||
|
private StrategyCommandDecision(ChargeStatus chargeStatus, BigDecimal power) {
|
||||||
|
this.chargeStatus = chargeStatus;
|
||||||
|
this.power = power;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChargeStatus getChargeStatus() {
|
||||||
|
return chargeStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPower() {
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 判断当前时间是否在时间范围内
|
// 判断当前时间是否在时间范围内
|
||||||
private static boolean isTimeInRange(LocalTime now, Date startTime, Date endTime) {
|
private static boolean isTimeInRange(LocalTime now, Date startTime, Date endTime) {
|
||||||
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
|
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
|
||||||
@ -461,13 +689,17 @@ public class StrategyPoller {
|
|||||||
LocalTime endLocalTime = endTime.toInstant()
|
LocalTime endLocalTime = endTime.toInstant()
|
||||||
.atZone(zoneId)
|
.atZone(zoneId)
|
||||||
.toLocalTime();
|
.toLocalTime();
|
||||||
return now.equals(startLocalTime) || (now.isAfter(startLocalTime) && now.isBefore(endLocalTime));
|
// 支持跨天时段,如23:00-01:00;边界采用闭区间
|
||||||
|
if (!startLocalTime.isAfter(endLocalTime)) {
|
||||||
|
return !now.isBefore(startLocalTime) && !now.isAfter(endLocalTime);
|
||||||
|
}
|
||||||
|
return !now.isBefore(startLocalTime) || !now.isAfter(endLocalTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断SOC上限和下限
|
// 判断SOC上限和下限
|
||||||
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp) {
|
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp, EmsStrategyRuntimeConfig runtimeConfig) {
|
||||||
BigDecimal socDown = SOC_DOWN;
|
BigDecimal socDown = runtimeConfig.getSocDown();
|
||||||
BigDecimal socUp = SOC_UP;
|
BigDecimal socUp = runtimeConfig.getSocUp();
|
||||||
if (SocLimit.ON.getCode().equals(emsStrategyTemp.getSdcLimit())) {
|
if (SocLimit.ON.getCode().equals(emsStrategyTemp.getSdcLimit())) {
|
||||||
socDown = emsStrategyTemp.getSdcDown();
|
socDown = emsStrategyTemp.getSdcDown();
|
||||||
socUp = emsStrategyTemp.getSdcUp();
|
socUp = emsStrategyTemp.getSdcUp();
|
||||||
@ -491,4 +723,54 @@ public class StrategyPoller {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EmsStrategyRuntimeConfig getRuntimeConfig(String siteId) {
|
||||||
|
EmsStrategyRuntimeConfig config = runtimeConfigMapper.selectBySiteId(siteId);
|
||||||
|
if (config == null) {
|
||||||
|
config = new EmsStrategyRuntimeConfig();
|
||||||
|
config.setSiteId(siteId);
|
||||||
|
}
|
||||||
|
if (config.getSocDown() == null) {
|
||||||
|
config.setSocDown(DEFAULT_SOC_DOWN);
|
||||||
|
}
|
||||||
|
if (config.getSocUp() == null) {
|
||||||
|
config.setSocUp(DEFAULT_SOC_UP);
|
||||||
|
}
|
||||||
|
if (config.getAntiReverseThreshold() == null) {
|
||||||
|
config.setAntiReverseThreshold(DEFAULT_ANTI_REVERSE_THRESHOLD);
|
||||||
|
}
|
||||||
|
if (config.getAntiReverseRangePercent() == null) {
|
||||||
|
config.setAntiReverseRangePercent(DEFAULT_ANTI_REVERSE_RANGE_PERCENT);
|
||||||
|
}
|
||||||
|
if (config.getAntiReverseUp() == null) {
|
||||||
|
config.setAntiReverseUp(DEFAULT_ANTI_REVERSE_UP);
|
||||||
|
}
|
||||||
|
if (config.getAntiReversePowerDownPercent() == null) {
|
||||||
|
config.setAntiReversePowerDownPercent(DEFAULT_ANTI_REVERSE_POWER_DOWN_PERCENT);
|
||||||
|
}
|
||||||
|
if (config.getAntiReverseHardStopThreshold() == null) {
|
||||||
|
config.setAntiReverseHardStopThreshold(DEFAULT_ANTI_REVERSE_HARD_STOP_THRESHOLD);
|
||||||
|
}
|
||||||
|
if (config.getPowerSetMultiplier() == null || config.getPowerSetMultiplier().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
config.setPowerSetMultiplier(DEFAULT_POWER_SET_MULTIPLIER);
|
||||||
|
}
|
||||||
|
if (config.getProtectInterveneEnable() == null) {
|
||||||
|
config.setProtectInterveneEnable(DEFAULT_PROTECT_INTERVENE_ENABLE);
|
||||||
|
}
|
||||||
|
if (config.getProtectL1DeratePercent() == null
|
||||||
|
|| config.getProtectL1DeratePercent().compareTo(BigDecimal.ZERO) < 0
|
||||||
|
|| config.getProtectL1DeratePercent().compareTo(new BigDecimal("100")) > 0) {
|
||||||
|
config.setProtectL1DeratePercent(DEFAULT_PROTECT_L1_DERATE_PERCENT);
|
||||||
|
}
|
||||||
|
if (config.getProtectRecoveryStableSeconds() == null || config.getProtectRecoveryStableSeconds() < 0) {
|
||||||
|
config.setProtectRecoveryStableSeconds(DEFAULT_PROTECT_RECOVERY_STABLE_SECONDS);
|
||||||
|
}
|
||||||
|
if (config.getProtectL3LatchEnable() == null) {
|
||||||
|
config.setProtectL3LatchEnable(DEFAULT_PROTECT_L3_LATCH_ENABLE);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(config.getProtectConflictPolicy())) {
|
||||||
|
config.setProtectConflictPolicy(DEFAULT_PROTECT_CONFLICT_POLICY);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,12 @@
|
|||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.influxdb</groupId>
|
||||||
|
<artifactId>influxdb-java</artifactId>
|
||||||
|
<version>2.24</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.xzzn.ems.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "weather.api")
|
||||||
|
public class WeatherApiProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用天气同步
|
||||||
|
*/
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天气接口基础地址
|
||||||
|
*/
|
||||||
|
private String baseUrl = "https://archive-api.open-meteo.com/v1/archive";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可选接口鉴权字段
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时区参数
|
||||||
|
*/
|
||||||
|
private String timezone = "Asia/Shanghai";
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBaseUrl(String baseUrl) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApiKey() {
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApiKey(String apiKey) {
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimezone() {
|
||||||
|
return timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimezone(String timezone) {
|
||||||
|
this.timezone = timezone;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,10 +25,6 @@ public class EmsDailyChargeData extends BaseEntity
|
|||||||
@Excel(name = "站点id")
|
@Excel(name = "站点id")
|
||||||
private String siteId;
|
private String siteId;
|
||||||
|
|
||||||
/** 设备唯一标识符 */
|
|
||||||
@Excel(name = "设备唯一标识符")
|
|
||||||
private String deviceId;
|
|
||||||
|
|
||||||
/** 数据日期:yyyy-MM-dd */
|
/** 数据日期:yyyy-MM-dd */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
||||||
@ -50,6 +46,14 @@ public class EmsDailyChargeData extends BaseEntity
|
|||||||
@Excel(name = "当日放电量")
|
@Excel(name = "当日放电量")
|
||||||
private BigDecimal dischargeData;
|
private BigDecimal dischargeData;
|
||||||
|
|
||||||
|
/** 总收入 */
|
||||||
|
@Excel(name = "总收入")
|
||||||
|
private BigDecimal totalRevenue;
|
||||||
|
|
||||||
|
/** 当日实时收入 */
|
||||||
|
@Excel(name = "当日实时收入")
|
||||||
|
private BigDecimal dayRevenue;
|
||||||
|
|
||||||
public void setId(Long id)
|
public void setId(Long id)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -70,16 +74,6 @@ public class EmsDailyChargeData extends BaseEntity
|
|||||||
return siteId;
|
return siteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeviceId(String deviceId)
|
|
||||||
{
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceId()
|
|
||||||
{
|
|
||||||
return deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDateTime(Date dateTime)
|
public void setDateTime(Date dateTime)
|
||||||
{
|
{
|
||||||
this.dateTime = dateTime;
|
this.dateTime = dateTime;
|
||||||
@ -130,17 +124,38 @@ public class EmsDailyChargeData extends BaseEntity
|
|||||||
return dischargeData;
|
return dischargeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
.append("id", getId())
|
.append("id", getId())
|
||||||
.append("siteId", getSiteId())
|
.append("siteId", getSiteId())
|
||||||
.append("deviceId", getDeviceId())
|
|
||||||
.append("dateTime", getDateTime())
|
.append("dateTime", getDateTime())
|
||||||
.append("totalChargeData", getTotalChargeData())
|
.append("totalChargeData", getTotalChargeData())
|
||||||
.append("totalDischargeData", getTotalDischargeData())
|
.append("totalDischargeData", getTotalDischargeData())
|
||||||
.append("chargeData", getChargeData())
|
.append("chargeData", getChargeData())
|
||||||
.append("dischargeData", getDischargeData())
|
.append("dischargeData", getDischargeData())
|
||||||
|
.append("totalRevenue", getTotalRevenue())
|
||||||
|
.append("dayRevenue", getDayRevenue())
|
||||||
.append("createBy", getCreateBy())
|
.append("createBy", getCreateBy())
|
||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
.append("updateBy", getUpdateBy())
|
.append("updateBy", getUpdateBy())
|
||||||
|
|||||||
@ -30,13 +30,9 @@ public class EmsDailyEnergyData extends BaseEntity
|
|||||||
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
||||||
private Date dataDate;
|
private Date dataDate;
|
||||||
|
|
||||||
/** 总收入 */
|
/** 数据小时(0-23) */
|
||||||
@Excel(name = "总收入")
|
@Excel(name = "数据小时(0-23)")
|
||||||
private BigDecimal totalRevenue;
|
private Integer dataHour;
|
||||||
|
|
||||||
/** 当日实时收入 */
|
|
||||||
@Excel(name = "当日实时收入")
|
|
||||||
private BigDecimal dayRevenue;
|
|
||||||
|
|
||||||
/** 尖峰时段充电差值 */
|
/** 尖峰时段充电差值 */
|
||||||
@Excel(name = "尖峰时段充电差值")
|
@Excel(name = "尖峰时段充电差值")
|
||||||
@ -71,6 +67,7 @@ public class EmsDailyEnergyData extends BaseEntity
|
|||||||
private BigDecimal valleyDischargeDiff;
|
private BigDecimal valleyDischargeDiff;
|
||||||
|
|
||||||
/** 差值计算时间(如2025-10-10 23:59:00) */
|
/** 差值计算时间(如2025-10-10 23:59:00) */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "差值计算时间", readConverterExp = "如=2025-10-10,2=3:59:00")
|
@Excel(name = "差值计算时间", readConverterExp = "如=2025-10-10,2=3:59:00")
|
||||||
private Date calcTime;
|
private Date calcTime;
|
||||||
|
|
||||||
@ -104,24 +101,14 @@ public class EmsDailyEnergyData extends BaseEntity
|
|||||||
return dataDate;
|
return dataDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTotalRevenue(BigDecimal totalRevenue)
|
public void setDataHour(Integer dataHour)
|
||||||
{
|
{
|
||||||
this.totalRevenue = totalRevenue;
|
this.dataHour = dataHour;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalRevenue()
|
public Integer getDataHour()
|
||||||
{
|
{
|
||||||
return totalRevenue;
|
return dataHour;
|
||||||
}
|
|
||||||
|
|
||||||
public void setDayRevenue(BigDecimal dayRevenue)
|
|
||||||
{
|
|
||||||
this.dayRevenue = dayRevenue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getDayRevenue()
|
|
||||||
{
|
|
||||||
return dayRevenue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPeakChargeDiff(BigDecimal peakChargeDiff)
|
public void setPeakChargeDiff(BigDecimal peakChargeDiff)
|
||||||
@ -220,8 +207,7 @@ public class EmsDailyEnergyData extends BaseEntity
|
|||||||
.append("id", getId())
|
.append("id", getId())
|
||||||
.append("siteId", getSiteId())
|
.append("siteId", getSiteId())
|
||||||
.append("dataDate", getDataDate())
|
.append("dataDate", getDataDate())
|
||||||
.append("totalRevenue", getTotalRevenue())
|
.append("dataHour", getDataHour())
|
||||||
.append("dayRevenue", getDayRevenue())
|
|
||||||
.append("peakChargeDiff", getPeakChargeDiff())
|
.append("peakChargeDiff", getPeakChargeDiff())
|
||||||
.append("peakDischargeDiff", getPeakDischargeDiff())
|
.append("peakDischargeDiff", getPeakDischargeDiff())
|
||||||
.append("highChargeDiff", getHighChargeDiff())
|
.append("highChargeDiff", getHighChargeDiff())
|
||||||
|
|||||||
@ -49,6 +49,10 @@ public class EmsPcsSetting extends BaseEntity
|
|||||||
@Excel(name = "关机目标功率")
|
@Excel(name = "关机目标功率")
|
||||||
private BigDecimal stopPower;
|
private BigDecimal stopPower;
|
||||||
|
|
||||||
|
/** 目标功率倍率 */
|
||||||
|
@Excel(name = "目标功率倍率")
|
||||||
|
private BigDecimal powerMultiplier;
|
||||||
|
|
||||||
/** 电池簇数 */
|
/** 电池簇数 */
|
||||||
@Excel(name = "电池簇数")
|
@Excel(name = "电池簇数")
|
||||||
private Integer clusterNum;
|
private Integer clusterNum;
|
||||||
@ -135,6 +139,16 @@ public class EmsPcsSetting extends BaseEntity
|
|||||||
return stopPower;
|
return stopPower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPowerMultiplier()
|
||||||
|
{
|
||||||
|
return powerMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPowerMultiplier(BigDecimal powerMultiplier)
|
||||||
|
{
|
||||||
|
this.powerMultiplier = powerMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
public void setClusterNum(Integer clusterNum)
|
public void setClusterNum(Integer clusterNum)
|
||||||
{
|
{
|
||||||
this.clusterNum = clusterNum;
|
this.clusterNum = clusterNum;
|
||||||
@ -165,6 +179,7 @@ public class EmsPcsSetting extends BaseEntity
|
|||||||
.append("stopCommand", getStopCommand())
|
.append("stopCommand", getStopCommand())
|
||||||
.append("startPower", getStartPower())
|
.append("startPower", getStartPower())
|
||||||
.append("stopPower", getStopPower())
|
.append("stopPower", getStopPower())
|
||||||
|
.append("powerMultiplier", getPowerMultiplier())
|
||||||
.append("clusterNum", getClusterNum())
|
.append("clusterNum", getClusterNum())
|
||||||
.append("clusterPointAddress", getClusterPointAddress())
|
.append("clusterPointAddress", getClusterPointAddress())
|
||||||
.append("createBy", getCreateBy())
|
.append("createBy", getCreateBy())
|
||||||
|
|||||||
@ -0,0 +1,128 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Excel;
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
public class EmsPointCalcConfig extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Excel(name = "点位ID")
|
||||||
|
private String pointId;
|
||||||
|
|
||||||
|
@Excel(name = "站点ID")
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
@Excel(name = "设备类型")
|
||||||
|
private String deviceCategory;
|
||||||
|
|
||||||
|
@Excel(name = "点位名称")
|
||||||
|
private String pointName;
|
||||||
|
|
||||||
|
@Excel(name = "数据键")
|
||||||
|
private String dataKey;
|
||||||
|
|
||||||
|
@Excel(name = "点位描述")
|
||||||
|
private String pointDesc;
|
||||||
|
|
||||||
|
@Excel(name = "单位")
|
||||||
|
private String dataUnit;
|
||||||
|
|
||||||
|
@Excel(name = "计算表达式")
|
||||||
|
private String calcExpression;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointName() {
|
||||||
|
return pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointName(String pointName) {
|
||||||
|
this.pointName = pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceCategory() {
|
||||||
|
return deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceCategory(String deviceCategory) {
|
||||||
|
this.deviceCategory = deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointDesc() {
|
||||||
|
return pointDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointDesc(String pointDesc) {
|
||||||
|
this.pointDesc = pointDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataUnit() {
|
||||||
|
return dataUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataUnit(String dataUnit) {
|
||||||
|
this.dataUnit = dataUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCalcExpression() {
|
||||||
|
return calcExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalcExpression(String calcExpression) {
|
||||||
|
this.calcExpression = calcExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("id", getId())
|
||||||
|
.append("pointId", getPointId())
|
||||||
|
.append("siteId", getSiteId())
|
||||||
|
.append("deviceCategory", getDeviceCategory())
|
||||||
|
.append("pointName", getPointName())
|
||||||
|
.append("dataKey", getDataKey())
|
||||||
|
.append("pointDesc", getPointDesc())
|
||||||
|
.append("dataUnit", getDataUnit())
|
||||||
|
.append("calcExpression", getCalcExpression())
|
||||||
|
.append("createBy", getCreateBy())
|
||||||
|
.append("createTime", getCreateTime())
|
||||||
|
.append("updateBy", getUpdateBy())
|
||||||
|
.append("updateTime", getUpdateTime())
|
||||||
|
.append("remark", getRemark())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
301
ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java
Normal file
301
ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Excel;
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点位配置对象 ems_point_config
|
||||||
|
*/
|
||||||
|
public class EmsPointConfig extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Excel(name = "点位ID")
|
||||||
|
private String pointId;
|
||||||
|
|
||||||
|
@Excel(name = "站点ID")
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
@Excel(name = "设备类型")
|
||||||
|
private String deviceCategory;
|
||||||
|
|
||||||
|
@Excel(name = "设备ID")
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
@Excel(name = "点位名称")
|
||||||
|
private String pointName;
|
||||||
|
|
||||||
|
@Excel(name = "数据键")
|
||||||
|
private String dataKey;
|
||||||
|
|
||||||
|
@Excel(name = "点位描述")
|
||||||
|
private String pointDesc;
|
||||||
|
|
||||||
|
@Excel(name = "寄存器地址")
|
||||||
|
private String registerAddress;
|
||||||
|
|
||||||
|
@Excel(name = "单位")
|
||||||
|
private String dataUnit;
|
||||||
|
|
||||||
|
@Excel(name = "A系数")
|
||||||
|
private BigDecimal dataA;
|
||||||
|
|
||||||
|
@Excel(name = "K系数")
|
||||||
|
private BigDecimal dataK;
|
||||||
|
|
||||||
|
@Excel(name = "B系数")
|
||||||
|
private BigDecimal dataB;
|
||||||
|
|
||||||
|
@Excel(name = "位偏移")
|
||||||
|
private Integer dataBit;
|
||||||
|
|
||||||
|
@Excel(name = "是否报警点位", readConverterExp = "0=否,1=是")
|
||||||
|
private Integer isAlarm;
|
||||||
|
|
||||||
|
@Excel(name = "点位类型")
|
||||||
|
private String pointType;
|
||||||
|
|
||||||
|
@Excel(name = "计算表达式")
|
||||||
|
private String calcExpression;
|
||||||
|
|
||||||
|
@Excel(name = "是否启用采集", readConverterExp = "0=否,1=是")
|
||||||
|
private Integer collectEnabled;
|
||||||
|
|
||||||
|
@Excel(name = "采集来源")
|
||||||
|
private String collectSource;
|
||||||
|
|
||||||
|
@Excel(name = "Modbus寄存器类型")
|
||||||
|
private String modbusRegisterType;
|
||||||
|
|
||||||
|
@Excel(name = "Modbus数据类型")
|
||||||
|
private String modbusDataType;
|
||||||
|
|
||||||
|
@Excel(name = "Modbus读取顺序")
|
||||||
|
private Integer modbusReadOrder;
|
||||||
|
|
||||||
|
@Excel(name = "Modbus分组")
|
||||||
|
private String modbusGroup;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceCategory() {
|
||||||
|
return deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceCategory(String deviceCategory) {
|
||||||
|
this.deviceCategory = deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointName() {
|
||||||
|
return pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointName(String pointName) {
|
||||||
|
this.pointName = pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointDesc() {
|
||||||
|
return pointDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointDesc(String pointDesc) {
|
||||||
|
this.pointDesc = pointDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegisterAddress() {
|
||||||
|
return registerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegisterAddress(String registerAddress) {
|
||||||
|
this.registerAddress = registerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataUnit() {
|
||||||
|
return dataUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataUnit(String dataUnit) {
|
||||||
|
this.dataUnit = dataUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getDataA() {
|
||||||
|
return dataA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataA(BigDecimal dataA) {
|
||||||
|
this.dataA = dataA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getDataK() {
|
||||||
|
return dataK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataK(BigDecimal dataK) {
|
||||||
|
this.dataK = dataK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getDataB() {
|
||||||
|
return dataB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataB(BigDecimal dataB) {
|
||||||
|
this.dataB = dataB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDataBit() {
|
||||||
|
return dataBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataBit(Integer dataBit) {
|
||||||
|
this.dataBit = dataBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getIsAlarm() {
|
||||||
|
return isAlarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsAlarm(Integer isAlarm) {
|
||||||
|
this.isAlarm = isAlarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointType() {
|
||||||
|
return pointType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointType(String pointType) {
|
||||||
|
this.pointType = pointType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCalcExpression() {
|
||||||
|
return calcExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalcExpression(String calcExpression) {
|
||||||
|
this.calcExpression = calcExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCollectEnabled() {
|
||||||
|
return collectEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollectEnabled(Integer collectEnabled) {
|
||||||
|
this.collectEnabled = collectEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCollectSource() {
|
||||||
|
return collectSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollectSource(String collectSource) {
|
||||||
|
this.collectSource = collectSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModbusRegisterType() {
|
||||||
|
return modbusRegisterType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModbusRegisterType(String modbusRegisterType) {
|
||||||
|
this.modbusRegisterType = modbusRegisterType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModbusDataType() {
|
||||||
|
return modbusDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModbusDataType(String modbusDataType) {
|
||||||
|
this.modbusDataType = modbusDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getModbusReadOrder() {
|
||||||
|
return modbusReadOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModbusReadOrder(Integer modbusReadOrder) {
|
||||||
|
this.modbusReadOrder = modbusReadOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModbusGroup() {
|
||||||
|
return modbusGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModbusGroup(String modbusGroup) {
|
||||||
|
this.modbusGroup = modbusGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("id", getId())
|
||||||
|
.append("pointId", getPointId())
|
||||||
|
.append("siteId", getSiteId())
|
||||||
|
.append("deviceCategory", getDeviceCategory())
|
||||||
|
.append("deviceId", getDeviceId())
|
||||||
|
.append("pointName", getPointName())
|
||||||
|
.append("dataKey", getDataKey())
|
||||||
|
.append("pointDesc", getPointDesc())
|
||||||
|
.append("registerAddress", getRegisterAddress())
|
||||||
|
.append("dataUnit", getDataUnit())
|
||||||
|
.append("dataA", getDataA())
|
||||||
|
.append("dataK", getDataK())
|
||||||
|
.append("dataB", getDataB())
|
||||||
|
.append("dataBit", getDataBit())
|
||||||
|
.append("isAlarm", getIsAlarm())
|
||||||
|
.append("pointType", getPointType())
|
||||||
|
.append("calcExpression", getCalcExpression())
|
||||||
|
.append("collectEnabled", getCollectEnabled())
|
||||||
|
.append("collectSource", getCollectSource())
|
||||||
|
.append("modbusRegisterType", getModbusRegisterType())
|
||||||
|
.append("modbusDataType", getModbusDataType())
|
||||||
|
.append("modbusReadOrder", getModbusReadOrder())
|
||||||
|
.append("modbusGroup", getModbusGroup())
|
||||||
|
.append("createBy", getCreateBy())
|
||||||
|
.append("createTime", getCreateTime())
|
||||||
|
.append("updateBy", getUpdateBy())
|
||||||
|
.append("updateTime", getUpdateTime())
|
||||||
|
.append("remark", getRemark())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控展示数据对象(按分组落到 ems_site_monitor_data_home/sbjk/tjbb)
|
||||||
|
*/
|
||||||
|
public class EmsSiteMonitorData extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String siteId;
|
||||||
|
private String fieldCode;
|
||||||
|
private String fieldValue;
|
||||||
|
private Date valueTime;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldCode() {
|
||||||
|
return fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldCode(String fieldCode) {
|
||||||
|
this.fieldCode = fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldValue() {
|
||||||
|
return fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldValue(String fieldValue) {
|
||||||
|
this.fieldValue = fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getValueTime() {
|
||||||
|
return valueTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueTime(Date valueTime) {
|
||||||
|
this.valueTime = valueTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控配置项定义对象 ems_site_monitor_item
|
||||||
|
*/
|
||||||
|
public class EmsSiteMonitorItem extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String moduleCode;
|
||||||
|
private String moduleName;
|
||||||
|
private String menuCode;
|
||||||
|
private String menuName;
|
||||||
|
private String sectionName;
|
||||||
|
private String fieldCode;
|
||||||
|
private String fieldName;
|
||||||
|
private Integer sortNo;
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModuleCode() {
|
||||||
|
return moduleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModuleCode(String moduleCode) {
|
||||||
|
this.moduleCode = moduleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModuleName() {
|
||||||
|
return moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModuleName(String moduleName) {
|
||||||
|
this.moduleName = moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenuCode() {
|
||||||
|
return menuCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMenuCode(String menuCode) {
|
||||||
|
this.menuCode = menuCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenuName() {
|
||||||
|
return menuName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMenuName(String menuName) {
|
||||||
|
this.menuName = menuName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSectionName() {
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSectionName(String sectionName) {
|
||||||
|
this.sectionName = sectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldCode() {
|
||||||
|
return fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldCode(String fieldCode) {
|
||||||
|
this.fieldCode = fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldName() {
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldName(String fieldName) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSortNo() {
|
||||||
|
return sortNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSortNo(Integer sortNo) {
|
||||||
|
this.sortNo = sortNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控字段点位映射对象 ems_site_monitor_point_match
|
||||||
|
*/
|
||||||
|
public class EmsSiteMonitorPointMatch extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String siteId;
|
||||||
|
private String fieldCode;
|
||||||
|
private String deviceId;
|
||||||
|
private String dataPoint;
|
||||||
|
private String fixedDataPoint;
|
||||||
|
private Integer useFixedDisplay;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldCode() {
|
||||||
|
return fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldCode(String fieldCode) {
|
||||||
|
this.fieldCode = fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataPoint() {
|
||||||
|
return dataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataPoint(String dataPoint) {
|
||||||
|
this.dataPoint = dataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFixedDataPoint() {
|
||||||
|
return fixedDataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFixedDataPoint(String fixedDataPoint) {
|
||||||
|
this.fixedDataPoint = fixedDataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getUseFixedDisplay() {
|
||||||
|
return useFixedDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseFixedDisplay(Integer useFixedDisplay) {
|
||||||
|
this.useFixedDisplay = useFixedDisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,6 +25,10 @@ public class EmsSiteSetting extends BaseEntity
|
|||||||
@Excel(name = "站点名称")
|
@Excel(name = "站点名称")
|
||||||
private String siteName;
|
private String siteName;
|
||||||
|
|
||||||
|
/** 站点简称 */
|
||||||
|
@Excel(name = "站点简称")
|
||||||
|
private String siteShortName;
|
||||||
|
|
||||||
/** 站点地址 */
|
/** 站点地址 */
|
||||||
@Excel(name = "站点地址")
|
@Excel(name = "站点地址")
|
||||||
private String siteAddress;
|
private String siteAddress;
|
||||||
@ -54,6 +58,9 @@ public class EmsSiteSetting extends BaseEntity
|
|||||||
@Excel(name = "站点id")
|
@Excel(name = "站点id")
|
||||||
private String siteId;
|
private String siteId;
|
||||||
|
|
||||||
|
/** 授权状态:true-已授权,false-未授权 */
|
||||||
|
private Boolean authorized;
|
||||||
|
|
||||||
public void setId(Long id)
|
public void setId(Long id)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -74,6 +81,16 @@ public class EmsSiteSetting extends BaseEntity
|
|||||||
return siteName;
|
return siteName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSiteShortName(String siteShortName)
|
||||||
|
{
|
||||||
|
this.siteShortName = siteShortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteShortName()
|
||||||
|
{
|
||||||
|
return siteShortName;
|
||||||
|
}
|
||||||
|
|
||||||
public void setSiteAddress(String siteAddress)
|
public void setSiteAddress(String siteAddress)
|
||||||
{
|
{
|
||||||
this.siteAddress = siteAddress;
|
this.siteAddress = siteAddress;
|
||||||
@ -144,11 +161,22 @@ public class EmsSiteSetting extends BaseEntity
|
|||||||
return siteId;
|
return siteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAuthorized(Boolean authorized)
|
||||||
|
{
|
||||||
|
this.authorized = authorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAuthorized()
|
||||||
|
{
|
||||||
|
return authorized;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
.append("id", getId())
|
.append("id", getId())
|
||||||
.append("siteName", getSiteName())
|
.append("siteName", getSiteName())
|
||||||
|
.append("siteShortName", getSiteShortName())
|
||||||
.append("siteAddress", getSiteAddress())
|
.append("siteAddress", getSiteAddress())
|
||||||
.append("runningTime", getRunningTime())
|
.append("runningTime", getRunningTime())
|
||||||
.append("latitude", getLatitude())
|
.append("latitude", getLatitude())
|
||||||
@ -161,6 +189,7 @@ public class EmsSiteSetting extends BaseEntity
|
|||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
.append("updateTime", getUpdateTime())
|
.append("updateTime", getUpdateTime())
|
||||||
.append("siteId", getSiteId())
|
.append("siteId", getSiteId())
|
||||||
|
.append("authorized", getAuthorized())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,221 @@
|
|||||||
|
package com.xzzn.ems.domain;
|
||||||
|
|
||||||
|
import com.xzzn.common.annotation.Excel;
|
||||||
|
import com.xzzn.common.core.domain.BaseEntity;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略运行参数配置对象 ems_strategy_runtime_config
|
||||||
|
*
|
||||||
|
* @author xzzn
|
||||||
|
* @date 2026-02-13
|
||||||
|
*/
|
||||||
|
public class EmsStrategyRuntimeConfig extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 站点ID */
|
||||||
|
@Excel(name = "站点ID")
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
/** SOC下限(%) */
|
||||||
|
@Excel(name = "SOC下限(%)")
|
||||||
|
private BigDecimal socDown;
|
||||||
|
|
||||||
|
/** SOC上限(%) */
|
||||||
|
@Excel(name = "SOC上限(%)")
|
||||||
|
private BigDecimal socUp;
|
||||||
|
|
||||||
|
/** 防逆流阈值(kW) */
|
||||||
|
@Excel(name = "防逆流阈值(kW)")
|
||||||
|
private BigDecimal antiReverseThreshold;
|
||||||
|
|
||||||
|
/** 防逆流阈值上浮比例(%) */
|
||||||
|
@Excel(name = "防逆流阈值上浮比例(%)")
|
||||||
|
private BigDecimal antiReverseRangePercent;
|
||||||
|
|
||||||
|
/** 防逆流恢复上限(kW) */
|
||||||
|
@Excel(name = "防逆流恢复上限(kW)")
|
||||||
|
private BigDecimal antiReverseUp;
|
||||||
|
|
||||||
|
/** 防逆流降功率比例(%) */
|
||||||
|
@Excel(name = "防逆流降功率比例(%)")
|
||||||
|
private BigDecimal antiReversePowerDownPercent;
|
||||||
|
/** 防逆流硬停阈值(kW) */
|
||||||
|
@Excel(name = "防逆流硬停阈值(kW)")
|
||||||
|
private BigDecimal antiReverseHardStopThreshold;
|
||||||
|
/** 设定功率倍率 */
|
||||||
|
@Excel(name = "设定功率倍率")
|
||||||
|
private BigDecimal powerSetMultiplier;
|
||||||
|
|
||||||
|
/** 保护介入开关(1-启用,0-禁用) */
|
||||||
|
@Excel(name = "保护介入开关")
|
||||||
|
private Integer protectInterveneEnable;
|
||||||
|
|
||||||
|
/** 一级保护降额比例(%) */
|
||||||
|
@Excel(name = "一级保护降额比例(%)")
|
||||||
|
private BigDecimal protectL1DeratePercent;
|
||||||
|
|
||||||
|
/** 保护释放稳定时长(秒) */
|
||||||
|
@Excel(name = "保护释放稳定时长(秒)")
|
||||||
|
private Integer protectRecoveryStableSeconds;
|
||||||
|
|
||||||
|
/** 三级保护锁存开关(1-启用,0-禁用) */
|
||||||
|
@Excel(name = "三级保护锁存开关")
|
||||||
|
private Integer protectL3LatchEnable;
|
||||||
|
|
||||||
|
/** 保护冲突策略 */
|
||||||
|
@Excel(name = "保护冲突策略")
|
||||||
|
private String protectConflictPolicy;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getSocDown() {
|
||||||
|
return socDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocDown(BigDecimal socDown) {
|
||||||
|
this.socDown = socDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getSocUp() {
|
||||||
|
return socUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocUp(BigDecimal socUp) {
|
||||||
|
this.socUp = socUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAntiReverseThreshold() {
|
||||||
|
return antiReverseThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiReverseThreshold(BigDecimal antiReverseThreshold) {
|
||||||
|
this.antiReverseThreshold = antiReverseThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAntiReverseRangePercent() {
|
||||||
|
return antiReverseRangePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiReverseRangePercent(BigDecimal antiReverseRangePercent) {
|
||||||
|
this.antiReverseRangePercent = antiReverseRangePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAntiReverseUp() {
|
||||||
|
return antiReverseUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiReverseUp(BigDecimal antiReverseUp) {
|
||||||
|
this.antiReverseUp = antiReverseUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAntiReversePowerDownPercent() {
|
||||||
|
return antiReversePowerDownPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiReversePowerDownPercent(BigDecimal antiReversePowerDownPercent) {
|
||||||
|
this.antiReversePowerDownPercent = antiReversePowerDownPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAntiReverseHardStopThreshold() {
|
||||||
|
return antiReverseHardStopThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiReverseHardStopThreshold(BigDecimal antiReverseHardStopThreshold) {
|
||||||
|
this.antiReverseHardStopThreshold = antiReverseHardStopThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPowerSetMultiplier() {
|
||||||
|
return powerSetMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPowerSetMultiplier(BigDecimal powerSetMultiplier) {
|
||||||
|
this.powerSetMultiplier = powerSetMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProtectInterveneEnable() {
|
||||||
|
return protectInterveneEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtectInterveneEnable(Integer protectInterveneEnable) {
|
||||||
|
this.protectInterveneEnable = protectInterveneEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getProtectL1DeratePercent() {
|
||||||
|
return protectL1DeratePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtectL1DeratePercent(BigDecimal protectL1DeratePercent) {
|
||||||
|
this.protectL1DeratePercent = protectL1DeratePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProtectRecoveryStableSeconds() {
|
||||||
|
return protectRecoveryStableSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtectRecoveryStableSeconds(Integer protectRecoveryStableSeconds) {
|
||||||
|
this.protectRecoveryStableSeconds = protectRecoveryStableSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProtectL3LatchEnable() {
|
||||||
|
return protectL3LatchEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtectL3LatchEnable(Integer protectL3LatchEnable) {
|
||||||
|
this.protectL3LatchEnable = protectL3LatchEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProtectConflictPolicy() {
|
||||||
|
return protectConflictPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtectConflictPolicy(String protectConflictPolicy) {
|
||||||
|
this.protectConflictPolicy = protectConflictPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("id", getId())
|
||||||
|
.append("siteId", getSiteId())
|
||||||
|
.append("socDown", getSocDown())
|
||||||
|
.append("socUp", getSocUp())
|
||||||
|
.append("antiReverseThreshold", getAntiReverseThreshold())
|
||||||
|
.append("antiReverseRangePercent", getAntiReverseRangePercent())
|
||||||
|
.append("antiReverseUp", getAntiReverseUp())
|
||||||
|
.append("antiReversePowerDownPercent", getAntiReversePowerDownPercent())
|
||||||
|
.append("antiReverseHardStopThreshold", getAntiReverseHardStopThreshold())
|
||||||
|
.append("powerSetMultiplier", getPowerSetMultiplier())
|
||||||
|
.append("protectInterveneEnable", getProtectInterveneEnable())
|
||||||
|
.append("protectL1DeratePercent", getProtectL1DeratePercent())
|
||||||
|
.append("protectRecoveryStableSeconds", getProtectRecoveryStableSeconds())
|
||||||
|
.append("protectL3LatchEnable", getProtectL3LatchEnable())
|
||||||
|
.append("protectConflictPolicy", getProtectConflictPolicy())
|
||||||
|
.append("createBy", getCreateBy())
|
||||||
|
.append("createTime", getCreateTime())
|
||||||
|
.append("updateBy", getUpdateBy())
|
||||||
|
.append("updateTime", getUpdateTime())
|
||||||
|
.append("remark", getRemark())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,14 @@ public class EmsStrategyTempTimeConfig extends BaseEntity
|
|||||||
@Excel(name = "充放功率 (kW)")
|
@Excel(name = "充放功率 (kW)")
|
||||||
private BigDecimal chargeDischargePower;
|
private BigDecimal chargeDischargePower;
|
||||||
|
|
||||||
|
/** SDC下限 (%) */
|
||||||
|
@Excel(name = "SDC下限 (%)")
|
||||||
|
private BigDecimal sdcDown;
|
||||||
|
|
||||||
|
/** SDC上限 (%) */
|
||||||
|
@Excel(name = "SDC上限 (%)")
|
||||||
|
private BigDecimal sdcUp;
|
||||||
|
|
||||||
/** 充电状态,如“1-充电”、“2-待机” */
|
/** 充电状态,如“1-充电”、“2-待机” */
|
||||||
@Excel(name = "充电状态,如“1-充电”、“2-待机”")
|
@Excel(name = "充电状态,如“1-充电”、“2-待机”")
|
||||||
private String chargeStatus;
|
private String chargeStatus;
|
||||||
@ -83,6 +91,26 @@ public class EmsStrategyTempTimeConfig extends BaseEntity
|
|||||||
return chargeDischargePower;
|
return chargeDischargePower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSdcDown(BigDecimal sdcDown)
|
||||||
|
{
|
||||||
|
this.sdcDown = sdcDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getSdcDown()
|
||||||
|
{
|
||||||
|
return sdcDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSdcUp(BigDecimal sdcUp)
|
||||||
|
{
|
||||||
|
this.sdcUp = sdcUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getSdcUp()
|
||||||
|
{
|
||||||
|
return sdcUp;
|
||||||
|
}
|
||||||
|
|
||||||
public void setChargeStatus(String chargeStatus)
|
public void setChargeStatus(String chargeStatus)
|
||||||
{
|
{
|
||||||
this.chargeStatus = chargeStatus;
|
this.chargeStatus = chargeStatus;
|
||||||
@ -110,6 +138,8 @@ public class EmsStrategyTempTimeConfig extends BaseEntity
|
|||||||
.append("startTime", getStartTime())
|
.append("startTime", getStartTime())
|
||||||
.append("endTime", getEndTime())
|
.append("endTime", getEndTime())
|
||||||
.append("chargeDischargePower", getChargeDischargePower())
|
.append("chargeDischargePower", getChargeDischargePower())
|
||||||
|
.append("sdcDown", getSdcDown())
|
||||||
|
.append("sdcUp", getSdcUp())
|
||||||
.append("chargeStatus", getChargeStatus())
|
.append("chargeStatus", getChargeStatus())
|
||||||
.append("createBy", getCreateBy())
|
.append("createBy", getCreateBy())
|
||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
|
|||||||
@ -11,6 +11,15 @@ public class AmmeterRevenueStatisListVo {
|
|||||||
/** 类别 */
|
/** 类别 */
|
||||||
private String dataTime;
|
private String dataTime;
|
||||||
|
|
||||||
|
/** 是否工作日:1-工作日 0-节假日 */
|
||||||
|
private Integer isWorkday;
|
||||||
|
|
||||||
|
/** 日期类型 */
|
||||||
|
private String dayType;
|
||||||
|
|
||||||
|
/** 天气情况 */
|
||||||
|
private String weatherDesc;
|
||||||
|
|
||||||
/** 组合有功-总 */
|
/** 组合有功-总 */
|
||||||
private BigDecimal activeTotalPrice = BigDecimal.ZERO;
|
private BigDecimal activeTotalPrice = BigDecimal.ZERO;
|
||||||
|
|
||||||
@ -52,6 +61,30 @@ public class AmmeterRevenueStatisListVo {
|
|||||||
this.dataTime = dataTime;
|
this.dataTime = dataTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getIsWorkday() {
|
||||||
|
return isWorkday;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsWorkday(Integer isWorkday) {
|
||||||
|
this.isWorkday = isWorkday;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDayType() {
|
||||||
|
return dayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDayType(String dayType) {
|
||||||
|
this.dayType = dayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWeatherDesc() {
|
||||||
|
return weatherDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeatherDesc(String weatherDesc) {
|
||||||
|
this.weatherDesc = weatherDesc;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getActiveTotalPrice() {
|
public BigDecimal getActiveTotalPrice() {
|
||||||
return activeTotalPrice;
|
return activeTotalPrice;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,18 @@ public class BatteryDataStatsListVo {
|
|||||||
/** SOH (%) */
|
/** SOH (%) */
|
||||||
private BigDecimal soh;
|
private BigDecimal soh;
|
||||||
|
|
||||||
|
/** 电压映射点位ID */
|
||||||
|
private String voltagePointId;
|
||||||
|
|
||||||
|
/** 温度映射点位ID */
|
||||||
|
private String temperaturePointId;
|
||||||
|
|
||||||
|
/** SOC映射点位ID */
|
||||||
|
private String socPointId;
|
||||||
|
|
||||||
|
/** SOH映射点位ID */
|
||||||
|
private String sohPointId;
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private Date dataTimestamp;
|
private Date dataTimestamp;
|
||||||
|
|
||||||
@ -71,6 +83,38 @@ public class BatteryDataStatsListVo {
|
|||||||
this.soh = soh;
|
this.soh = soh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVoltagePointId() {
|
||||||
|
return voltagePointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVoltagePointId(String voltagePointId) {
|
||||||
|
this.voltagePointId = voltagePointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemperaturePointId() {
|
||||||
|
return temperaturePointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemperaturePointId(String temperaturePointId) {
|
||||||
|
this.temperaturePointId = temperaturePointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSocPointId() {
|
||||||
|
return socPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocPointId(String socPointId) {
|
||||||
|
this.socPointId = socPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSohPointId() {
|
||||||
|
return sohPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSohPointId(String sohPointId) {
|
||||||
|
this.sohPointId = sohPointId;
|
||||||
|
}
|
||||||
|
|
||||||
public Date getDataTimestamp() {
|
public Date getDataTimestamp() {
|
||||||
return dataTimestamp;
|
return dataTimestamp;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,11 +24,25 @@ public class DevicePointDataList
|
|||||||
private BigDecimal avgValue;
|
private BigDecimal avgValue;
|
||||||
// 差值(max - min)
|
// 差值(max - min)
|
||||||
private BigDecimal diffValue;
|
private BigDecimal diffValue;
|
||||||
|
// 第一四分位数
|
||||||
|
private BigDecimal q1;
|
||||||
|
// 中位数
|
||||||
|
private BigDecimal median;
|
||||||
|
// 第三四分位数
|
||||||
|
private BigDecimal q3;
|
||||||
|
|
||||||
public DevicePointDataList(String deviceId, List<GeneralQueryDataVo> pointValueList,String parentDeviceId,
|
public DevicePointDataList(String deviceId, List<GeneralQueryDataVo> pointValueList,String parentDeviceId,
|
||||||
BigDecimal maxValue, BigDecimal minValue,
|
BigDecimal maxValue, BigDecimal minValue,
|
||||||
BigDecimal avgValue, BigDecimal diffValue,
|
BigDecimal avgValue, BigDecimal diffValue,
|
||||||
String maxDate, String minDate) {
|
String maxDate, String minDate) {
|
||||||
|
this(deviceId, pointValueList, parentDeviceId, maxValue, minValue, avgValue, diffValue, maxDate, minDate, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DevicePointDataList(String deviceId, List<GeneralQueryDataVo> pointValueList,String parentDeviceId,
|
||||||
|
BigDecimal maxValue, BigDecimal minValue,
|
||||||
|
BigDecimal avgValue, BigDecimal diffValue,
|
||||||
|
String maxDate, String minDate,
|
||||||
|
BigDecimal q1, BigDecimal median, BigDecimal q3) {
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
this.pointValueList = pointValueList;
|
this.pointValueList = pointValueList;
|
||||||
this.parentDeviceId = parentDeviceId;
|
this.parentDeviceId = parentDeviceId;
|
||||||
@ -38,6 +52,9 @@ public class DevicePointDataList
|
|||||||
this.diffValue = diffValue;
|
this.diffValue = diffValue;
|
||||||
this.maxDate = maxDate;
|
this.maxDate = maxDate;
|
||||||
this.minDate = minDate;
|
this.minDate = minDate;
|
||||||
|
this.q1 = q1;
|
||||||
|
this.median = median;
|
||||||
|
this.q3 = q3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DevicePointDataList(String deviceId, String parentDeviceId, List<GeneralQueryDataVo> pointValueList) {
|
public DevicePointDataList(String deviceId, String parentDeviceId, List<GeneralQueryDataVo> pointValueList) {
|
||||||
@ -121,4 +138,28 @@ public class DevicePointDataList
|
|||||||
public void setDiffValue(BigDecimal diffValue) {
|
public void setDiffValue(BigDecimal diffValue) {
|
||||||
this.diffValue = diffValue;
|
this.diffValue = diffValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getQ1() {
|
||||||
|
return q1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQ1(BigDecimal q1) {
|
||||||
|
this.q1 = q1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getMedian() {
|
||||||
|
return median;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMedian(BigDecimal median) {
|
||||||
|
this.median = median;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getQ3() {
|
||||||
|
return q3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQ3(BigDecimal q3) {
|
||||||
|
this.q3 = q3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class GeneralQueryPointOptionVo {
|
||||||
|
private String pointId;
|
||||||
|
private String pointName;
|
||||||
|
private String dataKey;
|
||||||
|
private String pointDesc;
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointName() {
|
||||||
|
return pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointName(String pointName) {
|
||||||
|
this.pointName = pointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointDesc() {
|
||||||
|
return pointDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointDesc(String pointDesc) {
|
||||||
|
this.pointDesc = pointDesc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按站点导入点位模板请求参数
|
||||||
|
*/
|
||||||
|
public class ImportPointTemplateRequest {
|
||||||
|
|
||||||
|
/** 目标站点ID */
|
||||||
|
@NotBlank(message = "站点ID不能为空")
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
/** 是否覆盖目标站点已有点位配置 */
|
||||||
|
private Boolean overwrite;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getOverwrite() {
|
||||||
|
return overwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOverwrite(Boolean overwrite) {
|
||||||
|
this.overwrite = overwrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class PointConfigCurveRequest {
|
||||||
|
private String siteId;
|
||||||
|
private String deviceId;
|
||||||
|
private String pointId;
|
||||||
|
private String dataKey;
|
||||||
|
private String pointType;
|
||||||
|
private String rangeType;
|
||||||
|
private String startTime;
|
||||||
|
private String endTime;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointType() {
|
||||||
|
return pointType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointType(String pointType) {
|
||||||
|
this.pointType = pointType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRangeType() {
|
||||||
|
return rangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRangeType(String rangeType) {
|
||||||
|
this.rangeType = rangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(String startTime) {
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEndTime() {
|
||||||
|
return endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndTime(String endTime) {
|
||||||
|
this.endTime = endTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class PointConfigCurveValueVo {
|
||||||
|
private Date dataTime;
|
||||||
|
private Object pointValue;
|
||||||
|
|
||||||
|
public Date getDataTime() {
|
||||||
|
return dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataTime(Date dataTime) {
|
||||||
|
this.dataTime = dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPointValue() {
|
||||||
|
return pointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointValue(Object pointValue) {
|
||||||
|
this.pointValue = pointValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public class PointConfigGenerateRecentRequest {
|
||||||
|
|
||||||
|
@NotBlank(message = "站点ID不能为空")
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
@NotBlank(message = "点位ID不能为空")
|
||||||
|
private String pointId;
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class PointConfigLatestValueItemVo {
|
||||||
|
private String siteId;
|
||||||
|
private String pointId;
|
||||||
|
private String deviceId;
|
||||||
|
private String dataKey;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PointConfigLatestValueRequest {
|
||||||
|
private List<PointConfigLatestValueItemVo> points;
|
||||||
|
|
||||||
|
public List<PointConfigLatestValueItemVo> getPoints() {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoints(List<PointConfigLatestValueItemVo> points) {
|
||||||
|
this.points = points;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class PointConfigLatestValueVo {
|
||||||
|
private String siteId;
|
||||||
|
private String pointId;
|
||||||
|
private String deviceId;
|
||||||
|
private String dataKey;
|
||||||
|
private Object pointValue;
|
||||||
|
private Date dataTime;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataKey() {
|
||||||
|
return dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataKey(String dataKey) {
|
||||||
|
this.dataKey = dataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPointValue() {
|
||||||
|
return pointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointValue(Object pointValue) {
|
||||||
|
this.pointValue = pointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDataTime() {
|
||||||
|
return dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataTime(Date dataTime) {
|
||||||
|
this.dataTime = dataTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,10 @@
|
|||||||
package com.xzzn.ems.domain.vo;
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备列表-点位详情-入参
|
* 设备列表-点位详情-入参
|
||||||
*
|
*
|
||||||
@ -24,6 +25,8 @@ public class PointDataRequest {
|
|||||||
private String dataPointName;
|
private String dataPointName;
|
||||||
/** 点位-模糊查询 */
|
/** 点位-模糊查询 */
|
||||||
private String dataPoint;
|
private String dataPoint;
|
||||||
|
/** 点位匹配字段 */
|
||||||
|
private String matchField;
|
||||||
/** 点位数据-范围上下限 */
|
/** 点位数据-范围上下限 */
|
||||||
private BigDecimal lower;
|
private BigDecimal lower;
|
||||||
private BigDecimal upper;
|
private BigDecimal upper;
|
||||||
@ -126,6 +129,14 @@ public class PointDataRequest {
|
|||||||
this.dataPoint = dataPoint;
|
this.dataPoint = dataPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMatchField() {
|
||||||
|
return matchField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMatchField(String matchField) {
|
||||||
|
this.matchField = matchField;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getLower() {
|
public BigDecimal getLower() {
|
||||||
return lower;
|
return lower;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ public class PointNameRequest {
|
|||||||
private String deviceCategory;
|
private String deviceCategory;
|
||||||
|
|
||||||
private String pointName;
|
private String pointName;
|
||||||
|
private List<String> pointNames;
|
||||||
|
private String pointId;
|
||||||
|
private List<String> pointIds;
|
||||||
|
|
||||||
/** 数据分组 1-分钟 2-小时 3-天 */
|
/** 数据分组 1-分钟 2-小时 3-天 */
|
||||||
private int dataUnit;
|
private int dataUnit;
|
||||||
@ -50,6 +53,30 @@ public class PointNameRequest {
|
|||||||
this.pointName = pointName;
|
this.pointName = pointName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getPointNames() {
|
||||||
|
return pointNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointNames(List<String> pointNames) {
|
||||||
|
this.pointNames = pointNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointId() {
|
||||||
|
return pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointId(String pointId) {
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPointIds() {
|
||||||
|
return pointIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointIds(List<String> pointIds) {
|
||||||
|
this.pointIds = pointIds;
|
||||||
|
}
|
||||||
|
|
||||||
public int getDataUnit() {
|
public int getDataUnit() {
|
||||||
return dataUnit;
|
return dataUnit;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,10 @@ public class PointQueryResponse
|
|||||||
@Excel(name = "点位名称")
|
@Excel(name = "点位名称")
|
||||||
private String pointName;
|
private String pointName;
|
||||||
|
|
||||||
|
/** 点位匹配字段 */
|
||||||
|
@Excel(name = "点位匹配字段")
|
||||||
|
private String matchField;
|
||||||
|
|
||||||
/** 数据点位 */
|
/** 数据点位 */
|
||||||
@Excel(name = "数据点位")
|
@Excel(name = "数据点位")
|
||||||
private String dataPoint;
|
private String dataPoint;
|
||||||
@ -110,6 +114,14 @@ public class PointQueryResponse
|
|||||||
this.pointName = pointName;
|
this.pointName = pointName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMatchField() {
|
||||||
|
return matchField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMatchField(String matchField) {
|
||||||
|
this.matchField = matchField;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDataUnit() {
|
public String getDataUnit() {
|
||||||
return dataUnit;
|
return dataUnit;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,114 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点保护约束(供策略轮询仲裁)
|
||||||
|
*/
|
||||||
|
public class ProtectionConstraintVo implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 最高保护等级:0-无保护,1/2/3 对应故障等级 */
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
/** 是否允许充电 */
|
||||||
|
private Boolean allowCharge;
|
||||||
|
|
||||||
|
/** 是否允许放电 */
|
||||||
|
private Boolean allowDischarge;
|
||||||
|
|
||||||
|
/** 功率上限比例(0~1) */
|
||||||
|
private BigDecimal powerLimitRatio;
|
||||||
|
|
||||||
|
/** 是否强制待机 */
|
||||||
|
private Boolean forceStandby;
|
||||||
|
|
||||||
|
/** 是否强制停机 */
|
||||||
|
private Boolean forceStop;
|
||||||
|
|
||||||
|
/** 生效的方案ID列表 */
|
||||||
|
private List<Long> sourcePlanIds;
|
||||||
|
|
||||||
|
/** 更新时间戳(毫秒) */
|
||||||
|
private Long updateAt;
|
||||||
|
|
||||||
|
public Integer getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(Integer level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAllowCharge() {
|
||||||
|
return allowCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowCharge(Boolean allowCharge) {
|
||||||
|
this.allowCharge = allowCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAllowDischarge() {
|
||||||
|
return allowDischarge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowDischarge(Boolean allowDischarge) {
|
||||||
|
this.allowDischarge = allowDischarge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPowerLimitRatio() {
|
||||||
|
return powerLimitRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPowerLimitRatio(BigDecimal powerLimitRatio) {
|
||||||
|
this.powerLimitRatio = powerLimitRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getForceStandby() {
|
||||||
|
return forceStandby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForceStandby(Boolean forceStandby) {
|
||||||
|
this.forceStandby = forceStandby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getForceStop() {
|
||||||
|
return forceStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForceStop(Boolean forceStop) {
|
||||||
|
this.forceStop = forceStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getSourcePlanIds() {
|
||||||
|
return sourcePlanIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourcePlanIds(List<Long> sourcePlanIds) {
|
||||||
|
this.sourcePlanIds = sourcePlanIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUpdateAt() {
|
||||||
|
return updateAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateAt(Long updateAt) {
|
||||||
|
this.updateAt = updateAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProtectionConstraintVo empty() {
|
||||||
|
ProtectionConstraintVo vo = new ProtectionConstraintVo();
|
||||||
|
vo.setLevel(0);
|
||||||
|
vo.setAllowCharge(true);
|
||||||
|
vo.setAllowDischarge(true);
|
||||||
|
vo.setPowerLimitRatio(BigDecimal.ONE);
|
||||||
|
vo.setForceStandby(false);
|
||||||
|
vo.setForceStop(false);
|
||||||
|
vo.setSourcePlanIds(new ArrayList<>());
|
||||||
|
vo.setUpdateAt(System.currentTimeMillis());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警保护方案-保护前提分组
|
||||||
|
*/
|
||||||
|
public class ProtectionSettingsGroupVo {
|
||||||
|
/** 故障保护前提 */
|
||||||
|
private List<ProtectionSettingVo> faultSettings;
|
||||||
|
|
||||||
|
/** 释放保护前提 */
|
||||||
|
private List<ProtectionSettingVo> releaseSettings;
|
||||||
|
|
||||||
|
public static ProtectionSettingsGroupVo empty() {
|
||||||
|
ProtectionSettingsGroupVo vo = new ProtectionSettingsGroupVo();
|
||||||
|
vo.setFaultSettings(new ArrayList<>());
|
||||||
|
vo.setReleaseSettings(new ArrayList<>());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProtectionSettingVo> getFaultSettings() {
|
||||||
|
return faultSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaultSettings(List<ProtectionSettingVo> faultSettings) {
|
||||||
|
this.faultSettings = faultSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProtectionSettingVo> getReleaseSettings() {
|
||||||
|
return releaseSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReleaseSettings(List<ProtectionSettingVo> releaseSettings) {
|
||||||
|
this.releaseSettings = releaseSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package com.xzzn.ems.domain.vo;
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -10,10 +11,12 @@ import java.util.Date;
|
|||||||
public class RunningGraphRequest {
|
public class RunningGraphRequest {
|
||||||
|
|
||||||
/** 开始时间 */
|
/** 开始时间 */
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private Date startDate;
|
private Date startDate;
|
||||||
|
|
||||||
/** 结束时间 */
|
/** 结束时间 */
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private Date endDate;
|
private Date endDate;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class SiteMonitorDataSaveItemVo {
|
||||||
|
private String fieldCode;
|
||||||
|
private String fieldValue;
|
||||||
|
private Date valueTime;
|
||||||
|
|
||||||
|
public String getFieldCode() {
|
||||||
|
return fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldCode(String fieldCode) {
|
||||||
|
this.fieldCode = fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldValue() {
|
||||||
|
return fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldValue(String fieldValue) {
|
||||||
|
this.fieldValue = fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getValueTime() {
|
||||||
|
return valueTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueTime(Date valueTime) {
|
||||||
|
this.valueTime = valueTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SiteMonitorDataSaveRequest {
|
||||||
|
private String siteId;
|
||||||
|
private List<SiteMonitorDataSaveItemVo> items;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SiteMonitorDataSaveItemVo> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<SiteMonitorDataSaveItemVo> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控展示数据(配置项 + 当前值)
|
||||||
|
*/
|
||||||
|
public class SiteMonitorProjectDisplayVo extends SiteMonitorProjectPointMappingVo {
|
||||||
|
private String fieldValue;
|
||||||
|
private Date valueTime;
|
||||||
|
|
||||||
|
public String getFieldValue() {
|
||||||
|
return fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldValue(String fieldValue) {
|
||||||
|
this.fieldValue = fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getValueTime() {
|
||||||
|
return valueTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueTime(Date valueTime) {
|
||||||
|
this.valueTime = valueTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SiteMonitorProjectPointMappingSaveRequest {
|
||||||
|
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
private List<SiteMonitorProjectPointMappingVo> mappings;
|
||||||
|
|
||||||
|
private List<String> deletedFieldCodes;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SiteMonitorProjectPointMappingVo> getMappings() {
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(List<SiteMonitorProjectPointMappingVo> mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getDeletedFieldCodes() {
|
||||||
|
return deletedFieldCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeletedFieldCodes(List<String> deletedFieldCodes) {
|
||||||
|
this.deletedFieldCodes = deletedFieldCodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class SiteMonitorProjectPointMappingVo {
|
||||||
|
|
||||||
|
private String moduleCode;
|
||||||
|
|
||||||
|
private String moduleName;
|
||||||
|
|
||||||
|
private String menuCode;
|
||||||
|
|
||||||
|
private String menuName;
|
||||||
|
|
||||||
|
private String sectionName;
|
||||||
|
|
||||||
|
private String fieldCode;
|
||||||
|
|
||||||
|
private String fieldName;
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
private String dataPoint;
|
||||||
|
|
||||||
|
private String fixedDataPoint;
|
||||||
|
|
||||||
|
private Integer useFixedDisplay;
|
||||||
|
|
||||||
|
public String getModuleCode() {
|
||||||
|
return moduleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModuleCode(String moduleCode) {
|
||||||
|
this.moduleCode = moduleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModuleName() {
|
||||||
|
return moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModuleName(String moduleName) {
|
||||||
|
this.moduleName = moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldCode() {
|
||||||
|
return fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenuCode() {
|
||||||
|
return menuCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMenuCode(String menuCode) {
|
||||||
|
this.menuCode = menuCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenuName() {
|
||||||
|
return menuName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMenuName(String menuName) {
|
||||||
|
this.menuName = menuName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSectionName() {
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSectionName(String sectionName) {
|
||||||
|
this.sectionName = sectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldCode(String fieldCode) {
|
||||||
|
this.fieldCode = fieldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldName() {
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldName(String fieldName) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataPoint() {
|
||||||
|
return dataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataPoint(String dataPoint) {
|
||||||
|
this.dataPoint = dataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceName() {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFixedDataPoint() {
|
||||||
|
return fixedDataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFixedDataPoint(String fixedDataPoint) {
|
||||||
|
this.fixedDataPoint = fixedDataPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getUseFixedDisplay() {
|
||||||
|
return useFixedDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseFixedDisplay(Integer useFixedDisplay) {
|
||||||
|
this.useFixedDisplay = useFixedDisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class WeatherSyncResultVo {
|
||||||
|
private String siteId;
|
||||||
|
private String startTime;
|
||||||
|
private String endTime;
|
||||||
|
private int totalDays;
|
||||||
|
private int successDays;
|
||||||
|
private int insertedDays;
|
||||||
|
private int updatedDays;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(String startTime) {
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEndTime() {
|
||||||
|
return endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndTime(String endTime) {
|
||||||
|
this.endTime = endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalDays() {
|
||||||
|
return totalDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalDays(int totalDays) {
|
||||||
|
this.totalDays = totalDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSuccessDays() {
|
||||||
|
return successDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuccessDays(int successDays) {
|
||||||
|
this.successDays = successDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInsertedDays() {
|
||||||
|
return insertedDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInsertedDays(int insertedDays) {
|
||||||
|
this.insertedDays = insertedDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUpdatedDays() {
|
||||||
|
return updatedDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedDays(int updatedDays) {
|
||||||
|
this.updatedDays = updatedDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WorkStatusEnumMappingSaveRequest {
|
||||||
|
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
|
private List<WorkStatusEnumMappingVo> mappings;
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WorkStatusEnumMappingVo> getMappings() {
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(List<WorkStatusEnumMappingVo> mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.xzzn.ems.domain.vo;
|
||||||
|
|
||||||
|
public class WorkStatusEnumMappingVo {
|
||||||
|
|
||||||
|
private String deviceCategory;
|
||||||
|
|
||||||
|
private String matchField;
|
||||||
|
|
||||||
|
private String matchFieldName;
|
||||||
|
|
||||||
|
private String enumCode;
|
||||||
|
|
||||||
|
private String enumName;
|
||||||
|
|
||||||
|
private String enumDesc;
|
||||||
|
|
||||||
|
private String dataEnumCode;
|
||||||
|
|
||||||
|
public String getEnumCode() {
|
||||||
|
return enumCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumCode(String enumCode) {
|
||||||
|
this.enumCode = enumCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnumName() {
|
||||||
|
return enumName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumName(String enumName) {
|
||||||
|
this.enumName = enumName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnumDesc() {
|
||||||
|
return enumDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumDesc(String enumDesc) {
|
||||||
|
this.enumDesc = enumDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataEnumCode() {
|
||||||
|
return dataEnumCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataEnumCode(String dataEnumCode) {
|
||||||
|
this.dataEnumCode = dataEnumCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceCategory() {
|
||||||
|
return deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceCategory(String deviceCategory) {
|
||||||
|
this.deviceCategory = deviceCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMatchField() {
|
||||||
|
return matchField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMatchField(String matchField) {
|
||||||
|
this.matchField = matchField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMatchFieldName() {
|
||||||
|
return matchFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMatchFieldName(String matchFieldName) {
|
||||||
|
this.matchFieldName = matchFieldName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -93,4 +93,6 @@ public interface EmsBatteryStackMapper
|
|||||||
public List<BatteryAveTempVo> getBatteryAveTempList(@Param("siteId")String siteId, @Param("startDate")Date yesterday, @Param("endDate") Date today);
|
public List<BatteryAveTempVo> getBatteryAveTempList(@Param("siteId")String siteId, @Param("startDate")Date yesterday, @Param("endDate") Date today);
|
||||||
|
|
||||||
List<StackPointVo> getStackPointByMinute(DateSearchRequest requestVo);
|
List<StackPointVo> getStackPointByMinute(DateSearchRequest requestVo);
|
||||||
|
|
||||||
|
List<StackStatisListVo> getStackDataByMinute(DateSearchRequest requestVo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,17 @@ public interface EmsDailyChargeDataMapper
|
|||||||
// 插入或更新站点每日充放电数据
|
// 插入或更新站点每日充放电数据
|
||||||
public void insertOrUpdateData(EmsDailyChargeData emsDailyChargeData);
|
public void insertOrUpdateData(EmsDailyChargeData emsDailyChargeData);
|
||||||
|
|
||||||
|
// 按站点+日期(天)查询当日已存在记录
|
||||||
|
public EmsDailyChargeData selectBySiteIdAndDateTime(@Param("siteId") String siteId,
|
||||||
|
@Param("dateTime") Date dateTime);
|
||||||
|
|
||||||
|
// 按站点+日期(天)更新收入字段
|
||||||
|
public int updateRevenueBySiteAndDate(@Param("siteId") String siteId,
|
||||||
|
@Param("dateTime") Date dateTime,
|
||||||
|
@Param("totalRevenue") BigDecimal totalRevenue,
|
||||||
|
@Param("dayRevenue") BigDecimal dayRevenue,
|
||||||
|
@Param("updateBy") String updateBy);
|
||||||
|
|
||||||
// 获取所有站点总充总放
|
// 获取所有站点总充总放
|
||||||
public Map<String, BigDecimal> getAllSiteChargeData(@Param("nowData")String nowData, @Param("siteId")String siteId);
|
public Map<String, BigDecimal> getAllSiteChargeData(@Param("nowData")String nowData, @Param("siteId")String siteId);
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,12 @@ public interface EmsDailyEnergyDataMapper
|
|||||||
|
|
||||||
// 获取站点某日电表数据
|
// 获取站点某日电表数据
|
||||||
public EmsDailyEnergyData getDataByDate(@Param("siteId")String siteId,@Param("today") String today);
|
public EmsDailyEnergyData getDataByDate(@Param("siteId")String siteId,@Param("today") String today);
|
||||||
|
|
||||||
|
// 按站点+日期+小时查询当小时已存在记录
|
||||||
|
public EmsDailyEnergyData selectBySiteIdAndDateHour(@Param("siteId") String siteId,
|
||||||
|
@Param("dataDate") java.util.Date dataDate,
|
||||||
|
@Param("dataHour") Integer dataHour);
|
||||||
|
|
||||||
// 插入或更新每日尖峰平谷差值
|
// 插入或更新每日尖峰平谷差值
|
||||||
public void insertOrUpdateData(EmsDailyEnergyData energyData);
|
public void insertOrUpdateData(EmsDailyEnergyData energyData);
|
||||||
// 电表报表
|
// 电表报表
|
||||||
|
|||||||
@ -136,6 +136,8 @@ public interface EmsPcsDataMapper
|
|||||||
|
|
||||||
public List<PcsStatisListVo> getPcsActivePowerByMonth(DateSearchRequest requestVo);
|
public List<PcsStatisListVo> getPcsActivePowerByMonth(DateSearchRequest requestVo);
|
||||||
|
|
||||||
|
public List<PcsStatisListVo> getPcsActivePowerByMinutes(DateSearchRequest requestVo);
|
||||||
|
|
||||||
// 实时运行-fx-pcs最高温度
|
// 实时运行-fx-pcs最高温度
|
||||||
public List<PcsMaxTempVo> getFXMaxTemp(@Param("siteId")String siteId, @Param("startDate")Date startDate, @Param("endDate")Date endDate);
|
public List<PcsMaxTempVo> getFXMaxTemp(@Param("siteId")String siteId, @Param("startDate")Date startDate, @Param("endDate")Date endDate);
|
||||||
// 实时运行-dds-pcs最高温度
|
// 实时运行-dds-pcs最高温度
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsPointCalcConfig;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface EmsPointCalcConfigMapper {
|
||||||
|
EmsPointCalcConfig selectEmsPointCalcConfigById(Long id);
|
||||||
|
|
||||||
|
List<EmsPointCalcConfig> selectEmsPointCalcConfigList(EmsPointCalcConfig emsPointCalcConfig);
|
||||||
|
|
||||||
|
int insertEmsPointCalcConfig(EmsPointCalcConfig emsPointCalcConfig);
|
||||||
|
|
||||||
|
int updateEmsPointCalcConfig(EmsPointCalcConfig emsPointCalcConfig);
|
||||||
|
|
||||||
|
int deleteEmsPointCalcConfigById(Long id);
|
||||||
|
|
||||||
|
int deleteEmsPointCalcConfigByIds(Long[] ids);
|
||||||
|
|
||||||
|
int countBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteId(@Param("siteId") String siteId);
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsPointConfig;
|
||||||
|
import com.xzzn.ems.domain.vo.GeneralQueryPointOptionVo;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface EmsPointConfigMapper {
|
||||||
|
EmsPointConfig selectEmsPointConfigById(Long id);
|
||||||
|
|
||||||
|
List<EmsPointConfig> selectEmsPointConfigList(EmsPointConfig emsPointConfig);
|
||||||
|
|
||||||
|
int insertEmsPointConfig(EmsPointConfig emsPointConfig);
|
||||||
|
|
||||||
|
int insertBatchEmsPointConfig(@Param("list") List<EmsPointConfig> list);
|
||||||
|
|
||||||
|
int updateEmsPointConfig(EmsPointConfig emsPointConfig);
|
||||||
|
|
||||||
|
int updateEmsPointConfigForImport(EmsPointConfig emsPointConfig);
|
||||||
|
|
||||||
|
int deleteEmsPointConfigById(Long id);
|
||||||
|
|
||||||
|
int deleteEmsPointConfigByIds(Long[] ids);
|
||||||
|
|
||||||
|
int countBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int copyTemplateToSite(@Param("templateSiteId") String templateSiteId,
|
||||||
|
@Param("targetSiteId") String targetSiteId,
|
||||||
|
@Param("operName") String operName);
|
||||||
|
|
||||||
|
String getRegisterAddress(@Param("siteId") String siteId,
|
||||||
|
@Param("deviceCategory") String deviceCategory,
|
||||||
|
@Param("deviceId") String deviceId,
|
||||||
|
@Param("dataKey") String dataKey);
|
||||||
|
|
||||||
|
List<GeneralQueryPointOptionVo> getPointNameList(@Param("siteIds") List<String> siteIds,
|
||||||
|
@Param("deviceCategory") String deviceCategory,
|
||||||
|
@Param("deviceId") String deviceId,
|
||||||
|
@Param("pointName") String pointName);
|
||||||
|
|
||||||
|
List<EmsPointConfig> getConfigListForGeneralQuery(@Param("siteIds") List<String> siteIds,
|
||||||
|
@Param("deviceCategory") String deviceCategory,
|
||||||
|
@Param("pointIds") List<String> pointIds,
|
||||||
|
@Param("pointNames") List<String> pointNames,
|
||||||
|
@Param("deviceIds") List<String> deviceIds);
|
||||||
|
|
||||||
|
List<EmsPointConfig> selectBySiteIdAndPointIds(@Param("siteId") String siteId,
|
||||||
|
@Param("pointIds") List<String> pointIds);
|
||||||
|
|
||||||
|
List<EmsPointConfig> selectModbusCollectPointConfigs(@Param("siteId") String siteId);
|
||||||
|
}
|
||||||
@ -67,4 +67,16 @@ public interface EmsPointEnumMatchMapper
|
|||||||
public List<EmsPointEnumMatch> selectList(@Param("siteId") String siteId,
|
public List<EmsPointEnumMatch> selectList(@Param("siteId") String siteId,
|
||||||
@Param("deviceCategory") String deviceCategory,
|
@Param("deviceCategory") String deviceCategory,
|
||||||
@Param("matchField") String matchField);
|
@Param("matchField") String matchField);
|
||||||
|
|
||||||
|
int countBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int copyTemplateToSite(@Param("templateSiteId") String templateSiteId,
|
||||||
|
@Param("targetSiteId") String targetSiteId,
|
||||||
|
@Param("operName") String operName);
|
||||||
|
|
||||||
|
int deleteByScope(@Param("siteId") String siteId,
|
||||||
|
@Param("deviceCategory") String deviceCategory,
|
||||||
|
@Param("matchField") String matchField);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,8 @@ public interface EmsPointMatchMapper
|
|||||||
|
|
||||||
// 获取匹配信息
|
// 获取匹配信息
|
||||||
public List<EmsPointMatch> getMatchInfo(@Param("siteIds") List<String> siteIds,
|
public List<EmsPointMatch> getMatchInfo(@Param("siteIds") List<String> siteIds,
|
||||||
@Param("deviceCategory")String deviceCategory,
|
@Param("deviceId") String deviceId,
|
||||||
|
@Param("deviceCategory") String deviceCategory,
|
||||||
@Param("pointName") String pointName);
|
@Param("pointName") String pointName);
|
||||||
// 根据条件查询数据-按分钟-单体电池特殊处理
|
// 根据条件查询数据-按分钟-单体电池特殊处理
|
||||||
public List<GeneralQueryDataVo> getBatteryPointDataByMinutes(@Param("siteIds")List<String> siteIds,
|
public List<GeneralQueryDataVo> getBatteryPointDataByMinutes(@Param("siteIds")List<String> siteIds,
|
||||||
@ -172,4 +173,14 @@ public interface EmsPointMatchMapper
|
|||||||
int getDevicePointAlarmNum(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory);
|
int getDevicePointAlarmNum(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory);
|
||||||
|
|
||||||
List<EmsPointMatch> selectDeviceStatusPoint(@Param("request") DeviceUpdateRequest request);
|
List<EmsPointMatch> selectDeviceStatusPoint(@Param("request") DeviceUpdateRequest request);
|
||||||
|
|
||||||
|
int countBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int copyTemplateToSite(@Param("templateSiteId") String templateSiteId,
|
||||||
|
@Param("targetSiteId") String targetSiteId,
|
||||||
|
@Param("operName") String operName);
|
||||||
|
|
||||||
|
List<EmsPointMatch> selectBySiteId(@Param("siteId") String siteId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控展示数据 Mapper
|
||||||
|
*/
|
||||||
|
public interface EmsSiteMonitorDataMapper {
|
||||||
|
String selectHistoryJsonByMinute(@Param("tableName") String tableName,
|
||||||
|
@Param("siteId") String siteId,
|
||||||
|
@Param("statisMinute") java.util.Date statisMinute);
|
||||||
|
|
||||||
|
int upsertHistoryJsonByMinute(@Param("tableName") String tableName,
|
||||||
|
@Param("siteId") String siteId,
|
||||||
|
@Param("statisMinute") java.util.Date statisMinute,
|
||||||
|
@Param("dataJson") String dataJson,
|
||||||
|
@Param("hotSoc") String hotSoc,
|
||||||
|
@Param("hotTotalActivePower") String hotTotalActivePower,
|
||||||
|
@Param("hotTotalReactivePower") String hotTotalReactivePower,
|
||||||
|
@Param("hotDayChargedCap") String hotDayChargedCap,
|
||||||
|
@Param("hotDayDisChargedCap") String hotDayDisChargedCap,
|
||||||
|
@Param("operName") String operName);
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsSiteMonitorItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控配置项定义 Mapper
|
||||||
|
*/
|
||||||
|
public interface EmsSiteMonitorItemMapper {
|
||||||
|
List<EmsSiteMonitorItem> selectEnabledList();
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsSiteMonitorPointMatch;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单站监控字段点位映射 Mapper
|
||||||
|
*/
|
||||||
|
public interface EmsSiteMonitorPointMatchMapper {
|
||||||
|
List<String> selectDistinctSiteIds();
|
||||||
|
|
||||||
|
List<EmsSiteMonitorPointMatch> selectBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteId(@Param("siteId") String siteId);
|
||||||
|
|
||||||
|
int deleteBySiteIdAndDeviceId(@Param("siteId") String siteId, @Param("deviceId") String deviceId);
|
||||||
|
|
||||||
|
int insertBatch(@Param("list") List<EmsSiteMonitorPointMatch> list);
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
public interface EmsSiteWeatherDayMapper {
|
||||||
|
|
||||||
|
int updateWeatherDesc(@Param("siteId") String siteId,
|
||||||
|
@Param("calendarDate") String calendarDate,
|
||||||
|
@Param("weatherDesc") String weatherDesc,
|
||||||
|
@Param("weatherCode") Integer weatherCode);
|
||||||
|
|
||||||
|
int selectCountBySiteAndDate(@Param("siteId") String siteId, @Param("calendarDate") String calendarDate);
|
||||||
|
|
||||||
|
int insertSiteWeatherDay(@Param("siteId") String siteId,
|
||||||
|
@Param("calendarDate") String calendarDate,
|
||||||
|
@Param("weatherDesc") String weatherDesc,
|
||||||
|
@Param("weatherCode") Integer weatherCode,
|
||||||
|
@Param("source") String source);
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.xzzn.ems.mapper;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略运行参数配置Mapper接口
|
||||||
|
*
|
||||||
|
* @author xzzn
|
||||||
|
* @date 2026-02-13
|
||||||
|
*/
|
||||||
|
public interface EmsStrategyRuntimeConfigMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据站点ID查询参数配置
|
||||||
|
*
|
||||||
|
* @param siteId 站点ID
|
||||||
|
* @return 参数配置
|
||||||
|
*/
|
||||||
|
EmsStrategyRuntimeConfig selectBySiteId(String siteId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增参数配置
|
||||||
|
*
|
||||||
|
* @param config 参数配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int insert(EmsStrategyRuntimeConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按站点ID更新参数配置
|
||||||
|
*
|
||||||
|
* @param config 参数配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int updateBySiteId(EmsStrategyRuntimeConfig config);
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
package com.xzzn.ems.service;
|
|
||||||
|
|
||||||
public interface IDDSDataProcessService {
|
|
||||||
|
|
||||||
public void handleDdsData(String message);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -77,6 +77,15 @@ public interface IEmsAlarmRecordsService
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String createTicketNo(Long id, Long userId);
|
public String createTicketNo(Long id, Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭告警并设置为已处理
|
||||||
|
*
|
||||||
|
* @param id 告警ID
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
public String closeAlarm(Long id, Long userId);
|
||||||
// 订阅失败-增加告警
|
// 订阅失败-增加告警
|
||||||
public void addSubFailedAlarmRecord(String topic);
|
public void addSubFailedAlarmRecord(String topic);
|
||||||
// 订阅成功-处理告警
|
// 订阅成功-处理告警
|
||||||
@ -103,4 +112,6 @@ public interface IEmsAlarmRecordsService
|
|||||||
public void dealSyncData(String content, String operateType);
|
public void dealSyncData(String content, String operateType);
|
||||||
|
|
||||||
public void addDeviceOfflineRecord(String siteId, String deviceNumber);
|
public void addDeviceOfflineRecord(String siteId, String deviceNumber);
|
||||||
|
|
||||||
|
public void deleteDeviceOfflineRecord(String siteId, String deviceNumber);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsDailyChargeData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点每日充放电数据Service接口
|
||||||
|
*/
|
||||||
|
public interface IEmsDailyChargeDataService {
|
||||||
|
|
||||||
|
List<EmsDailyChargeData> selectEmsDailyChargeDataList(EmsDailyChargeData emsDailyChargeData);
|
||||||
|
|
||||||
|
EmsDailyChargeData selectEmsDailyChargeDataById(Long id);
|
||||||
|
|
||||||
|
int insertEmsDailyChargeData(EmsDailyChargeData emsDailyChargeData, String operName);
|
||||||
|
|
||||||
|
int updateEmsDailyChargeData(EmsDailyChargeData emsDailyChargeData, String operName);
|
||||||
|
|
||||||
|
int deleteEmsDailyChargeDataByIds(Long[] ids);
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsDailyEnergyData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点每日收益数据Service接口
|
||||||
|
*/
|
||||||
|
public interface IEmsDailyEnergyDataService {
|
||||||
|
|
||||||
|
List<EmsDailyEnergyData> selectEmsDailyEnergyDataList(EmsDailyEnergyData emsDailyEnergyData);
|
||||||
|
|
||||||
|
EmsDailyEnergyData selectEmsDailyEnergyDataById(Long id);
|
||||||
|
|
||||||
|
int insertEmsDailyEnergyData(EmsDailyEnergyData emsDailyEnergyData, String operName);
|
||||||
|
|
||||||
|
int updateEmsDailyEnergyData(EmsDailyEnergyData emsDailyEnergyData, String operName);
|
||||||
|
|
||||||
|
int deleteEmsDailyEnergyDataByIds(Long[] ids);
|
||||||
|
}
|
||||||
@ -6,7 +6,13 @@ import com.xzzn.ems.domain.vo.DeviceUpdateRequest;
|
|||||||
import com.xzzn.ems.domain.vo.DevicesSettingVo;
|
import com.xzzn.ems.domain.vo.DevicesSettingVo;
|
||||||
import com.xzzn.ems.domain.vo.PointDataRequest;
|
import com.xzzn.ems.domain.vo.PointDataRequest;
|
||||||
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorDataSaveRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorProjectDisplayVo;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingVo;
|
||||||
|
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingVo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -36,4 +42,18 @@ public interface IEmsDeviceSettingService
|
|||||||
public List<Map<String, Object>> getDeviceListBySiteAndCategory(String siteId, String deviceCategory);
|
public List<Map<String, Object>> getDeviceListBySiteAndCategory(String siteId, String deviceCategory);
|
||||||
|
|
||||||
public boolean updateDeviceStatus(DeviceUpdateRequest request);
|
public boolean updateDeviceStatus(DeviceUpdateRequest request);
|
||||||
|
|
||||||
|
public List<SiteMonitorProjectPointMappingVo> getSiteMonitorProjectPointMapping(String siteId);
|
||||||
|
|
||||||
|
public int saveSiteMonitorProjectPointMapping(SiteMonitorProjectPointMappingSaveRequest request, String operName);
|
||||||
|
|
||||||
|
public List<WorkStatusEnumMappingVo> getSiteWorkStatusEnumMappings(String siteId);
|
||||||
|
|
||||||
|
public int saveSiteWorkStatusEnumMappings(String siteId, List<WorkStatusEnumMappingVo> mappings, String operName);
|
||||||
|
|
||||||
|
public List<SiteMonitorProjectDisplayVo> getSiteMonitorProjectDisplay(String siteId);
|
||||||
|
|
||||||
|
public int saveSiteMonitorProjectData(SiteMonitorDataSaveRequest request, String operName);
|
||||||
|
|
||||||
|
public int syncSiteMonitorDataByMqtt(String siteId, String deviceId, String jsonData, Date valueTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsPointCalcConfig;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IEmsPointCalcConfigService {
|
||||||
|
List<EmsPointCalcConfig> selectPointCalcConfigList(EmsPointCalcConfig pointCalcConfig);
|
||||||
|
|
||||||
|
EmsPointCalcConfig selectPointCalcConfigById(Long id);
|
||||||
|
|
||||||
|
int insertPointCalcConfig(EmsPointCalcConfig pointCalcConfig, String operName);
|
||||||
|
|
||||||
|
int updatePointCalcConfig(EmsPointCalcConfig pointCalcConfig, String operName);
|
||||||
|
|
||||||
|
int deletePointCalcConfigByIds(Long[] ids);
|
||||||
|
|
||||||
|
int deleteBySiteId(String siteId);
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsPointConfig;
|
||||||
|
import com.xzzn.ems.domain.vo.ImportPointTemplateRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigCurveRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigCurveValueVo;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigGenerateRecentRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigLatestValueRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.PointConfigLatestValueVo;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IEmsPointConfigService {
|
||||||
|
List<EmsPointConfig> selectPointConfigList(EmsPointConfig pointConfig);
|
||||||
|
|
||||||
|
EmsPointConfig selectPointConfigById(Long id);
|
||||||
|
|
||||||
|
int insertPointConfig(EmsPointConfig pointConfig, String operName);
|
||||||
|
|
||||||
|
int updatePointConfig(EmsPointConfig pointConfig, String operName);
|
||||||
|
|
||||||
|
int deletePointConfigByIds(Long[] ids);
|
||||||
|
|
||||||
|
String importTemplateBySite(ImportPointTemplateRequest request, String operName);
|
||||||
|
|
||||||
|
String importCsvBySite(String siteId, Boolean overwrite, MultipartFile file, String operName);
|
||||||
|
|
||||||
|
String getRegisterAddress(String siteId, String deviceCategory, String deviceId, String dataKey);
|
||||||
|
|
||||||
|
List<PointConfigLatestValueVo> getLatestValues(PointConfigLatestValueRequest request);
|
||||||
|
|
||||||
|
List<PointConfigCurveValueVo> getCurveData(PointConfigCurveRequest request);
|
||||||
|
|
||||||
|
String generateRecent7DaysData(PointConfigGenerateRecentRequest request);
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import com.xzzn.ems.domain.EmsPointMatch;
|
|||||||
import com.xzzn.ems.domain.vo.DevicePointMatchExportVo;
|
import com.xzzn.ems.domain.vo.DevicePointMatchExportVo;
|
||||||
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
|
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
|
||||||
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
|
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.ImportPointTemplateRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 点位匹配Service接口
|
* 点位匹配Service接口
|
||||||
@ -40,4 +41,52 @@ public interface IEmsPointMatchService
|
|||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public List<DevicePointMatchVo> importDataByDevice(ImportPointDataRequest request, String operName);
|
public List<DevicePointMatchVo> importDataByDevice(ImportPointDataRequest request, String operName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按站点导入模板点位数据
|
||||||
|
* @param request 请求参数
|
||||||
|
* @param operName 操作人
|
||||||
|
* @return 导入结果信息
|
||||||
|
*/
|
||||||
|
public String importTemplateBySite(ImportPointTemplateRequest request, String operName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询点位配置列表
|
||||||
|
*
|
||||||
|
* @param emsPointMatch 点位配置
|
||||||
|
* @return 点位配置列表
|
||||||
|
*/
|
||||||
|
public List<EmsPointMatch> selectPointMatchConfigList(EmsPointMatch emsPointMatch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询点位配置详情
|
||||||
|
*
|
||||||
|
* @param id 主键ID
|
||||||
|
* @return 点位配置
|
||||||
|
*/
|
||||||
|
public EmsPointMatch selectPointMatchById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增点位配置
|
||||||
|
*
|
||||||
|
* @param emsPointMatch 点位配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int insertPointMatch(EmsPointMatch emsPointMatch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改点位配置
|
||||||
|
*
|
||||||
|
* @param emsPointMatch 点位配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updatePointMatch(EmsPointMatch emsPointMatch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除点位配置
|
||||||
|
*
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deletePointMatchByIds(Long[] ids);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,4 +32,8 @@ public interface IEmsSiteService
|
|||||||
public List<Map<String,Object>> getAllPcsInfo(String siteId);
|
public List<Map<String,Object>> getAllPcsInfo(String siteId);
|
||||||
|
|
||||||
public List<Map<String,Object>> getParentCategoryDeviceId(String siteId, String deviceCategory);
|
public List<Map<String,Object>> getParentCategoryDeviceId(String siteId, String deviceCategory);
|
||||||
|
|
||||||
|
int addSite(EmsSiteSetting emsSiteSetting);
|
||||||
|
|
||||||
|
int updateSite(EmsSiteSetting emsSiteSetting);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import com.xzzn.ems.domain.vo.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计报表数据Service接口
|
* 统计报表数据Service接口
|
||||||
*
|
*
|
||||||
@ -31,4 +33,8 @@ public interface IEmsStatsReportService
|
|||||||
public List<PowerStatisListVo> getPowerDataList(DateSearchRequest requestVo);
|
public List<PowerStatisListVo> getPowerDataList(DateSearchRequest requestVo);
|
||||||
|
|
||||||
public List<BatteryDataStatsListVo> getSingleBatteryData(DateSearchRequest requestVo);
|
public List<BatteryDataStatsListVo> getSingleBatteryData(DateSearchRequest requestVo);
|
||||||
|
|
||||||
|
void exportAmmeterData(HttpServletResponse response, StatisAmmeterDateRequest requestVo);
|
||||||
|
|
||||||
|
void exportAmmeterRevenueData(HttpServletResponse response, StatisAmmeterDateRequest requestVo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略运行参数配置Service接口
|
||||||
|
*
|
||||||
|
* @author xzzn
|
||||||
|
* @date 2026-02-13
|
||||||
|
*/
|
||||||
|
public interface IEmsStrategyRuntimeConfigService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按站点ID获取参数配置(不存在时返回默认值)
|
||||||
|
*
|
||||||
|
* @param siteId 站点ID
|
||||||
|
* @return 参数配置
|
||||||
|
*/
|
||||||
|
EmsStrategyRuntimeConfig getBySiteId(String siteId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存参数配置(按siteId新增或更新)
|
||||||
|
*
|
||||||
|
* @param config 参数配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int saveBySiteId(EmsStrategyRuntimeConfig config);
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.xzzn.ems.domain.vo.StatisAmmeterDateRequest;
|
||||||
|
import com.xzzn.ems.domain.vo.WeatherSyncResultVo;
|
||||||
|
|
||||||
|
public interface IEmsWeatherSyncService {
|
||||||
|
WeatherSyncResultVo syncWeatherByDateRange(StatisAmmeterDateRequest requestVo);
|
||||||
|
}
|
||||||
@ -1,6 +0,0 @@
|
|||||||
package com.xzzn.ems.service;
|
|
||||||
|
|
||||||
public interface IFXXDataProcessService {
|
|
||||||
|
|
||||||
public void handleFxData(String message);
|
|
||||||
}
|
|
||||||
@ -13,7 +13,7 @@ public interface IGeneralQueryService
|
|||||||
{
|
{
|
||||||
|
|
||||||
// 模糊查询获取点位名称List
|
// 模糊查询获取点位名称List
|
||||||
public List<String> getPointNameList(PointNameRequest request);
|
public List<GeneralQueryPointOptionVo> getPointNameList(PointNameRequest request);
|
||||||
|
|
||||||
// 根据条件获取点位数据变化
|
// 根据条件获取点位数据变化
|
||||||
public List<GeneralQueryResponse> getPointValueList(PointNameRequest request);
|
public List<GeneralQueryResponse> getPointValueList(PointNameRequest request);
|
||||||
|
|||||||
@ -13,6 +13,8 @@ public interface ISingleSiteService
|
|||||||
|
|
||||||
public SiteMonitorHomeVo getSiteMonitorDataVo(String siteId);
|
public SiteMonitorHomeVo getSiteMonitorDataVo(String siteId);
|
||||||
|
|
||||||
|
public SiteMonitorHomeVo getSiteMonitorTotalDataVo(String siteId);
|
||||||
|
|
||||||
|
|
||||||
public SiteMonitorRunningHeadInfoVo getSiteRunningHeadInfo(String siteId);
|
public SiteMonitorRunningHeadInfoVo getSiteRunningHeadInfo(String siteId);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,697 @@
|
|||||||
|
package com.xzzn.ems.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class InfluxPointDataWriter {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(InfluxPointDataWriter.class);
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
@Value("${influxdb.enabled:true}")
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
@Value("${influxdb.url:}")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Value("${influxdb.username:}")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Value("${influxdb.password:}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Value("${influxdb.api-token:}")
|
||||||
|
private String apiToken;
|
||||||
|
|
||||||
|
@Value("${influxdb.database:ems_point_data}")
|
||||||
|
private String database;
|
||||||
|
|
||||||
|
@Value("${influxdb.retention-policy:autogen}")
|
||||||
|
private String retentionPolicy;
|
||||||
|
|
||||||
|
@Value("${influxdb.measurement:mqtt_point_data}")
|
||||||
|
private String measurement;
|
||||||
|
|
||||||
|
@Value("${influxdb.write-method:POST}")
|
||||||
|
private String writeMethod;
|
||||||
|
|
||||||
|
@Value("${influxdb.read-method:GET}")
|
||||||
|
private String readMethod;
|
||||||
|
|
||||||
|
@Value("${influxdb.write-path:/write}")
|
||||||
|
private String writePath;
|
||||||
|
|
||||||
|
@Value("${influxdb.query-path:/query}")
|
||||||
|
private String queryPath;
|
||||||
|
|
||||||
|
@Value("${influxdb.org:}")
|
||||||
|
private String org;
|
||||||
|
|
||||||
|
@Value("${influxdb.bucket:}")
|
||||||
|
private String bucket;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
if (!enabled) {
|
||||||
|
log.info("InfluxDB 写入已禁用");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (url == null || url.trim().isEmpty()) {
|
||||||
|
log.warn("InfluxDB URL 未配置,跳过初始化");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("InfluxDB 已启用 HTTP 接入, url: {}, database: {}", url, database);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBatch(List<PointWritePayload> payloads) {
|
||||||
|
if (!enabled || payloads == null || payloads.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
StringBuilder body = new StringBuilder();
|
||||||
|
for (PointWritePayload payload : payloads) {
|
||||||
|
if (payload == null || payload.getPointValue() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long time = payload.getDataTime() == null ? System.currentTimeMillis() : payload.getDataTime().getTime();
|
||||||
|
body.append(measurement)
|
||||||
|
.append(",site_id=").append(escapeLineTag(payload.getSiteId()))
|
||||||
|
.append(",device_id=").append(escapeLineTag(payload.getDeviceId()))
|
||||||
|
.append(",point_key=").append(escapeLineTag(payload.getPointKey()))
|
||||||
|
.append(" value=").append(payload.getPointValue().toPlainString())
|
||||||
|
.append(" ").append(time)
|
||||||
|
.append("\n");
|
||||||
|
}
|
||||||
|
if (body.length() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String writeUrl = buildWriteUrl();
|
||||||
|
if (isBlank(writeUrl)) {
|
||||||
|
log.warn("写入 InfluxDB 失败:v2 写入地址未构建成功,请检查 influxdb.org / influxdb.bucket 配置");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HttpResult result = executeRequest(methodOrDefault(writeMethod, "POST"), writeUrl, body.toString());
|
||||||
|
if (result.code < 200 || result.code >= 300) {
|
||||||
|
if (result.code == 404 && isV2WritePath() && isOrgOrBucketMissing(result.body)) {
|
||||||
|
if (ensureV2OrgAndBucket()) {
|
||||||
|
HttpResult retryResult = executeRequest(methodOrDefault(writeMethod, "POST"), writeUrl, body.toString());
|
||||||
|
if (retryResult.code >= 200 && retryResult.code < 300) {
|
||||||
|
log.info("InfluxDB org/bucket 自动创建成功,写入已恢复");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.warn("InfluxDB 重试写入失败,HTTP状态码: {}, url: {}, body: {}", retryResult.code, writeUrl, safeLog(retryResult.body));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.warn("写入 InfluxDB 失败,HTTP状态码: {}, url: {}, body: {}", result.code, writeUrl, safeLog(result.body));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("写入 InfluxDB 失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PointValue> queryCurveData(String siteId, String deviceId, String pointKey, Date startTime, Date endTime) {
|
||||||
|
if (!enabled) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (isBlank(siteId) || isBlank(deviceId) || isBlank(pointKey) || startTime == null || endTime == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedSiteId = siteId.trim();
|
||||||
|
String normalizedDeviceId = deviceId.trim();
|
||||||
|
String normalizedPointKey = pointKey.trim();
|
||||||
|
|
||||||
|
String influxQl = String.format(
|
||||||
|
"SELECT \"value\" FROM \"%s\" WHERE \"site_id\" = '%s' AND \"device_id\" = '%s' AND \"point_key\" = '%s' " +
|
||||||
|
"AND time >= %dms AND time <= %dms ORDER BY time ASC",
|
||||||
|
measurement,
|
||||||
|
escapeTagValue(normalizedSiteId),
|
||||||
|
escapeTagValue(normalizedDeviceId),
|
||||||
|
escapeTagValue(normalizedPointKey),
|
||||||
|
startTime.getTime(),
|
||||||
|
endTime.getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String queryUrl = buildQueryUrl(influxQl);
|
||||||
|
List<PointValue> values = parseInfluxQlResponse(executeRequestWithResponse(methodOrDefault(readMethod, "GET"), queryUrl));
|
||||||
|
if (!values.isEmpty()) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容 dataKey 大小写差异,避免点位 key 字母大小写不一致导致查不到曲线
|
||||||
|
String regexQuery = String.format(
|
||||||
|
"SELECT \"value\" FROM \"%s\" WHERE \"site_id\" = '%s' AND \"device_id\" = '%s' AND \"point_key\" =~ /(?i)^%s$/ " +
|
||||||
|
"AND time >= %dms AND time <= %dms ORDER BY time ASC",
|
||||||
|
measurement,
|
||||||
|
escapeTagValue(normalizedSiteId),
|
||||||
|
escapeTagValue(normalizedDeviceId),
|
||||||
|
escapeRegex(normalizedPointKey),
|
||||||
|
startTime.getTime(),
|
||||||
|
endTime.getTime()
|
||||||
|
);
|
||||||
|
values = parseInfluxQlResponse(executeRequestWithResponse(methodOrDefault(readMethod, "GET"), buildQueryUrl(regexQuery)));
|
||||||
|
return values;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("查询 InfluxDB 曲线失败: {}", e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PointValue> queryCurveDataByPointKey(String siteId, String pointKey, Date startTime, Date endTime) {
|
||||||
|
if (!enabled) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (isBlank(siteId) || isBlank(pointKey) || startTime == null || endTime == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedSiteId = siteId.trim();
|
||||||
|
String normalizedPointKey = pointKey.trim();
|
||||||
|
|
||||||
|
String influxQl = String.format(
|
||||||
|
"SELECT \"value\" FROM \"%s\" WHERE \"site_id\" = '%s' AND \"point_key\" = '%s' " +
|
||||||
|
"AND time >= %dms AND time <= %dms ORDER BY time ASC",
|
||||||
|
measurement,
|
||||||
|
escapeTagValue(normalizedSiteId),
|
||||||
|
escapeTagValue(normalizedPointKey),
|
||||||
|
startTime.getTime(),
|
||||||
|
endTime.getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String queryUrl = buildQueryUrl(influxQl);
|
||||||
|
return parseInfluxQlResponse(executeRequestWithResponse(methodOrDefault(readMethod, "GET"), queryUrl));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("按 pointKey 查询 InfluxDB 曲线失败: {}", e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PointValue queryLatestPointValueByPointKey(String siteId, String pointKey, Date startTime, Date endTime) {
|
||||||
|
if (!enabled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isBlank(siteId) || isBlank(pointKey) || startTime == null || endTime == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedSiteId = siteId.trim();
|
||||||
|
String normalizedPointKey = pointKey.trim();
|
||||||
|
|
||||||
|
String influxQl = String.format(
|
||||||
|
"SELECT \"value\" FROM \"%s\" WHERE \"site_id\" = '%s' AND \"point_key\" = '%s' " +
|
||||||
|
"AND time >= %dms AND time <= %dms ORDER BY time DESC LIMIT 1",
|
||||||
|
measurement,
|
||||||
|
escapeTagValue(normalizedSiteId),
|
||||||
|
escapeTagValue(normalizedPointKey),
|
||||||
|
startTime.getTime(),
|
||||||
|
endTime.getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<PointValue> values = parseInfluxQlResponse(
|
||||||
|
executeRequestWithResponse(methodOrDefault(readMethod, "GET"), buildQueryUrl(influxQl))
|
||||||
|
);
|
||||||
|
if (!values.isEmpty()) {
|
||||||
|
return values.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
String regexQuery = String.format(
|
||||||
|
"SELECT \"value\" FROM \"%s\" WHERE \"site_id\" = '%s' AND \"point_key\" =~ /(?i)^%s$/ " +
|
||||||
|
"AND time >= %dms AND time <= %dms ORDER BY time DESC LIMIT 1",
|
||||||
|
measurement,
|
||||||
|
escapeTagValue(normalizedSiteId),
|
||||||
|
escapeRegex(normalizedPointKey),
|
||||||
|
startTime.getTime(),
|
||||||
|
endTime.getTime()
|
||||||
|
);
|
||||||
|
values = parseInfluxQlResponse(
|
||||||
|
executeRequestWithResponse(methodOrDefault(readMethod, "GET"), buildQueryUrl(regexQuery))
|
||||||
|
);
|
||||||
|
return values.isEmpty() ? null : values.get(0);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("按 pointKey 查询 InfluxDB 最新值失败: {}", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildWriteUrl() {
|
||||||
|
if (isV2WritePath()) {
|
||||||
|
return buildV2WriteUrl();
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder(trimTrailingSlash(url));
|
||||||
|
sb.append(normalizePath(writePath)).append("?db=").append(urlEncode(database));
|
||||||
|
if (!isBlank(retentionPolicy)) {
|
||||||
|
sb.append("&rp=").append(urlEncode(retentionPolicy));
|
||||||
|
}
|
||||||
|
sb.append("&precision=ms");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildQueryUrl(String influxQl) {
|
||||||
|
String queryDb = database;
|
||||||
|
if (isV2WritePath() && !isBlank(bucket)) {
|
||||||
|
queryDb = bucket;
|
||||||
|
}
|
||||||
|
StringBuilder queryUrl = new StringBuilder(trimTrailingSlash(url))
|
||||||
|
.append(normalizePath(queryPath))
|
||||||
|
.append("?db=").append(urlEncode(queryDb))
|
||||||
|
.append("&epoch=ms&q=").append(urlEncode(influxQl));
|
||||||
|
if (!isBlank(retentionPolicy)) {
|
||||||
|
queryUrl.append("&rp=").append(urlEncode(retentionPolicy));
|
||||||
|
}
|
||||||
|
return queryUrl.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildV2WriteUrl() {
|
||||||
|
String currentBucket = isBlank(bucket) ? database : bucket;
|
||||||
|
if (isBlank(org) || isBlank(currentBucket)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return trimTrailingSlash(url)
|
||||||
|
+ "/api/v2/write?org=" + urlEncode(org)
|
||||||
|
+ "&bucket=" + urlEncode(currentBucket)
|
||||||
|
+ "&precision=ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpResult executeRequest(String method, String requestUrl, String body) throws Exception {
|
||||||
|
HttpURLConnection connection = openConnection(method, requestUrl, "text/plain; charset=UTF-8");
|
||||||
|
try {
|
||||||
|
if (body != null) {
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
try (OutputStream os = connection.getOutputStream()) {
|
||||||
|
os.write(body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int code = connection.getResponseCode();
|
||||||
|
InputStream is = (code >= 200 && code < 300) ? connection.getInputStream() : connection.getErrorStream();
|
||||||
|
return new HttpResult(code, readStream(is));
|
||||||
|
} finally {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String executeRequestWithResponse(String method, String requestUrl) throws Exception {
|
||||||
|
HttpURLConnection connection = openConnection(method, requestUrl, "text/plain; charset=UTF-8");
|
||||||
|
try {
|
||||||
|
int code = connection.getResponseCode();
|
||||||
|
InputStream is = (code >= 200 && code < 300) ? connection.getInputStream() : connection.getErrorStream();
|
||||||
|
return readStream(is);
|
||||||
|
} finally {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readStream(InputStream is) throws Exception {
|
||||||
|
if (is == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpResult executeJsonRequest(String method, String requestUrl, String jsonBody) throws Exception {
|
||||||
|
HttpURLConnection connection = openConnection(method, requestUrl, "application/json; charset=UTF-8");
|
||||||
|
try {
|
||||||
|
if (jsonBody != null) {
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
try (OutputStream os = connection.getOutputStream()) {
|
||||||
|
os.write(jsonBody.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int code = connection.getResponseCode();
|
||||||
|
InputStream is = (code >= 200 && code < 300) ? connection.getInputStream() : connection.getErrorStream();
|
||||||
|
return new HttpResult(code, readStream(is));
|
||||||
|
} finally {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpURLConnection openConnection(String method, String requestUrl, String contentType) throws Exception {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new java.net.URL(requestUrl).openConnection();
|
||||||
|
connection.setRequestMethod(method);
|
||||||
|
connection.setConnectTimeout(5000);
|
||||||
|
connection.setReadTimeout(8000);
|
||||||
|
connection.setRequestProperty("Accept", "application/json");
|
||||||
|
connection.setRequestProperty("Content-Type", contentType);
|
||||||
|
if (!isBlank(apiToken)) {
|
||||||
|
connection.setRequestProperty("Authorization", "Token " + apiToken.trim());
|
||||||
|
} else if (!isBlank(username) || !isBlank(password)) {
|
||||||
|
String basic = java.util.Base64.getEncoder()
|
||||||
|
.encodeToString((safe(username) + ":" + safe(password)).getBytes(StandardCharsets.UTF_8));
|
||||||
|
connection.setRequestProperty("Authorization", "Basic " + basic);
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escapeLineTag(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return value.replace("\\", "\\\\")
|
||||||
|
.replace(",", "\\,")
|
||||||
|
.replace(" ", "\\ ")
|
||||||
|
.replace("=", "\\=");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimTrailingSlash(String v) {
|
||||||
|
if (v == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String result = v.trim();
|
||||||
|
while (result.endsWith("/")) {
|
||||||
|
result = result.substring(0, result.length() - 1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String urlEncode(String value) {
|
||||||
|
try {
|
||||||
|
return URLEncoder.encode(safe(value), StandardCharsets.UTF_8.name());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return safe(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String safe(String value) {
|
||||||
|
return value == null ? "" : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isV2WritePath() {
|
||||||
|
return "/api/v2/write".equals(normalizePath(writePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOrgOrBucketMissing(String responseBody) {
|
||||||
|
if (isBlank(responseBody)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String lower = responseBody.toLowerCase();
|
||||||
|
return (lower.contains("organization") && lower.contains("not found"))
|
||||||
|
|| (lower.contains("bucket") && lower.contains("not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean ensureV2OrgAndBucket() {
|
||||||
|
try {
|
||||||
|
if (isBlank(org)) {
|
||||||
|
log.warn("InfluxDB 自动创建 organization 失败:org 配置为空");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String currentBucket = isBlank(bucket) ? database : bucket;
|
||||||
|
String orgId = queryOrgId(org);
|
||||||
|
if (isBlank(orgId)) {
|
||||||
|
orgId = createOrg(org);
|
||||||
|
}
|
||||||
|
if (isBlank(orgId)) {
|
||||||
|
log.warn("InfluxDB 自动创建 organization 失败,org={}", org);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bucketExists(org, currentBucket)) {
|
||||||
|
if (!createBucket(orgId, currentBucket)) {
|
||||||
|
log.warn("InfluxDB 自动创建 bucket 失败,org={}, bucket={}", org, currentBucket);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("InfluxDB 自动创建 org/bucket 异常: {}", ex.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String queryOrgId(String orgName) throws Exception {
|
||||||
|
String requestUrl = trimTrailingSlash(url) + "/api/v2/orgs?org=" + urlEncode(orgName);
|
||||||
|
HttpResult result = executeJsonRequest("GET", requestUrl, null);
|
||||||
|
if (result.code < 200 || result.code >= 300 || isBlank(result.body)) {
|
||||||
|
log.warn("查询 organization 失败,status={}, org={}, body={}", result.code, orgName, safeLog(result.body));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonNode root = OBJECT_MAPPER.readTree(result.body);
|
||||||
|
JsonNode orgs = root.path("orgs");
|
||||||
|
if (orgs.isArray() && orgs.size() > 0) {
|
||||||
|
JsonNode first = orgs.get(0);
|
||||||
|
if (first != null) {
|
||||||
|
String id = first.path("id").asText(null);
|
||||||
|
if (!isBlank(id)) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createOrg(String orgName) throws Exception {
|
||||||
|
String requestUrl = trimTrailingSlash(url) + "/api/v2/orgs";
|
||||||
|
Map<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("name", orgName);
|
||||||
|
String body = OBJECT_MAPPER.writeValueAsString(payload);
|
||||||
|
HttpResult result = executeJsonRequest("POST", requestUrl, body);
|
||||||
|
if ((result.code < 200 || result.code >= 300) || isBlank(result.body)) {
|
||||||
|
log.warn("创建 organization 失败,status={}, org={}, body={}", result.code, orgName, safeLog(result.body));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonNode root = OBJECT_MAPPER.readTree(result.body);
|
||||||
|
String id = root.path("id").asText(null);
|
||||||
|
return isBlank(id) ? null : id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean bucketExists(String orgName, String bucketName) throws Exception {
|
||||||
|
String requestUrl = trimTrailingSlash(url)
|
||||||
|
+ "/api/v2/buckets?name=" + urlEncode(bucketName)
|
||||||
|
+ "&org=" + urlEncode(orgName);
|
||||||
|
HttpResult result = executeJsonRequest("GET", requestUrl, null);
|
||||||
|
if (result.code < 200 || result.code >= 300 || isBlank(result.body)) {
|
||||||
|
log.warn("查询 bucket 失败,status={}, org={}, bucket={}, body={}", result.code, orgName, bucketName, safeLog(result.body));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JsonNode root = OBJECT_MAPPER.readTree(result.body);
|
||||||
|
JsonNode buckets = root.path("buckets");
|
||||||
|
return buckets.isArray() && buckets.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean createBucket(String orgId, String bucketName) throws Exception {
|
||||||
|
String requestUrl = trimTrailingSlash(url) + "/api/v2/buckets";
|
||||||
|
Map<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("orgID", orgId);
|
||||||
|
payload.put("name", bucketName);
|
||||||
|
String body = OBJECT_MAPPER.writeValueAsString(payload);
|
||||||
|
HttpResult result = executeJsonRequest("POST", requestUrl, body);
|
||||||
|
if (result.code < 200 || result.code >= 300) {
|
||||||
|
log.warn("创建 bucket 失败,status={}, orgId={}, bucket={}, body={}", result.code, orgId, bucketName, safeLog(result.body));
|
||||||
|
}
|
||||||
|
return result.code >= 200 && result.code < 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String methodOrDefault(String method, String defaultMethod) {
|
||||||
|
return isBlank(method) ? defaultMethod : method.trim().toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizePath(String path) {
|
||||||
|
if (isBlank(path)) {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
String p = path.trim();
|
||||||
|
return p.startsWith("/") ? p : "/" + p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String safeLog(String body) {
|
||||||
|
if (body == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return body.length() > 200 ? body.substring(0, 200) : body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date parseInfluxTime(Object timeObject) {
|
||||||
|
if (timeObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (timeObject instanceof Number) {
|
||||||
|
return new Date(((Number) timeObject).longValue());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Date.from(Instant.parse(String.valueOf(timeObject)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal toBigDecimal(Object valueObject) {
|
||||||
|
if (valueObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (valueObject instanceof BigDecimal) {
|
||||||
|
return (BigDecimal) valueObject;
|
||||||
|
}
|
||||||
|
if (valueObject instanceof Number) {
|
||||||
|
return new BigDecimal(valueObject.toString());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(String.valueOf(valueObject));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escapeTagValue(String value) {
|
||||||
|
return value == null ? "" : value.replace("\\", "\\\\").replace("'", "\\'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String escapeRegex(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return value.replace("\\", "\\\\")
|
||||||
|
.replace("/", "\\/")
|
||||||
|
.replace(".", "\\.")
|
||||||
|
.replace("(", "\\(")
|
||||||
|
.replace(")", "\\)")
|
||||||
|
.replace("[", "\\[")
|
||||||
|
.replace("]", "\\]")
|
||||||
|
.replace("{", "\\{")
|
||||||
|
.replace("}", "\\}")
|
||||||
|
.replace("^", "\\^")
|
||||||
|
.replace("$", "\\$")
|
||||||
|
.replace("*", "\\*")
|
||||||
|
.replace("+", "\\+")
|
||||||
|
.replace("?", "\\?")
|
||||||
|
.replace("|", "\\|");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PointValue> parseInfluxQlResponse(String response) throws Exception {
|
||||||
|
if (isBlank(response)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<PointValue> values = new ArrayList<>();
|
||||||
|
JsonNode root = OBJECT_MAPPER.readTree(response);
|
||||||
|
JsonNode resultsNode = root.path("results");
|
||||||
|
if (!resultsNode.isArray()) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JsonNode result : resultsNode) {
|
||||||
|
JsonNode seriesArray = result.path("series");
|
||||||
|
if (!seriesArray.isArray()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (JsonNode series : seriesArray) {
|
||||||
|
JsonNode rows = series.path("values");
|
||||||
|
if (!rows.isArray()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (JsonNode row : rows) {
|
||||||
|
if (!row.isArray() || row.size() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Date dataTime = parseInfluxTime(row.get(0).isNumber() ? row.get(0).asLong() : row.get(0).asText());
|
||||||
|
BigDecimal pointValue = toBigDecimal(row.get(1).isNumber() ? row.get(1).asText() : row.get(1).asText(null));
|
||||||
|
if (dataTime == null || pointValue == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
values.add(new PointValue(dataTime, pointValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isBlank(String value) {
|
||||||
|
return value == null || value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PointWritePayload {
|
||||||
|
private final String siteId;
|
||||||
|
private final String deviceId;
|
||||||
|
private final String pointKey;
|
||||||
|
private final BigDecimal pointValue;
|
||||||
|
private final Date dataTime;
|
||||||
|
|
||||||
|
public PointWritePayload(String siteId, String deviceId, String pointKey, BigDecimal pointValue, Date dataTime) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.pointKey = pointKey;
|
||||||
|
this.pointValue = pointValue;
|
||||||
|
this.dataTime = dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteId() {
|
||||||
|
return siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPointKey() {
|
||||||
|
return pointKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPointValue() {
|
||||||
|
return pointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDataTime() {
|
||||||
|
return dataTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PointValue {
|
||||||
|
private final Date dataTime;
|
||||||
|
private final BigDecimal pointValue;
|
||||||
|
|
||||||
|
public PointValue(Date dataTime, BigDecimal pointValue) {
|
||||||
|
this.dataTime = dataTime;
|
||||||
|
this.pointValue = pointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDataTime() {
|
||||||
|
return dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getPointValue() {
|
||||||
|
return pointValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HttpResult {
|
||||||
|
private final int code;
|
||||||
|
private final String body;
|
||||||
|
|
||||||
|
private HttpResult(int code, String body) {
|
||||||
|
this.code = code;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -174,6 +174,27 @@ public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
|
|||||||
return ticketNo;
|
return ticketNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String closeAlarm(Long id, Long userId) {
|
||||||
|
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.selectEmsAlarmRecordsById(id);
|
||||||
|
if (emsAlarmRecords == null) {
|
||||||
|
return "告警记录不存在";
|
||||||
|
}
|
||||||
|
if (AlarmStatus.DONE.getCode().equals(emsAlarmRecords.getStatus())) {
|
||||||
|
return "告警已关闭";
|
||||||
|
}
|
||||||
|
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
||||||
|
emsAlarmRecords.setAlarmEndTime(DateUtils.getNowDate());
|
||||||
|
emsAlarmRecords.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
if (userId == null) {
|
||||||
|
userId = 1L;
|
||||||
|
}
|
||||||
|
SysUser user = sysUserMapper.selectUserById(userId);
|
||||||
|
emsAlarmRecords.setUpdateBy(user != null ? user.getUserName() : "system");
|
||||||
|
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
// 订阅失败-增加告警
|
// 订阅失败-增加告警
|
||||||
@Override
|
@Override
|
||||||
public void addSubFailedAlarmRecord(String topic) {
|
public void addSubFailedAlarmRecord(String topic) {
|
||||||
@ -227,7 +248,8 @@ public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addEmptyDataAlarmRecord(String siteId, String topicDevice) {
|
public void addEmptyDataAlarmRecord(String siteId, String topicDevice) {
|
||||||
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(RedisKeyConstants.TOPIC_EMPTY_ALARM_RECORD + siteId + "_" + topicDevice);
|
String key = getRedisKeyForTopicEmptyAlarm(siteId, topicDevice);
|
||||||
|
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
|
||||||
if (emsAlarmRecords != null) {
|
if (emsAlarmRecords != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -235,7 +257,7 @@ public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
|
|||||||
emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);
|
emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);
|
||||||
|
|
||||||
// 存redis-防止重复插入-有效期一天
|
// 存redis-防止重复插入-有效期一天
|
||||||
redisCache.setCacheObject(RedisKeyConstants.TOPIC_EMPTY_ALARM_RECORD + siteId + "_" + topicDevice, emsAlarmRecords,1, TimeUnit.DAYS);
|
redisCache.setCacheObject(key, emsAlarmRecords,1, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmsAlarmRecords createAlarmAtPcs(String siteId, String deviceId,String content,String level) {
|
private EmsAlarmRecords createAlarmAtPcs(String siteId, String deviceId,String content,String level) {
|
||||||
@ -254,7 +276,7 @@ public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteEmptyDataAlarmRecord(String siteId, String topicDevice) {
|
public void deleteEmptyDataAlarmRecord(String siteId, String topicDevice) {
|
||||||
String key = RedisKeyConstants.TOPIC_EMPTY_ALARM_RECORD + siteId + "_" + topicDevice;
|
String key = getRedisKeyForTopicEmptyAlarm(siteId, topicDevice);
|
||||||
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
|
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
|
||||||
if (emsAlarmRecords == null) {
|
if (emsAlarmRecords == null) {
|
||||||
return;
|
return;
|
||||||
@ -330,16 +352,41 @@ public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDeviceOfflineRecord(String siteId, String deviceId) {
|
public void addDeviceOfflineRecord(String siteId, String deviceId) {
|
||||||
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(RedisKeyConstants.MODBUS_OFFLINE_ALARM_RECORD + siteId + "_" + deviceId);
|
String key = getRedisKeyForModbusFailAlarm(siteId, deviceId);
|
||||||
|
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
|
||||||
if (emsAlarmRecords != null) {
|
if (emsAlarmRecords != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emsAlarmRecords = createAlarmAtPcs(siteId, deviceId,"modbus连接设备失败", AlarmLevelStatus.EMERGENCY.getCode());
|
emsAlarmRecords = createAlarmAtPcs(siteId, deviceId,"modbus连接设备失败", AlarmLevelStatus.GENERAL.getCode());
|
||||||
emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);
|
emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);
|
||||||
|
|
||||||
// 存redis-防止重复插入-有效期一天
|
// 存redis-防止重复插入-有效期一天
|
||||||
redisCache.setCacheObject(RedisKeyConstants.MODBUS_OFFLINE_ALARM_RECORD + siteId + "_" + deviceId, emsAlarmRecords,1, TimeUnit.DAYS);
|
redisCache.setCacheObject(key, emsAlarmRecords,1, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDeviceOfflineRecord(String siteId, String deviceId) {
|
||||||
|
String key = getRedisKeyForModbusFailAlarm(siteId, deviceId);
|
||||||
|
EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
|
||||||
|
if (emsAlarmRecords == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
||||||
|
emsAlarmRecords.setUpdateTime(new Date());
|
||||||
|
emsAlarmRecords.setAlarmEndTime(new Date());
|
||||||
|
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
||||||
|
|
||||||
|
redisCache.deleteObject(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRedisKeyForTopicEmptyAlarm(String siteId, String topicDevice) {
|
||||||
|
|
||||||
|
return RedisKeyConstants.TOPIC_EMPTY_ALARM_RECORD + siteId + "_" + topicDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRedisKeyForModbusFailAlarm(String siteId, String deviceId) {
|
||||||
|
|
||||||
|
return RedisKeyConstants.MODBUS_OFFLINE_ALARM_RECORD + siteId + "_" + deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.xzzn.ems.service.impl;
|
||||||
|
|
||||||
|
import com.xzzn.common.utils.DateUtils;
|
||||||
|
import com.xzzn.ems.domain.EmsDailyChargeData;
|
||||||
|
import com.xzzn.ems.mapper.EmsDailyChargeDataMapper;
|
||||||
|
import com.xzzn.ems.service.IEmsDailyChargeDataService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点每日充放电数据Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EmsDailyChargeDataServiceImpl implements IEmsDailyChargeDataService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmsDailyChargeDataMapper emsDailyChargeDataMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EmsDailyChargeData> selectEmsDailyChargeDataList(EmsDailyChargeData emsDailyChargeData) {
|
||||||
|
return emsDailyChargeDataMapper.selectEmsDailyChargeDataList(emsDailyChargeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmsDailyChargeData selectEmsDailyChargeDataById(Long id) {
|
||||||
|
return emsDailyChargeDataMapper.selectEmsDailyChargeDataById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int insertEmsDailyChargeData(EmsDailyChargeData emsDailyChargeData, String operName) {
|
||||||
|
emsDailyChargeData.setCreateBy(operName);
|
||||||
|
emsDailyChargeData.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return emsDailyChargeDataMapper.insertEmsDailyChargeData(emsDailyChargeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int updateEmsDailyChargeData(EmsDailyChargeData emsDailyChargeData, String operName) {
|
||||||
|
emsDailyChargeData.setUpdateBy(operName);
|
||||||
|
emsDailyChargeData.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return emsDailyChargeDataMapper.updateEmsDailyChargeData(emsDailyChargeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteEmsDailyChargeDataByIds(Long[] ids) {
|
||||||
|
return emsDailyChargeDataMapper.deleteEmsDailyChargeDataByIds(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.xzzn.ems.service.impl;
|
||||||
|
|
||||||
|
import com.xzzn.common.utils.DateUtils;
|
||||||
|
import com.xzzn.ems.domain.EmsDailyEnergyData;
|
||||||
|
import com.xzzn.ems.mapper.EmsDailyEnergyDataMapper;
|
||||||
|
import com.xzzn.ems.service.IEmsDailyEnergyDataService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点每日收益数据Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EmsDailyEnergyDataServiceImpl implements IEmsDailyEnergyDataService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmsDailyEnergyDataMapper emsDailyEnergyDataMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EmsDailyEnergyData> selectEmsDailyEnergyDataList(EmsDailyEnergyData emsDailyEnergyData) {
|
||||||
|
return emsDailyEnergyDataMapper.selectEmsDailyEnergyDataList(emsDailyEnergyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmsDailyEnergyData selectEmsDailyEnergyDataById(Long id) {
|
||||||
|
return emsDailyEnergyDataMapper.selectEmsDailyEnergyDataById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int insertEmsDailyEnergyData(EmsDailyEnergyData emsDailyEnergyData, String operName) {
|
||||||
|
emsDailyEnergyData.setCreateBy(operName);
|
||||||
|
emsDailyEnergyData.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return emsDailyEnergyDataMapper.insertEmsDailyEnergyData(emsDailyEnergyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int updateEmsDailyEnergyData(EmsDailyEnergyData emsDailyEnergyData, String operName) {
|
||||||
|
emsDailyEnergyData.setUpdateBy(operName);
|
||||||
|
emsDailyEnergyData.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return emsDailyEnergyDataMapper.updateEmsDailyEnergyData(emsDailyEnergyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteEmsDailyEnergyDataByIds(Long[] ids) {
|
||||||
|
return emsDailyEnergyDataMapper.deleteEmsDailyEnergyDataByIds(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user