Compare commits
15 Commits
21673ecd1e
...
waibao
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b3be8636f | |||
| 5eb9b455a5 | |||
| 4947f085c7 | |||
| 5460aadf6c | |||
| 79a8040446 | |||
| ed36292c94 | |||
| 515f440298 | |||
| e4cfd15cb4 | |||
| 5ab2cb8f90 | |||
| 4e7d387edf | |||
| 49ed5f218a | |||
| 8806473080 | |||
| 71d0b0f609 | |||
| 6253fb6b2d | |||
| 5d5a7137fc |
@ -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));
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ 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;
|
||||
@ -93,4 +94,10 @@ public class EmsPointConfigController extends BaseController {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,20 +8,21 @@ import com.xzzn.common.core.page.TableDataInfo;
|
||||
import com.xzzn.common.enums.BusinessType;
|
||||
import com.xzzn.common.utils.file.FileUploadUtils;
|
||||
import com.xzzn.common.utils.file.MimeTypeUtils;
|
||||
import com.xzzn.common.utils.poi.ExcelUtil;
|
||||
import com.xzzn.ems.domain.EmsSiteSetting;
|
||||
import com.xzzn.ems.domain.vo.DeviceUpdateRequest;
|
||||
import com.xzzn.ems.domain.vo.DevicesSettingVo;
|
||||
import com.xzzn.ems.domain.vo.PointDataRequest;
|
||||
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SiteDeviceListVo;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo;
|
||||
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingSaveRequest;
|
||||
import com.xzzn.ems.service.IEmsDeviceSettingService;
|
||||
import com.xzzn.ems.service.IEmsSiteService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@ -34,14 +35,17 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 站点配置
|
||||
*
|
||||
* 绔欑偣閰嶇疆
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/ems/siteConfig")
|
||||
public class EmsSiteConfigController extends BaseController{
|
||||
public class EmsSiteConfigController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IEmsSiteService iEmsSiteService;
|
||||
@ -49,197 +53,169 @@ public class EmsSiteConfigController extends BaseController{
|
||||
@Autowired
|
||||
private IEmsDeviceSettingService iEmsDeviceSettingService;
|
||||
|
||||
/**
|
||||
* 获取站点列表
|
||||
*/
|
||||
@GetMapping("/getSiteInfoList")
|
||||
public TableDataInfo getSiteInfoList(@RequestParam String siteName, @RequestParam String startTime, @RequestParam String endTime)
|
||||
{
|
||||
public TableDataInfo getSiteInfoList(@RequestParam String siteName, @RequestParam String startTime, @RequestParam String endTime) {
|
||||
startPage();
|
||||
List<EmsSiteSetting> list = iEmsSiteService.getAllSiteInfoList(siteName,startTime,endTime);
|
||||
List<EmsSiteSetting> list = iEmsSiteService.getAllSiteInfoList(siteName, startTime, endTime);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增站点
|
||||
*/
|
||||
@PostMapping("/addSite")
|
||||
public AjaxResult addSite(@RequestBody EmsSiteSetting emsSiteSetting)
|
||||
{
|
||||
public AjaxResult addSite(@RequestBody EmsSiteSetting emsSiteSetting) {
|
||||
emsSiteSetting.setCreateBy(getUsername());
|
||||
return toAjax(iEmsSiteService.addSite(emsSiteSetting));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑站点
|
||||
*/
|
||||
@PostMapping("/updateSite")
|
||||
public AjaxResult updateSite(@RequestBody EmsSiteSetting emsSiteSetting)
|
||||
{
|
||||
public AjaxResult updateSite(@RequestBody EmsSiteSetting emsSiteSetting) {
|
||||
emsSiteSetting.setUpdateBy(getUsername());
|
||||
return toAjax(iEmsSiteService.updateSite(emsSiteSetting));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备列表-分页
|
||||
*/
|
||||
@GetMapping("/getDeviceInfoList")
|
||||
public TableDataInfo getDeviceInfoList(@RequestParam(value = "siteId", required = false) String siteId,
|
||||
@RequestParam(value = "deviceCategory", required = false) String deviceCategory)
|
||||
{
|
||||
public TableDataInfo getDeviceInfoList(@RequestParam(value = "siteId", required = false) String siteId,
|
||||
@RequestParam(value = "deviceCategory", required = false) String deviceCategory) {
|
||||
startPage();
|
||||
List<SiteDeviceListVo> list = iEmsSiteService.getAllDeviceListNoDisp(siteId, deviceCategory);
|
||||
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备详细信息
|
||||
*/
|
||||
@GetMapping("/getDeviceDetailInfo")
|
||||
public AjaxResult getDeviceDetailInfo(@RequestParam Long id)
|
||||
{
|
||||
public AjaxResult getDeviceDetailInfo(@RequestParam Long id) {
|
||||
return success(iEmsDeviceSettingService.getDeviceDetailInfo(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备列表-不分页
|
||||
*/
|
||||
@GetMapping("/getDeviceList")
|
||||
public AjaxResult getDeviceInfoList2(@RequestParam String siteId)
|
||||
{
|
||||
public AjaxResult getDeviceInfoList2(@RequestParam String siteId) {
|
||||
return success(iEmsSiteService.getAllDeviceList(siteId, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有设备类别
|
||||
*/
|
||||
@GetMapping("/getDeviceCategory")
|
||||
public AjaxResult getDeviceCategory()
|
||||
{
|
||||
public AjaxResult getDeviceCategory() {
|
||||
return success(iEmsDeviceSettingService.getDeviceCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增设备
|
||||
*/
|
||||
@PostMapping("/addDevice")
|
||||
public AjaxResult addDevice(@RequestBody DevicesSettingVo devicesSetting)
|
||||
{
|
||||
public AjaxResult addDevice(@RequestBody DevicesSettingVo devicesSetting) {
|
||||
int result = iEmsDeviceSettingService.addDevice(devicesSetting);
|
||||
if (result > 0) {
|
||||
if (result > 0) {
|
||||
return AjaxResult.success(result);
|
||||
} else {
|
||||
return AjaxResult.error("该设备已存在");
|
||||
}
|
||||
return AjaxResult.error("璇ヨ澶囧凡瀛樺湪");
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传设备图片
|
||||
*/
|
||||
@PostMapping("/uploadDeviceImg")
|
||||
public AjaxResult uploadDeviceImg(@RequestParam("avatarfile") MultipartFile file) throws Exception
|
||||
{
|
||||
public AjaxResult uploadDeviceImg(@RequestParam("avatarfile") MultipartFile file) throws Exception {
|
||||
if (!file.isEmpty()) {
|
||||
String avatar = FileUploadUtils.upload(RuoYiConfig.getDevicePath(), file, MimeTypeUtils.IMAGE_EXTENSION);
|
||||
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("imgUrl", avatar);
|
||||
return ajax;
|
||||
}
|
||||
return error("上传图片异常,请联系管理员");
|
||||
return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛?");
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改Modbus设备配置
|
||||
*/
|
||||
@PostMapping("/updateDevice")
|
||||
public AjaxResult updateDevice(@RequestBody DevicesSettingVo emsDevicesSetting)
|
||||
{
|
||||
public AjaxResult updateDevice(@RequestBody DevicesSettingVo emsDevicesSetting) {
|
||||
int result = iEmsDeviceSettingService.updateDevice(emsDevicesSetting);
|
||||
if (result > 0) {
|
||||
if (result > 0) {
|
||||
return AjaxResult.success(result);
|
||||
} else if (result == -1) {
|
||||
return AjaxResult.error("数据不存在");
|
||||
} else if (result == -2) {
|
||||
return AjaxResult.error("该设备已存在");
|
||||
} else if (result == -1) {
|
||||
return AjaxResult.error("鏁版嵁涓嶅瓨鍦?");
|
||||
} else if (result == -2) {
|
||||
return AjaxResult.error("璇ヨ澶囧凡瀛樺湪");
|
||||
}
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Modbus设备配置
|
||||
*/
|
||||
@DeleteMapping("/deleteService/{id}")
|
||||
public AjaxResult deleteService(@PathVariable Long id)
|
||||
{
|
||||
public AjaxResult deleteService(@PathVariable Long id) {
|
||||
return toAjax(iEmsDeviceSettingService.deleteEmsDevicesSettingById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个站点单个设备点位查询-点位清单
|
||||
*/
|
||||
@GetMapping("/getDevicePointList")
|
||||
public TableDataInfo getDevicePointList(@Validated PointDataRequest request)
|
||||
{
|
||||
public TableDataInfo getDevicePointList(@Validated PointDataRequest request) {
|
||||
List<PointQueryResponse> result = iEmsDeviceSettingService.getSingleSiteDevicePoints(request);
|
||||
return getDataTable2(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定站点下的所有设备类别
|
||||
*/
|
||||
@GetMapping("/getSiteAllDeviceCategory")
|
||||
public AjaxResult getSiteAllDeviceCategory(String siteId)
|
||||
{
|
||||
public AjaxResult getSiteAllDeviceCategory(String siteId) {
|
||||
return success(iEmsDeviceSettingService.getSiteAllDeviceCategory(siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备类别获取父类的设备id
|
||||
*/
|
||||
@GetMapping("/getParentDeviceId")
|
||||
public AjaxResult getParentDeviceId(@RequestParam String siteId, @RequestParam String deviceCategory)
|
||||
{
|
||||
public AjaxResult getParentDeviceId(@RequestParam String siteId, @RequestParam String deviceCategory) {
|
||||
return success(iEmsSiteService.getParentCategoryDeviceId(siteId, deviceCategory));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定站点下的指定设备类型的设备
|
||||
*/
|
||||
@GetMapping("/getDeviceListBySiteAndCategory")
|
||||
public AjaxResult getDeviceListBySiteAndCategory(String siteId,String deviceCategory)
|
||||
{
|
||||
public AjaxResult getDeviceListBySiteAndCategory(String siteId, String deviceCategory) {
|
||||
return success(iEmsDeviceSettingService.getDeviceListBySiteAndCategory(siteId, deviceCategory));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单站监控项目点位映射
|
||||
*/
|
||||
@GetMapping("/getSingleMonitorProjectPointMapping")
|
||||
public AjaxResult getSingleMonitorProjectPointMapping(@RequestParam String siteId)
|
||||
{
|
||||
public AjaxResult getSingleMonitorProjectPointMapping(@RequestParam String siteId) {
|
||||
return success(iEmsDeviceSettingService.getSiteMonitorProjectPointMapping(siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存单站监控项目点位映射
|
||||
*/
|
||||
@PostMapping("/saveSingleMonitorProjectPointMapping")
|
||||
public AjaxResult saveSingleMonitorProjectPointMapping(@RequestBody SiteMonitorProjectPointMappingSaveRequest request)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@PostMapping("/saveSingleMonitorWorkStatusEnumMappings")
|
||||
public AjaxResult saveSingleMonitorWorkStatusEnumMappings(@RequestBody WorkStatusEnumMappingSaveRequest request) {
|
||||
int rows = iEmsDeviceSettingService.saveSiteWorkStatusEnumMappings(request.getSiteId(), request.getMappings(), getUsername());
|
||||
return AjaxResult.success(rows);
|
||||
}
|
||||
|
||||
@GetMapping("/downloadSingleBatteryMonitorImportTemplate")
|
||||
public void downloadSingleBatteryMonitorImportTemplate(HttpServletResponse response) {
|
||||
ExcelUtil<SingleBatteryMonitorImportRowVo> util = new ExcelUtil<>(SingleBatteryMonitorImportRowVo.class);
|
||||
util.importTemplateExcel(response, "单体电池导入模板", "单体电池导入模板");
|
||||
}
|
||||
|
||||
@PostMapping("/importSingleBatteryMonitorMappings")
|
||||
public AjaxResult importSingleBatteryMonitorMappings(@RequestParam("siteId") String siteId,
|
||||
@RequestParam("file") MultipartFile file) throws Exception {
|
||||
ExcelUtil<SingleBatteryMonitorImportRowVo> util = new ExcelUtil<>(SingleBatteryMonitorImportRowVo.class);
|
||||
List<SingleBatteryMonitorImportRowVo> rowList = util.importExcel(file.getInputStream(), 1);
|
||||
if (rowList == null) {
|
||||
return AjaxResult.error("导入失败:未读取到任何数据,请检查 Excel 文件内容");
|
||||
}
|
||||
List<SingleBatteryMonitorImportRowVo> validRowList = new ArrayList<>();
|
||||
for (int i = 0; i < rowList.size(); i++) {
|
||||
SingleBatteryMonitorImportRowVo row = rowList.get(i);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setRowNum(i + 3);
|
||||
validRowList.add(row);
|
||||
}
|
||||
if (validRowList.isEmpty()) {
|
||||
return AjaxResult.error("导入失败:未识别到有效数据,请使用系统导出的最新模板,并保持表头名称不变");
|
||||
}
|
||||
SingleBatteryMonitorImportResultVo result = iEmsDeviceSettingService.importSingleBatteryMonitorMappings(siteId, validRowList, getUsername());
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
@PostMapping("/initializeSingleBatteryMonitorMappings")
|
||||
public AjaxResult initializeSingleBatteryMonitorMappings(@RequestBody SingleBatteryConfigInitRequest request) {
|
||||
SingleBatteryConfigInitResultVo result = iEmsDeviceSettingService.initializeSingleBatteryMonitorMappings(request, getUsername());
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermi('system:device:onAndOff')")
|
||||
@Log(title = "开关机", businessType = BusinessType.UPDATE)
|
||||
@Log(title = "寮€鍏虫満", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/updateDeviceStatus")
|
||||
public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request)
|
||||
{
|
||||
public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request) {
|
||||
return success(iEmsDeviceSettingService.updateDeviceStatus(request));
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,10 +10,13 @@ import com.xzzn.ems.domain.vo.DateSearchRequest;
|
||||
import com.xzzn.ems.domain.vo.RunningGraphRequest;
|
||||
import com.xzzn.ems.domain.vo.SiteBatteryDataList;
|
||||
import com.xzzn.ems.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.IEmsStatsReportService;
|
||||
import com.xzzn.ems.service.ISingleSiteService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -28,6 +31,8 @@ import java.util.List;
|
||||
@RestController
|
||||
@RequestMapping("/ems/siteMonitor")
|
||||
public class EmsSiteMonitorController extends BaseController{
|
||||
private static final Logger log = LoggerFactory.getLogger(EmsSiteMonitorController.class);
|
||||
private static final String RUNNING_GRAPH_CTRL_DEBUG = "RunningGraphCtrlDebug";
|
||||
|
||||
@Autowired
|
||||
private ISingleSiteService iSingleSiteService;
|
||||
@ -47,6 +52,15 @@ public class EmsSiteMonitorController extends BaseController{
|
||||
return success(iSingleSiteService.getSiteMonitorDataVo(siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单站首页总累计运行数据(基于日表)
|
||||
*/
|
||||
@GetMapping("/homeTotalView")
|
||||
public AjaxResult getSingleSiteHomeTotalView(@RequestParam String siteId)
|
||||
{
|
||||
return success(iSingleSiteService.getSiteMonitorTotalDataVo(siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 单站监控-设备监控-实时运行头部数据
|
||||
*/
|
||||
@ -60,27 +74,75 @@ public class EmsSiteMonitorController extends BaseController{
|
||||
* 单站监控-设备监控-实时运行曲线图数据
|
||||
*/
|
||||
@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")
|
||||
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")
|
||||
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")
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,9 +217,7 @@ public class EmsSiteMonitorController extends BaseController{
|
||||
{
|
||||
startPage();
|
||||
SiteBatteryDataList siteBatteryDataList = new SiteBatteryDataList();
|
||||
// 簇最大最小单体id数据
|
||||
List<BMSBatteryDataList> clusterBatteryDataList = iSingleSiteService.getClusterBatteryList(siteId,stackDeviceId,clusterDeviceId);
|
||||
siteBatteryDataList.setClusterList(clusterBatteryDataList);
|
||||
|
||||
// 单体电池数据
|
||||
List<BatteryDataStatsListVo> List = iSingleSiteService.getClusterDataInfoList(clusterDeviceId,siteId,stackDeviceId,batteryId);
|
||||
// 对batteryList进行分页处理
|
||||
|
||||
@ -12,7 +12,9 @@ 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.IEmsWeatherSyncService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -38,6 +40,8 @@ public class EmsStatisticalReportController extends BaseController
|
||||
|
||||
@Autowired
|
||||
private IEmsStatsReportService ieEmsStatsReportService;
|
||||
@Autowired
|
||||
private IEmsWeatherSyncService iEmsWeatherSyncService;
|
||||
|
||||
/**
|
||||
* 概率统计-收益指标查询
|
||||
@ -130,6 +134,17 @@ public class EmsStatisticalReportController extends BaseController
|
||||
return getDataTable(dataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计报表-电表报表(直接基于 ems_daily_energy_data)
|
||||
*/
|
||||
@GetMapping("/getAmmeterDataFromDaily")
|
||||
public TableDataInfo getAmmeterDataFromDaily(StatisAmmeterDateRequest requestVo)
|
||||
{
|
||||
startPage();
|
||||
List<AmmeterStatisListVo> dataList = ieEmsStatsReportService.getAmmeterDataResult(requestVo);
|
||||
return getDataTable(dataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出电表报表
|
||||
*/
|
||||
@ -141,6 +156,17 @@ public class EmsStatisticalReportController extends BaseController
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 概率统计-电表收益报表
|
||||
*/
|
||||
@ -176,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,11 +6,7 @@ import com.xzzn.common.enums.TopicHandleType;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.EmsMqttTopicConfig;
|
||||
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
|
||||
import com.xzzn.ems.service.IDDSDataProcessService;
|
||||
import com.xzzn.ems.service.IDeviceDataProcessService;
|
||||
import com.xzzn.ems.service.IEmsStrategyService;
|
||||
import com.xzzn.ems.service.IFXXAlarmDataProcessService;
|
||||
import com.xzzn.ems.service.IFXXDataProcessService;
|
||||
import com.xzzn.ems.service.IMqttSyncLogService;
|
||||
import com.xzzn.framework.manager.MqttLifecycleManager;
|
||||
import com.xzzn.framework.web.service.MqttPublisher;
|
||||
@ -38,22 +34,13 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
||||
|
||||
private final MqttLifecycleManager mqttLifecycleManager;
|
||||
|
||||
@Autowired
|
||||
private IFXXDataProcessService fXXDataProcessService;
|
||||
|
||||
@Autowired
|
||||
private IDDSDataProcessService dDSDataProcessService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceDataProcessService deviceDataProcessService;
|
||||
|
||||
@Autowired
|
||||
private IFXXAlarmDataProcessService fXXAlarmDataProcessService;
|
||||
@Autowired
|
||||
private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
|
||||
@Autowired
|
||||
private IEmsStrategyService emsStrategyService;
|
||||
@Autowired
|
||||
private IMqttSyncLogService iMqttSyncLogService;
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
package com.xzzn.web.controller.system;
|
||||
|
||||
import com.xzzn.common.core.controller.BaseController;
|
||||
import com.xzzn.common.core.domain.AjaxResult;
|
||||
import com.xzzn.ems.domain.vo.BizRemarkBatchGetRequest;
|
||||
import com.xzzn.ems.domain.vo.BizRemarkSaveRequest;
|
||||
import com.xzzn.ems.service.ISysBizRemarkService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/system/bizRemark")
|
||||
public class SysBizRemarkController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private ISysBizRemarkService sysBizRemarkService;
|
||||
|
||||
@PostMapping("/batchGet")
|
||||
public AjaxResult batchGet(@RequestBody BizRemarkBatchGetRequest request)
|
||||
{
|
||||
return success(sysBizRemarkService.getRemarkMap(request.getBizType(), request.getBizKey1(), request.getBizKey2List()));
|
||||
}
|
||||
|
||||
@PostMapping("/save")
|
||||
public AjaxResult save(@RequestBody BizRemarkSaveRequest request)
|
||||
{
|
||||
return toAjax(sysBizRemarkService.saveRemark(request, getUsername()));
|
||||
}
|
||||
}
|
||||
@ -205,3 +205,10 @@ modbus:
|
||||
poll:
|
||||
interval: "0 */5 * * * *" # 5分钟间隔
|
||||
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:
|
||||
interval: "0 */5 * * * *" # 5分钟间隔
|
||||
timeout: 30000 # 30秒超时
|
||||
|
||||
weather:
|
||||
api:
|
||||
enabled: true
|
||||
base-url: https://archive-api.open-meteo.com/v1/archive
|
||||
api-key:
|
||||
timezone: Asia/Shanghai
|
||||
|
||||
@ -221,3 +221,10 @@ modbus:
|
||||
poll:
|
||||
interval: "0 */5 * * * *" # 5分钟间隔
|
||||
timeout: 30000 # 30秒超时
|
||||
|
||||
weather:
|
||||
api:
|
||||
enabled: true
|
||||
base-url: https://archive-api.open-meteo.com/v1/archive
|
||||
api-key:
|
||||
timezone: Asia/Shanghai
|
||||
|
||||
@ -103,6 +103,9 @@ public class RedisKeyConstants
|
||||
|
||||
/** 设备信息初始化 */
|
||||
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";
|
||||
|
||||
@ -126,6 +129,15 @@ public class RedisKeyConstants
|
||||
/** 点位配置缓存(按站点+设备) */
|
||||
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_";
|
||||
}
|
||||
|
||||
@ -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.JSONObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.serotonin.modbus4j.ModbusMaster;
|
||||
import com.xzzn.common.constant.RedisKeyConstants;
|
||||
import com.xzzn.common.core.modbus.ModbusProcessor;
|
||||
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
||||
import com.xzzn.common.core.modbus.domain.TagConfig;
|
||||
import com.xzzn.common.core.redis.RedisCache;
|
||||
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.EmsPointConfig;
|
||||
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsPointConfigMapper;
|
||||
import com.xzzn.ems.service.IEmsAlarmRecordsService;
|
||||
import com.xzzn.ems.service.impl.DeviceDataProcessServiceImpl;
|
||||
import com.xzzn.framework.manager.MqttLifecycleManager;
|
||||
import com.xzzn.framework.web.service.MqttPublisher;
|
||||
import com.xzzn.quartz.config.ScheduledTask;
|
||||
import com.xzzn.quartz.domain.SysJob;
|
||||
import com.xzzn.quartz.service.ISysJobService;
|
||||
import com.xzzn.quartz.util.CronUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -54,10 +48,8 @@ import org.springframework.util.CollectionUtils;
|
||||
@Component("modbusPoller")
|
||||
public class ModbusPoller {
|
||||
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 AtomicBoolean polling = new AtomicBoolean(false);
|
||||
|
||||
@ -69,77 +61,46 @@ public class ModbusPoller {
|
||||
@Autowired
|
||||
private IEmsAlarmRecordsService iEmsAlarmRecordsService;
|
||||
|
||||
@Autowired
|
||||
private ISysJobService iSysJobService;
|
||||
@Autowired
|
||||
private DeviceDataProcessServiceImpl deviceDataProcessServiceImpl;
|
||||
@Autowired
|
||||
private EmsDevicesSettingMapper emsDevicesSettingMapper;
|
||||
@Autowired
|
||||
private EmsPointConfigMapper emsPointConfigMapper;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@Autowired
|
||||
private MqttPublisher mqttPublisher;
|
||||
|
||||
@Value("${mqtt.topic}")
|
||||
private String topic;
|
||||
@Value("${mqtt.siteId}")
|
||||
private String siteId;
|
||||
|
||||
@Autowired
|
||||
public ModbusPoller(MqttLifecycleManager mqttLifecycleManager, ScheduledTask scheduledTask) {
|
||||
this.mqttLifecycleManager = mqttLifecycleManager;
|
||||
this.scheduledTask = scheduledTask;
|
||||
}
|
||||
|
||||
public void pollAllDevices() {
|
||||
if (!polling.compareAndSet(false, true)) {
|
||||
log.warn("上一次轮询尚未完成,本次轮询跳过");
|
||||
return;
|
||||
}
|
||||
Path devicesDir = Paths.get(System.getProperty("user.dir"), "devices");
|
||||
if (!Files.exists(devicesDir)) {
|
||||
log.error("Devices目录不存在: {}", devicesDir);
|
||||
List<PollingTask> pollingTasks = buildPollingTasks();
|
||||
if (CollectionUtils.isEmpty(pollingTasks)) {
|
||||
log.warn("未查询到可用的Modbus采集点位配置,跳过本轮轮询");
|
||||
polling.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Path> jsonFiles = null;
|
||||
try {
|
||||
jsonFiles = Files.list(devicesDir)
|
||||
.filter(path -> path.toString().endsWith(".json"))
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
log.error("modbusPoller.loadConfigs 获取设备配置文件失败: {}", devicesDir, e);
|
||||
polling.set(false);
|
||||
return;
|
||||
}
|
||||
// 按主机IP分组,同一网关串行访问,避免连接抖动
|
||||
Map<String, List<PollingTask>> groupedByHost = pollingTasks.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
task -> task.getDeviceConfig().getHost(),
|
||||
HashMap::new,
|
||||
Collectors.toList()));
|
||||
|
||||
// 按主机IP分组(同一网关的不同端口也归为一组,避免并发访问导致Connection Reset)
|
||||
Map<String, List<DeviceConfig>> groupedByHost = new HashMap<>();
|
||||
for (Path filePath : jsonFiles) {
|
||||
DeviceConfig config = null;
|
||||
try {
|
||||
config = objectMapper.readValue(filePath.toFile(), DeviceConfig.class);
|
||||
} catch (IOException e) {
|
||||
log.error("modbusPoller.loadConfigs 解析设备配置文件失败: {}", filePath, e);
|
||||
continue;
|
||||
}
|
||||
if (config.isEnabled()) {
|
||||
// 只按主机IP分组,确保同一网关的所有端口串行访问
|
||||
String hostKey = config.getHost();
|
||||
groupedByHost.computeIfAbsent(hostKey, k -> new ArrayList<>()).add(config);
|
||||
}
|
||||
}
|
||||
|
||||
// 使用单线程 executor 串行执行所有主机的 Modbus 操作
|
||||
// 将所有主机的设备按顺序串行处理,避免任何并发访问
|
||||
Future<?> future = modbusExecutor.submit(() -> {
|
||||
for (Map.Entry<String, List<DeviceConfig>> entry : groupedByHost.entrySet()) {
|
||||
for (Map.Entry<String, List<PollingTask>> entry : groupedByHost.entrySet()) {
|
||||
String hostKey = entry.getKey();
|
||||
List<DeviceConfig> configs = entry.getValue();
|
||||
for (DeviceConfig config : configs) {
|
||||
List<PollingTask> tasks = entry.getValue();
|
||||
for (PollingTask task : tasks) {
|
||||
try {
|
||||
scheduledStart(config);
|
||||
scheduledStart(task.getSiteId(), task.getDeviceConfig());
|
||||
// 每次读取后等待200ms,给Modbus网关足够的处理时间
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException ie) {
|
||||
@ -147,7 +108,8 @@ public class ModbusPoller {
|
||||
log.warn("Modbus轮询被中断");
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
log.error("采集设备数据异常: {}", config.getDeviceName(), e);
|
||||
log.error("采集设备数据异常: siteId={}, deviceId={}",
|
||||
task.getSiteId(), task.getDeviceConfig().getDeviceNumber(), e);
|
||||
}
|
||||
}
|
||||
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()) {
|
||||
log.info("Reading data from devices: {}", config.getDeviceName());
|
||||
|
||||
@ -205,7 +299,7 @@ public class ModbusPoller {
|
||||
log.info("Data from {}: {}", config.getDeviceName(), data);
|
||||
String deviceNumber = config.getDeviceNumber();
|
||||
//处理数据并发送MQTT消息、保存Redis数据和数据入库
|
||||
processingData(data, deviceNumber);
|
||||
processingData(siteId, data, deviceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,24 +348,25 @@ public class ModbusPoller {
|
||||
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)) {
|
||||
// 增加失败计数
|
||||
int failureCount = deviceFailureCounts.getOrDefault(deviceNumber, 0) + 1;
|
||||
deviceFailureCounts.put(deviceNumber, failureCount);
|
||||
int failureCount = deviceFailureCounts.getOrDefault(siteDeviceKey, 0) + 1;
|
||||
deviceFailureCounts.put(siteDeviceKey, failureCount);
|
||||
|
||||
log.warn("设备 {} 数据读取失败,当前连续失败次数: {}", deviceNumber, failureCount);
|
||||
log.warn("设备 {} 数据读取失败,当前连续失败次数: {}", siteDeviceKey, failureCount);
|
||||
|
||||
// 连续6次失败触发报警
|
||||
if (failureCount >= 6) {
|
||||
if (failureCount >= SITE_DEVICE_OFFLINE_THRESHOLD) {
|
||||
addDeviceOfflineRecord(siteId, deviceNumber);
|
||||
log.error("设备 {} 连续 {} 次未读取到数据,触发报警", deviceNumber, failureCount);
|
||||
log.error("设备 {} 连续 {} 次未读取到数据,触发报警", siteDeviceKey, failureCount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 数据读取成功,重置计数器
|
||||
deviceFailureCounts.remove(deviceNumber);
|
||||
deviceFailureCounts.remove(siteDeviceKey);
|
||||
// 读取到数据后告警自恢复
|
||||
deleteDeviceOfflineRecord(siteId, deviceNumber);
|
||||
|
||||
@ -281,9 +376,42 @@ public class ModbusPoller {
|
||||
json.put("Data", data);
|
||||
json.put("timestamp", timestamp);
|
||||
json.put("Device", deviceNumber);
|
||||
sendMqttMsg(json);
|
||||
saveRedisData(json, deviceNumber);
|
||||
saveDataToDatabase(data, deviceNumber, timestamp);
|
||||
if (shouldSendMqttOnChange(siteId, deviceNumber, data)) {
|
||||
sendMqttMsg(json);
|
||||
} else {
|
||||
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) {
|
||||
@ -296,7 +424,7 @@ public class ModbusPoller {
|
||||
}
|
||||
|
||||
|
||||
public void saveRedisData(JSONObject obj, String deviceNumber) {
|
||||
public void saveRedisData(String siteId, JSONObject obj, String deviceNumber) {
|
||||
try {
|
||||
// 存放mqtt原始每个设备最晚一次数据,便于后面点位获取数据
|
||||
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj);
|
||||
@ -308,8 +436,12 @@ public class ModbusPoller {
|
||||
}
|
||||
}
|
||||
|
||||
private void saveDataToDatabase(Map<String, Object> data, String deviceNumber, Long timestamp) {
|
||||
deviceDataProcessServiceImpl.processingDeviceData(siteId, deviceNumber, JSON.toJSONString(data), DateUtils.convertUpdateTime(timestamp));
|
||||
private void saveDataToDatabase(String siteId, Map<String, Object> data, String deviceNumber, Long 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);
|
||||
}
|
||||
|
||||
//处理设备连接失败的情况,更新设备状态为离线,添加报警记录
|
||||
@ -333,11 +465,22 @@ public class ModbusPoller {
|
||||
}
|
||||
}
|
||||
|
||||
private int getScheduledTaskInterval() {
|
||||
SysJob query = new SysJob();
|
||||
query.setInvokeTarget("modbusPoller.pollAllDevices");
|
||||
List<SysJob> sysJobs = iSysJobService.selectJobList(query);
|
||||
return Math.toIntExact(CronUtils.getNextExecutionIntervalMillis(sysJobs.get(0).getCronExpression()));
|
||||
private static class PollingTask {
|
||||
private final String siteId;
|
||||
private final DeviceConfig deviceConfig;
|
||||
|
||||
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.AlarmStatus;
|
||||
import com.xzzn.common.enums.ProtPlanStatus;
|
||||
import com.xzzn.common.enums.StrategyStatus;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.EmsAlarmRecords;
|
||||
import com.xzzn.ems.domain.EmsDevicesSetting;
|
||||
import com.xzzn.ems.domain.EmsFaultIssueLog;
|
||||
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
|
||||
import com.xzzn.ems.domain.EmsStrategyRunning;
|
||||
import com.xzzn.ems.domain.vo.ProtectionConstraintVo;
|
||||
import com.xzzn.ems.domain.vo.ProtectionPlanVo;
|
||||
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.EmsDevicesSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsFaultIssueLogMapper;
|
||||
import com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper;
|
||||
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
|
||||
import com.xzzn.ems.service.IEmsFaultProtectionPlanService;
|
||||
import com.xzzn.common.core.modbus.ModbusProcessor;
|
||||
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
||||
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -51,14 +27,29 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
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")
|
||||
public class ProtectionPlanTask {
|
||||
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")
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
@Autowired
|
||||
@ -66,18 +57,11 @@ public class ProtectionPlanTask {
|
||||
@Autowired
|
||||
private EmsAlarmRecordsMapper emsAlarmRecordsMapper;
|
||||
@Autowired
|
||||
private EmsStrategyRunningMapper emsStrategyRunningMapper;
|
||||
@Autowired
|
||||
private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
@Autowired
|
||||
private EmsDevicesSettingMapper emsDevicesSettingMapper;
|
||||
@Autowired
|
||||
private ModbusProcessor modbusProcessor;
|
||||
@Autowired
|
||||
private EmsFaultIssueLogMapper emsFaultIssueLogMapper;
|
||||
|
||||
public ProtectionPlanTask(IEmsFaultProtectionPlanService iEmsFaultProtectionPlanService) {
|
||||
this.iEmsFaultProtectionPlanService = iEmsFaultProtectionPlanService;
|
||||
@ -86,303 +70,456 @@ public class ProtectionPlanTask {
|
||||
public void pollPlanList() {
|
||||
Long planId = 0L;
|
||||
try {
|
||||
// 获取所有方案,轮询
|
||||
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
|
||||
|
||||
for (EmsFaultProtectionPlan plan : planList) {
|
||||
planId = plan.getId();
|
||||
String siteId = plan.getSiteId();
|
||||
if (StringUtils.isEmpty(siteId)) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
// 保护前提
|
||||
String protectionSettings = plan.getProtectionSettings();
|
||||
final List<ProtectionSettingVo> protSettings = objectMapper.readValue(
|
||||
protectionSettings,
|
||||
new TypeReference<List<ProtectionSettingVo>>() {}
|
||||
);
|
||||
if (protSettings == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理告警保护方案
|
||||
boolean isHighLevel = dealWithProtectionPlan(plan, protSettings);
|
||||
if (isHighLevel) {
|
||||
// 触发最高故障等级-结束循环
|
||||
return;
|
||||
ProtectionSettingsGroupVo settingGroup = parseProtectionSettings(plan.getProtectionSettings());
|
||||
if (CollectionUtils.isEmpty(settingGroup.getFaultSettings())
|
||||
&& CollectionUtils.isEmpty(settingGroup.getReleaseSettings())) {
|
||||
continue;
|
||||
}
|
||||
dealWithProtectionPlan(plan, settingGroup);
|
||||
}
|
||||
refreshProtectionConstraintCache(planList);
|
||||
} catch (Exception e) {
|
||||
logger.error("轮询失败,方案id为:{}", planId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理告警保护方案-返回触发下发方案时是否最高等级
|
||||
// 需要同步云端
|
||||
@SyncAfterInsert
|
||||
private boolean dealWithProtectionPlan(EmsFaultProtectionPlan plan, List<ProtectionSettingVo> protSettings) {
|
||||
private void dealWithProtectionPlan(EmsFaultProtectionPlan plan, ProtectionSettingsGroupVo settingGroup) {
|
||||
logger.info("<轮询保护方案> 站点:{},方案ID:{}", plan.getSiteId(), plan.getId());
|
||||
boolean isHighLevel = false;
|
||||
|
||||
String siteId = plan.getSiteId();
|
||||
final Integer isAlertAlarm = plan.getIsAlert();
|
||||
final Long status = plan.getStatus();
|
||||
// 看方案是否启用,走不同判断
|
||||
Integer isAlertAlarm = plan.getIsAlert();
|
||||
List<ProtectionSettingVo> faultSettings = settingGroup.getFaultSettings();
|
||||
List<ProtectionSettingVo> releaseSettings = settingGroup.getReleaseSettings();
|
||||
Long status = plan.getStatus();
|
||||
if (status == null) {
|
||||
status = ProtPlanStatus.STOP.getCode();
|
||||
}
|
||||
|
||||
if (Objects.equals(status, ProtPlanStatus.STOP.getCode())) {
|
||||
logger.info("<方案未启用> 站点:{},方案ID:{}", siteId, plan.getId());
|
||||
// 未启用,获取方案的故障值与最新数据判断是否需要下发方案
|
||||
if(checkIsNeedIssuedPlan(protSettings, siteId)){
|
||||
if("3".equals(plan.getFaultLevel())){
|
||||
isHighLevel = true;//最高故障等级
|
||||
}
|
||||
// 延时
|
||||
final int faultDelay = plan.getFaultDelaySeconds().intValue();
|
||||
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
|
||||
// 延时后再次确认是否仍满足触发条件(防止期间状态变化)
|
||||
if (checkIsNeedIssuedPlan(protSettings, siteId)) {
|
||||
// 判断是否需要生成告警
|
||||
if (isAlertAlarm == 1) {
|
||||
logger.info("<生成告警> 方案ID:{},站点:{}", plan.getId(), siteId);
|
||||
EmsAlarmRecords alarmRecords = addAlarmRecord(siteId,plan.getFaultName(),
|
||||
getAlarmLevel(plan.getFaultLevel()));
|
||||
emsAlarmRecordsMapper.insertEmsAlarmRecords(alarmRecords);
|
||||
}
|
||||
|
||||
// 是否有保护方案,有则通过modbus连接设备下发方案
|
||||
String protPlanJson = plan.getProtectionPlan();
|
||||
if (protPlanJson != null && !protPlanJson.isEmpty() && !"[]".equals(protPlanJson)) {
|
||||
logger.info("<下发保护方案> 方案内容:{}", protPlanJson);
|
||||
executeProtectionActions(protPlanJson,siteId,plan.getId(),plan.getFaultLevel()); // 执行Modbus指令
|
||||
}
|
||||
|
||||
// 更新方案状态为“已启用”
|
||||
logger.info("<方案已启用> 方案ID:{}", plan.getId());
|
||||
plan.setStatus(ProtPlanStatus.RUNNING.getCode());
|
||||
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
||||
|
||||
// 更新该站点策略为暂停状态
|
||||
updateStrategyRunningStatus(siteId, StrategyStatus.SUSPENDED.getCode());
|
||||
if (checkIsNeedIssuedPlan(faultSettings, siteId)) {
|
||||
int faultDelay = safeDelaySeconds(plan.getFaultDelaySeconds(), 0);
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
if (!checkIsNeedIssuedPlan(faultSettings, siteId)) {
|
||||
return;
|
||||
}
|
||||
}, faultDelay, TimeUnit.SECONDS);
|
||||
}
|
||||
} else {
|
||||
logger.info("<方案已启用> 站点:{},方案ID:{}", siteId, plan.getId());
|
||||
// 已启用,则获取方案的释放值与最新数据判断是否需要取消方案
|
||||
if(checkIsNeedCancelPlan(protSettings, siteId)){
|
||||
// 延时,
|
||||
int releaseDelay = plan.getReleaseDelaySeconds().intValue();
|
||||
ScheduledFuture<?> delayTask = scheduledExecutorService.schedule(() -> {
|
||||
// 判断是否已存在未处理告警,有着取消
|
||||
if(isAlertAlarm == 1){
|
||||
logger.info("<取消告警>");
|
||||
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.getFailedRecord(siteId,
|
||||
plan.getFaultName(),getAlarmLevel(plan.getFaultLevel()));
|
||||
if(emsAlarmRecords != null){
|
||||
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
||||
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
||||
}
|
||||
if (Integer.valueOf(1).equals(isAlertAlarm)) {
|
||||
EmsAlarmRecords alarmRecords = addAlarmRecord(siteId, plan.getFaultName(), getAlarmLevel(plan.getFaultLevel()));
|
||||
emsAlarmRecordsMapper.insertEmsAlarmRecords(alarmRecords);
|
||||
}
|
||||
// 更新方案状态为“未启用”
|
||||
logger.info("<方案变更为未启用> 方案ID:{}", plan.getId());
|
||||
plan.setStatus(ProtPlanStatus.STOP.getCode());
|
||||
plan.setStatus(ProtPlanStatus.RUNNING.getCode());
|
||||
plan.setUpdateBy("system");
|
||||
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
||||
// 更新该站点策略为启用状态
|
||||
updateStrategyRunningStatus(siteId, StrategyStatus.RUNNING.getCode());
|
||||
}, releaseDelay, TimeUnit.SECONDS);
|
||||
refreshSiteProtectionConstraint(siteId);
|
||||
}, faultDelay, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
return isHighLevel;
|
||||
}
|
||||
|
||||
// 下发保护方案
|
||||
private void executeProtectionActions(String protPlanJson, String siteId, Long planId, Integer faultLevel){
|
||||
final List<ProtectionPlanVo> protPlanList;
|
||||
try {
|
||||
protPlanList = objectMapper.readValue(
|
||||
protPlanJson,
|
||||
new TypeReference<List<ProtectionPlanVo>>() {}
|
||||
);
|
||||
if (protPlanList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历保护方案
|
||||
for (ProtectionPlanVo plan : protPlanList) {
|
||||
if (StringUtils.isEmpty(plan.getDeviceId()) || StringUtils.isEmpty(plan.getPoint())) {
|
||||
return;
|
||||
}
|
||||
// 给设备发送指令记录日志,并同步云端
|
||||
EmsFaultIssueLog faultIssueLog = createLogEntity(plan,siteId);
|
||||
faultIssueLog.setLogLevel(faultLevel);
|
||||
emsFaultIssueLogMapper.insertEmsFaultIssueLog(faultIssueLog);
|
||||
|
||||
// 通过modbus连接设备,发送数据
|
||||
executeSinglePlan(plan,siteId);
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("下发保护方案失败,方案id为:", planId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private EmsFaultIssueLog createLogEntity(ProtectionPlanVo plan,String siteId) {
|
||||
EmsFaultIssueLog faultIssueLog = new EmsFaultIssueLog();
|
||||
faultIssueLog.setLogId(UUID.randomUUID().toString());
|
||||
faultIssueLog.setLogTime(new Date());
|
||||
faultIssueLog.setSiteId(siteId);
|
||||
faultIssueLog.setDeviceId(plan.getDeviceId());
|
||||
faultIssueLog.setPoint(plan.getPoint());
|
||||
faultIssueLog.setValue(plan.getValue());
|
||||
faultIssueLog.setCreateBy("sys");
|
||||
faultIssueLog.setCreateTime(new Date());
|
||||
return faultIssueLog;
|
||||
}
|
||||
|
||||
private void executeSinglePlan(ProtectionPlanVo plan, String siteId) throws Exception {
|
||||
String deviceId = plan.getDeviceId();
|
||||
// 获取设备地址信息
|
||||
EmsDevicesSetting device = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
|
||||
if (device == null || StringUtils.isEmpty(device.getIpAddress()) || device.getIpPort()==null) {
|
||||
logger.warn("设备信息不完整,deviceId:{}", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建设备配置
|
||||
DeviceConfig config = new DeviceConfig();
|
||||
config.setHost(device.getIpAddress());
|
||||
config.setPort(device.getIpPort().intValue());
|
||||
config.setSlaveId(device.getSlaveId().intValue());
|
||||
config.setDeviceName(device.getDeviceName());
|
||||
config.setDeviceNumber(device.getDeviceId());
|
||||
|
||||
// 构建写入标签配置
|
||||
WriteTagConfig writeTag = new WriteTagConfig();
|
||||
writeTag.setAddress(plan.getPoint());
|
||||
writeTag.setValue(plan.getValue());
|
||||
|
||||
List<WriteTagConfig> writeTags = new ArrayList<>();
|
||||
writeTags.add(writeTag);
|
||||
config.setWriteTags(writeTags);
|
||||
|
||||
// 写入数据到设备
|
||||
boolean success = modbusProcessor.writeDataToDeviceWithRetry(config);
|
||||
|
||||
if (!success) {
|
||||
logger.error("写入失败,设备地址:{}", device.getIpAddress());
|
||||
if (checkIsNeedCancelPlan(releaseSettings, siteId)) {
|
||||
int releaseDelay = safeDelaySeconds(plan.getReleaseDelaySeconds(), 0);
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
if (Integer.valueOf(1).equals(isAlertAlarm)) {
|
||||
EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.getFailedRecord(
|
||||
siteId,
|
||||
plan.getFaultName(),
|
||||
getAlarmLevel(plan.getFaultLevel())
|
||||
);
|
||||
if (emsAlarmRecords != null) {
|
||||
emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
|
||||
emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
|
||||
}
|
||||
}
|
||||
plan.setStatus(ProtPlanStatus.STOP.getCode());
|
||||
plan.setUpdateBy("system");
|
||||
emsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(plan);
|
||||
refreshSiteProtectionConstraint(siteId);
|
||||
}, releaseDelay, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
// 校验释放值是否取消方案
|
||||
private boolean checkIsNeedCancelPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
||||
BigDecimal releaseValue = BigDecimal.ZERO;
|
||||
private int safeDelaySeconds(Long delay, int defaultSeconds) {
|
||||
if (delay == null || delay < 0) {
|
||||
return defaultSeconds;
|
||||
}
|
||||
return delay.intValue();
|
||||
}
|
||||
|
||||
private ProtectionSettingsGroupVo parseProtectionSettings(String settingsJson) {
|
||||
if (StringUtils.isEmpty(settingsJson)) {
|
||||
return ProtectionSettingsGroupVo.empty();
|
||||
}
|
||||
try {
|
||||
if (settingsJson.trim().startsWith("[")) {
|
||||
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>>() {}
|
||||
);
|
||||
return plans == null ? new ArrayList<>() : plans;
|
||||
}
|
||||
ProtectionPlanVo plan = objectMapper.readValue(planJson, ProtectionPlanVo.class);
|
||||
List<ProtectionPlanVo> plans = new ArrayList<>();
|
||||
if (plan != null) {
|
||||
plans.add(plan);
|
||||
}
|
||||
return plans;
|
||||
} catch (Exception e) {
|
||||
logger.error("解析执行保护失败,json:{}", planJson, e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshProtectionConstraintCache(List<EmsFaultProtectionPlan> allPlans) {
|
||||
Map<String, List<EmsFaultProtectionPlan>> planBySite = new HashMap<>();
|
||||
for (EmsFaultProtectionPlan plan : allPlans) {
|
||||
if (StringUtils.isEmpty(plan.getSiteId())) {
|
||||
continue;
|
||||
}
|
||||
planBySite.computeIfAbsent(plan.getSiteId(), k -> new ArrayList<>()).add(plan);
|
||||
}
|
||||
for (Map.Entry<String, List<EmsFaultProtectionPlan>> entry : planBySite.entrySet()) {
|
||||
writeSiteProtectionConstraint(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshSiteProtectionConstraint(String siteId) {
|
||||
if (StringUtils.isEmpty(siteId)) {
|
||||
return;
|
||||
}
|
||||
EmsFaultProtectionPlan query = new EmsFaultProtectionPlan();
|
||||
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;
|
||||
}
|
||||
|
||||
ProtectionConstraintVo merged = ProtectionConstraintVo.empty();
|
||||
for (EmsFaultProtectionPlan runningPlan : runningPlans) {
|
||||
ProtectionConstraintVo single = buildConstraintFromPlan(runningPlan);
|
||||
mergeConstraint(merged, single);
|
||||
}
|
||||
merged.setUpdateAt(System.currentTimeMillis());
|
||||
redisCache.setCacheObject(key, merged, CONSTRAINT_TTL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private ProtectionConstraintVo buildConstraintFromPlan(EmsFaultProtectionPlan plan) {
|
||||
ProtectionConstraintVo vo = ProtectionConstraintVo.empty();
|
||||
int level = plan.getFaultLevel() == null ? 0 : plan.getFaultLevel();
|
||||
vo.setLevel(level);
|
||||
vo.setSourcePlanIds(new ArrayList<>());
|
||||
vo.getSourcePlanIds().add(plan.getId());
|
||||
|
||||
if (level == 1) {
|
||||
vo.setPowerLimitRatio(DEFAULT_L1_POWER_RATIO);
|
||||
} 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();
|
||||
BigDecimal ratioByDesc = parseDerateRatio(description);
|
||||
if (ratioByDesc != null) {
|
||||
vo.setPowerLimitRatio(minRatio(vo.getPowerLimitRatio(), ratioByDesc));
|
||||
}
|
||||
|
||||
if (description.contains("禁止充放电")) {
|
||||
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) {
|
||||
StringBuilder conditionSb = new StringBuilder();
|
||||
for (int i = 0; i < protSettings.size(); i++) {
|
||||
ProtectionSettingVo vo = protSettings.get(i);
|
||||
String deviceId = vo.getDeviceId();
|
||||
String point = vo.getPoint();
|
||||
releaseValue = vo.getFaultValue();
|
||||
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || releaseValue == null
|
||||
|| StringUtils.isEmpty(vo.getReleaseOperator())){
|
||||
BigDecimal releaseValue = vo.getReleaseValue();
|
||||
if (StringUtils.isEmpty(deviceId)
|
||||
|| StringUtils.isEmpty(point)
|
||||
|| releaseValue == null
|
||||
|| StringUtils.isEmpty(vo.getReleaseOperator())) {
|
||||
return false;
|
||||
}
|
||||
// 获取点位最新值
|
||||
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
||||
logger.info("checkIsNeedCancelPlan 点位:{},最新值:{},比较方式:{},释放值:{}", point, lastPointValue, vo.getReleaseOperator(), releaseValue);
|
||||
if(lastPointValue == null){
|
||||
if (lastPointValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
|
||||
conditionSb.append(lastPointValue).append(vo.getReleaseOperator()).append(releaseValue);
|
||||
if (i < protSettings.size() - 1) {
|
||||
String relation = vo.getRelationNext();
|
||||
conditionSb.append(" ").append(relation).append(" ");
|
||||
conditionSb.append(" ").append(vo.getRelationNext()).append(" ");
|
||||
}
|
||||
|
||||
}
|
||||
// 执行比较语句
|
||||
return executeWithParser(conditionSb.toString());
|
||||
}
|
||||
|
||||
// 校验故障值是否需要下发方案
|
||||
private boolean checkIsNeedIssuedPlan(List<ProtectionSettingVo> protSettings, String siteId) {
|
||||
BigDecimal faultValue = BigDecimal.ZERO;
|
||||
|
||||
StringBuilder conditionSb = new StringBuilder();
|
||||
for (int i = 0; i < protSettings.size(); i++) {
|
||||
ProtectionSettingVo vo = protSettings.get(i);
|
||||
String deviceId = vo.getDeviceId();
|
||||
String point = vo.getPoint();
|
||||
faultValue = vo.getFaultValue();
|
||||
if(StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(point) || faultValue == null
|
||||
|| StringUtils.isEmpty(vo.getFaultOperator())){
|
||||
BigDecimal faultValue = vo.getFaultValue();
|
||||
if (StringUtils.isEmpty(deviceId)
|
||||
|| StringUtils.isEmpty(point)
|
||||
|| faultValue == null
|
||||
|| StringUtils.isEmpty(vo.getFaultOperator())) {
|
||||
return false;
|
||||
}
|
||||
// 获取点位最新值
|
||||
BigDecimal lastPointValue = getPointLastValue(deviceId, point, siteId);
|
||||
logger.info("checkIsNeedIssuedPlan 点位:{},最新值:{},比较方式:{},故障值:{}", point, lastPointValue, vo.getFaultOperator(), faultValue);
|
||||
if(lastPointValue == null){
|
||||
if (lastPointValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 拼接校验语句-最新值+比较方式+故障值+与下一点位关系(最后一个条件后不加关系)
|
||||
conditionSb.append(lastPointValue).append(vo.getFaultOperator()).append(faultValue);
|
||||
if (i < protSettings.size() - 1) {
|
||||
String relation = vo.getRelationNext();
|
||||
conditionSb.append(" ").append(relation).append(" ");
|
||||
conditionSb.append(" ").append(vo.getRelationNext()).append(" ");
|
||||
}
|
||||
|
||||
}
|
||||
// 执行比较语句
|
||||
return executeWithParser(conditionSb.toString());
|
||||
}
|
||||
|
||||
private BigDecimal getPointLastValue(String deviceId, String point, String siteId) {
|
||||
JSONObject mqttJson = redisCache.getCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceId);
|
||||
if(mqttJson == null){
|
||||
if (mqttJson == null) {
|
||||
return null;
|
||||
}
|
||||
String jsonData = mqttJson.get("Data").toString();
|
||||
if(StringUtils.isEmpty(jsonData)){
|
||||
if (StringUtils.isEmpty(jsonData)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> obj = JSON.parseObject(jsonData, new com.alibaba.fastjson2.TypeReference<Map<String, Object>>() {});
|
||||
return StringUtils.getBigDecimal(obj.get(point));
|
||||
}
|
||||
|
||||
// 更新站点策略为启用
|
||||
private void updateStrategyRunningStatus(String siteId, String status) {
|
||||
// 获取是否有正在运行的策略,如果有则不更改
|
||||
EmsStrategyRunning query = new EmsStrategyRunning();
|
||||
query.setSiteId(siteId);
|
||||
query.setStatus(StrategyStatus.RUNNING.getCode().equals(status) ? StrategyStatus.SUSPENDED.getCode() : StrategyStatus.RUNNING.getCode());
|
||||
List<EmsStrategyRunning> strategyRunningList = emsStrategyRunningMapper.selectEmsStrategyRunningList(query);
|
||||
if (CollectionUtils.isNotEmpty(strategyRunningList)) {
|
||||
// 获取已存在并且状态为:未启用和已暂停的最晚一条策略,更新为已启用
|
||||
strategyRunningList.forEach(emsStrategyRunning -> {
|
||||
emsStrategyRunning.setStatus(status);
|
||||
emsStrategyRunningMapper.updateEmsStrategyRunning(emsStrategyRunning);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 更新站点策略为启用
|
||||
private void updateStrategyRunning(String siteId) {
|
||||
// 获取是否有正在运行的策略,如果有则不更改
|
||||
EmsStrategyRunning emsStrategyRunning = emsStrategyRunningMapper.getRunningStrategy(siteId);
|
||||
if (emsStrategyRunning == null) {
|
||||
// 获取已存在并且状态为:未启用和已暂停的最晚一条策略,更新为已启用
|
||||
emsStrategyRunning = emsStrategyRunningMapper.getPendingStrategy(siteId);
|
||||
emsStrategyRunning.setStatus(StrategyStatus.RUNNING.getCode());
|
||||
emsStrategyRunningMapper.updateEmsStrategyRunning(emsStrategyRunning);
|
||||
}
|
||||
}
|
||||
|
||||
private EmsAlarmRecords addAlarmRecord(String siteId, String content,String level) {
|
||||
private EmsAlarmRecords addAlarmRecord(String siteId, String content, String level) {
|
||||
EmsAlarmRecords emsAlarmRecords = new EmsAlarmRecords();
|
||||
emsAlarmRecords.setSiteId(siteId);
|
||||
emsAlarmRecords.setAlarmContent(content);
|
||||
@ -395,29 +532,31 @@ public class ProtectionPlanTask {
|
||||
return emsAlarmRecords;
|
||||
}
|
||||
|
||||
// 故障等级-告警等级匹配
|
||||
private String getAlarmLevel(Integer faultLevel) {
|
||||
if (ObjectUtils.isEmpty(faultLevel) || faultLevel < 1 || faultLevel > 3) {
|
||||
logger.warn("非法故障等级:{},默认返回普通告警", faultLevel);
|
||||
logger.warn("非法故障等级:{},默认返回紧急告警", faultLevel);
|
||||
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||
}
|
||||
switch (faultLevel) {
|
||||
case 1: return AlarmLevelStatus.GENERAL.getCode();
|
||||
case 2: return AlarmLevelStatus.SERIOUS.getCode();
|
||||
case 3: return AlarmLevelStatus.EMERGENCY.getCode();
|
||||
case 1:
|
||||
return AlarmLevelStatus.GENERAL.getCode();
|
||||
case 2:
|
||||
return AlarmLevelStatus.SERIOUS.getCode();
|
||||
case 3:
|
||||
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||
default:
|
||||
logger.error("未匹配的故障等级:{}", faultLevel);
|
||||
return AlarmLevelStatus.EMERGENCY.getCode();
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义表达式解析器(仅支持简单运算符和逻辑关系)
|
||||
/**
|
||||
* 自定义表达式解析器(仅支持简单运算符和逻辑关系)
|
||||
*/
|
||||
public boolean executeWithParser(String conditionStr) {
|
||||
if (conditionStr == null || conditionStr.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1. 拆分逻辑关系(提取 && 或 ||)
|
||||
List<String> logicRelations = new ArrayList<>();
|
||||
Pattern logicPattern = Pattern.compile("(&&|\\|\\|)");
|
||||
Matcher logicMatcher = logicPattern.matcher(conditionStr);
|
||||
@ -425,10 +564,7 @@ public class ProtectionPlanTask {
|
||||
logicRelations.add(logicMatcher.group());
|
||||
}
|
||||
|
||||
// 2. 拆分原子条件(如 "3.55>3.52")
|
||||
String[] atomicConditions = logicPattern.split(conditionStr);
|
||||
|
||||
// 3. 解析每个原子条件并计算结果
|
||||
List<Boolean> atomicResults = new ArrayList<>();
|
||||
Pattern conditionPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*([><]=?|==)\\s*(\\d+\\.?\\d*)");
|
||||
for (String atomic : atomicConditions) {
|
||||
@ -437,11 +573,10 @@ public class ProtectionPlanTask {
|
||||
logger.error("无效的原子条件:{}", atomic);
|
||||
return false;
|
||||
}
|
||||
double left = Double.parseDouble(matcher.group(1)); // 左值(最新值)
|
||||
String operator = matcher.group(2); // 运算符
|
||||
double right = Double.parseDouble(matcher.group(3)); // 右值(故障值)
|
||||
double left = Double.parseDouble(matcher.group(1));
|
||||
String operator = matcher.group(2);
|
||||
double right = Double.parseDouble(matcher.group(3));
|
||||
|
||||
// 执行比较
|
||||
boolean result;
|
||||
switch (operator) {
|
||||
case ">":
|
||||
@ -466,11 +601,10 @@ public class ProtectionPlanTask {
|
||||
atomicResults.add(result);
|
||||
}
|
||||
|
||||
// 4. 组合原子结果(根据逻辑关系)
|
||||
boolean finalResult = atomicResults.get(0);
|
||||
for (int i = 0; i < logicRelations.size(); i++) {
|
||||
String relation = logicRelations.get(i);
|
||||
boolean nextResult = atomicResults.get(i+1);
|
||||
boolean nextResult = atomicResults.get(i + 1);
|
||||
if ("&&".equals(relation)) {
|
||||
finalResult = finalResult && nextResult;
|
||||
} else if ("||".equals(relation)) {
|
||||
|
||||
@ -2,11 +2,16 @@ package com.xzzn.quartz.task;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.xzzn.common.constant.RedisKeyConstants;
|
||||
import com.xzzn.common.core.modbus.ModbusProcessor;
|
||||
import com.xzzn.common.core.modbus.domain.DeviceConfig;
|
||||
import com.xzzn.common.core.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.DeviceCategory;
|
||||
import com.xzzn.common.enums.OperatorType;
|
||||
import com.xzzn.common.enums.SiteDevice;
|
||||
import com.xzzn.common.enums.SocLimit;
|
||||
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.EmsDevicesSetting;
|
||||
import com.xzzn.ems.domain.EmsPcsSetting;
|
||||
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||
import com.xzzn.ems.domain.EmsStrategyLog;
|
||||
import com.xzzn.ems.domain.EmsStrategyTemp;
|
||||
import com.xzzn.ems.domain.EmsStrategyTimeConfig;
|
||||
import com.xzzn.ems.domain.vo.ProtectionConstraintVo;
|
||||
import com.xzzn.ems.domain.vo.StrategyRunningVo;
|
||||
import com.xzzn.ems.mapper.EmsAmmeterDataMapper;
|
||||
import com.xzzn.ems.mapper.EmsBatteryStackMapper;
|
||||
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsPcsSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsStrategyLogMapper;
|
||||
import com.xzzn.ems.mapper.EmsStrategyRuntimeConfigMapper;
|
||||
import com.xzzn.ems.mapper.EmsStrategyRunningMapper;
|
||||
import com.xzzn.ems.mapper.EmsStrategyTempMapper;
|
||||
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.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -57,16 +69,34 @@ public class StrategyPoller {
|
||||
private static final ConcurrentHashMap<Long, Boolean> strategyLocks = new ConcurrentHashMap<>();
|
||||
|
||||
// SOC 上下限值,默认为0%-100%
|
||||
private static final BigDecimal SOC_DOWN = new BigDecimal(0);
|
||||
private static final BigDecimal SOC_UP = new BigDecimal(100);
|
||||
private static final BigDecimal DEFAULT_SOC_DOWN = BigDecimal.ZERO;
|
||||
private static final BigDecimal DEFAULT_SOC_UP = new BigDecimal(100);
|
||||
// 逆变器功率下限值,默认为30kW
|
||||
private static final BigDecimal ANTI_REVERSE_THRESHOLD = new BigDecimal(30);
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_THRESHOLD = new BigDecimal(30);
|
||||
// 逆变器下限值范围,默认为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
|
||||
private static final BigDecimal ANTI_REVERSE_UP = new BigDecimal(100);
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_UP = new BigDecimal(100);
|
||||
// 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
|
||||
private EmsStrategyRunningMapper emsStrategyRunningMapper;
|
||||
@ -85,7 +115,13 @@ public class StrategyPoller {
|
||||
@Autowired
|
||||
private EmsStrategyLogMapper emsStrategyLogMapper;
|
||||
@Autowired
|
||||
private EmsStrategyRuntimeConfigMapper runtimeConfigMapper;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@Autowired
|
||||
private ModbusProcessor modbusProcessor;
|
||||
@Autowired
|
||||
private ISysOperLogService operLogService;
|
||||
|
||||
@Resource(name = "modbusExecutor")
|
||||
private ExecutorService modbusExecutor;
|
||||
@ -132,6 +168,7 @@ public class StrategyPoller {
|
||||
}
|
||||
|
||||
private void dealStrategyCurveData(Long strategyId, String siteId) {
|
||||
EmsStrategyRuntimeConfig runtimeConfig = getRuntimeConfig(siteId);
|
||||
// 1.获取当前策略的所有模板
|
||||
List<Map<String, String>> temps = emsStrategyTempMapper.getTempNameList(strategyId, siteId);
|
||||
if (CollectionUtils.isEmpty(temps)) {
|
||||
@ -174,24 +211,53 @@ public class StrategyPoller {
|
||||
continue;
|
||||
}
|
||||
// 判断SOC上下限
|
||||
if (isSocInRange(emsStrategyTemp)) {
|
||||
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower().divide(new BigDecimal(pcsDeviceList.size()));
|
||||
if (isSocInRange(emsStrategyTemp, runtimeConfig)) {
|
||||
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) {
|
||||
EmsPcsSetting pcsSetting = emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(pcsDevice.getId());
|
||||
EmsPcsSetting pcsSetting = pcsSettingCache.computeIfAbsent(
|
||||
pcsDevice.getId(),
|
||||
id -> emsPcsSettingMapper.selectEmsPcsSettingByDeviceId(id)
|
||||
);
|
||||
if (pcsSetting == null || pcsSetting.getClusterNum() < 1) {
|
||||
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
|
||||
continue;
|
||||
}
|
||||
// 功率默认放大10倍,平均功率值,根据电池簇数量进行平均分配
|
||||
avgChargeDischargePower = avgChargeDischargePower.multiply(new BigDecimal(10)).divide(new BigDecimal(pcsSetting.getClusterNum()));
|
||||
// 平均功率值根据倍率放大后,再按电池簇数量平均分配
|
||||
BigDecimal strategyPower = avgChargeDischargePower.multiply(runtimeConfig.getPowerSetMultiplier())
|
||||
.divide(new BigDecimal(pcsSetting.getClusterNum()), POWER_SCALE, RoundingMode.HALF_UP);
|
||||
// 根据充电状态,处理数据
|
||||
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
||||
StrategyCommandDecision decision = applyProtectionConstraint(
|
||||
strategyPower,
|
||||
ChargeStatus.CHARGING,
|
||||
runtimeConfig,
|
||||
protectionConstraint
|
||||
);
|
||||
// 发送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())) {
|
||||
boolean needAntiReverseFlow = false;
|
||||
Integer powerDownType = null;
|
||||
BigDecimal chargeDischargePower = avgChargeDischargePower;
|
||||
BigDecimal chargeDischargePower = strategyPower;
|
||||
// 查询策略运行日志
|
||||
EmsStrategyLog lastStrategyLog = getLastStrategyLog(pcsDevice.getDeviceId(), emsStrategyTemp);
|
||||
if (lastStrategyLog != null) {
|
||||
@ -204,39 +270,69 @@ public class StrategyPoller {
|
||||
}
|
||||
|
||||
// 查询电网电表的正向有功功率,36kW-50kW范围内,稳定运行,低于36kW,降功率,高于50kW,增加功率
|
||||
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
|
||||
if (emsAmmeterData == null || emsAmmeterData.getTotalActivePower() == null) {
|
||||
logger.info("当前站点: {}, 未获取到最新电表数据", emsStrategyTemp.getSiteId());
|
||||
if (totalActivePower == null) {
|
||||
logger.warn("当前站点: {}, 未获取到最新电表数据,执行保守策略并切换待机", emsStrategyTemp.getSiteId());
|
||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, true, 0);
|
||||
continue;
|
||||
} 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());
|
||||
BigDecimal power = avgChargeDischargePower.multiply(ANTI_REVERSE_POWER_DOWN_PERCENT).divide(new BigDecimal(100));
|
||||
needAntiReverseFlow = isNeedAntiReverseFlow(totalActivePower, runtimeConfig);
|
||||
BigDecimal power = strategyPower.multiply(runtimeConfig.getAntiReversePowerDownPercent())
|
||||
.divide(new BigDecimal(100), POWER_SCALE, RoundingMode.HALF_UP);
|
||||
if (needAntiReverseFlow) {
|
||||
// 降功率
|
||||
chargeDischargePower = chargeDischargePower.subtract(power);
|
||||
powerDownType = 0;
|
||||
} else {
|
||||
// 判断是否需要增加功率,
|
||||
if (powerDownType != null && emsAmmeterData.getTotalActivePower().compareTo(ANTI_REVERSE_UP) > 0) {
|
||||
if (chargeDischargePower.compareTo(avgChargeDischargePower) == 0) {
|
||||
// 功率增加到平均值则停止
|
||||
if (powerDownType != null && totalActivePower.compareTo(runtimeConfig.getAntiReverseUp()) > 0) {
|
||||
if (chargeDischargePower.compareTo(targetPower) >= 0) {
|
||||
// 功率增加到限幅值则停止
|
||||
continue;
|
||||
}
|
||||
// 增加功率
|
||||
chargeDischargePower = chargeDischargePower.add(power);
|
||||
if (chargeDischargePower.compareTo(targetPower) > 0) {
|
||||
chargeDischargePower = targetPower;
|
||||
}
|
||||
powerDownType = 1;
|
||||
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,则设备直接待机
|
||||
// 发送Modbus命令控制设备-待机
|
||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.STANDBY, BigDecimal.ZERO, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||
} else {
|
||||
// 发送Modbus命令控制设备-放电
|
||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, ChargeStatus.DISCHARGING, chargeDischargePower, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||
sendModbusCommand(Collections.singletonList(pcsDevice), pcsSetting, finalStatus, finalPower, emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||
}
|
||||
} else {
|
||||
// 发送Modbus命令控制设备-待机
|
||||
@ -297,11 +393,11 @@ public class StrategyPoller {
|
||||
return emsStrategyLogMapper.getLastStrategyLog(query);
|
||||
}
|
||||
|
||||
private boolean isNeedAntiReverseFlow(BigDecimal totalActivePower) {
|
||||
private boolean isNeedAntiReverseFlow(BigDecimal totalActivePower, EmsStrategyRuntimeConfig runtimeConfig) {
|
||||
// 获取当前设定的防逆流阈值(30kW)
|
||||
BigDecimal threshold = ANTI_REVERSE_THRESHOLD;
|
||||
BigDecimal threshold = runtimeConfig.getAntiReverseThreshold();
|
||||
// 计算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%范围)
|
||||
return totalActivePower.compareTo(upperLimit) < 0;
|
||||
@ -409,8 +505,9 @@ public class StrategyPoller {
|
||||
continue;
|
||||
} else {
|
||||
// 充、放电,则先开机设备
|
||||
switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL);
|
||||
continue;
|
||||
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,8 +518,10 @@ public class StrategyPoller {
|
||||
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
||||
if (!result) {
|
||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
||||
recordDeviceOperationLog(siteId, deviceId, "写功率", chargeDischargePower, false, chargeStatus.getInfo() + "功率下发失败");
|
||||
continue;
|
||||
} else {
|
||||
recordDeviceOperationLog(siteId, deviceId, "写功率", chargeDischargePower, true, null);
|
||||
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
||||
// 待机,先写功率值,再关机
|
||||
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP)) {
|
||||
@ -440,18 +539,147 @@ public class StrategyPoller {
|
||||
private boolean switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
|
||||
String siteId = pcsDevice.getSiteId();
|
||||
String deviceId = pcsDevice.getDeviceId();
|
||||
String originalWorkStatus = pcsDevice.getWorkStatus();
|
||||
pcsDevice.setWorkStatus(workStatus.getCode());
|
||||
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
|
||||
if (deviceConfig == null) {
|
||||
pcsDevice.setWorkStatus(originalWorkStatus);
|
||||
return false;
|
||||
}
|
||||
boolean result = modbusProcessor.writeDataToDeviceWithRetry(deviceConfig);
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
|
||||
@ -461,13 +689,17 @@ public class StrategyPoller {
|
||||
LocalTime endLocalTime = endTime.toInstant()
|
||||
.atZone(zoneId)
|
||||
.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上限和下限
|
||||
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp) {
|
||||
BigDecimal socDown = SOC_DOWN;
|
||||
BigDecimal socUp = SOC_UP;
|
||||
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp, EmsStrategyRuntimeConfig runtimeConfig) {
|
||||
BigDecimal socDown = runtimeConfig.getSocDown();
|
||||
BigDecimal socUp = runtimeConfig.getSocUp();
|
||||
if (SocLimit.ON.getCode().equals(emsStrategyTemp.getSdcLimit())) {
|
||||
socDown = emsStrategyTemp.getSdcDown();
|
||||
socUp = emsStrategyTemp.getSdcUp();
|
||||
@ -491,4 +723,54 @@ public class StrategyPoller {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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")
|
||||
private String siteId;
|
||||
|
||||
/** 设备唯一标识符 */
|
||||
@Excel(name = "设备唯一标识符")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据日期:yyyy-MM-dd */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ -50,6 +46,14 @@ public class EmsDailyChargeData extends BaseEntity
|
||||
@Excel(name = "当日放电量")
|
||||
private BigDecimal dischargeData;
|
||||
|
||||
/** 总收入 */
|
||||
@Excel(name = "总收入")
|
||||
private BigDecimal totalRevenue;
|
||||
|
||||
/** 当日实时收入 */
|
||||
@Excel(name = "当日实时收入")
|
||||
private BigDecimal dayRevenue;
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
@ -70,16 +74,6 @@ public class EmsDailyChargeData extends BaseEntity
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDateTime(Date dateTime)
|
||||
{
|
||||
this.dateTime = dateTime;
|
||||
@ -130,17 +124,38 @@ public class EmsDailyChargeData extends BaseEntity
|
||||
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
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("siteId", getSiteId())
|
||||
.append("deviceId", getDeviceId())
|
||||
.append("dateTime", getDateTime())
|
||||
.append("totalChargeData", getTotalChargeData())
|
||||
.append("totalDischargeData", getTotalDischargeData())
|
||||
.append("chargeData", getChargeData())
|
||||
.append("dischargeData", getDischargeData())
|
||||
.append("totalRevenue", getTotalRevenue())
|
||||
.append("dayRevenue", getDayRevenue())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
|
||||
@ -30,13 +30,9 @@ public class EmsDailyEnergyData extends BaseEntity
|
||||
@Excel(name = "数据日期:yyyy-MM-dd", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date dataDate;
|
||||
|
||||
/** 总收入 */
|
||||
@Excel(name = "总收入")
|
||||
private BigDecimal totalRevenue;
|
||||
|
||||
/** 当日实时收入 */
|
||||
@Excel(name = "当日实时收入")
|
||||
private BigDecimal dayRevenue;
|
||||
/** 数据小时(0-23) */
|
||||
@Excel(name = "数据小时(0-23)")
|
||||
private Integer dataHour;
|
||||
|
||||
/** 尖峰时段充电差值 */
|
||||
@Excel(name = "尖峰时段充电差值")
|
||||
@ -71,6 +67,7 @@ public class EmsDailyEnergyData extends BaseEntity
|
||||
private BigDecimal valleyDischargeDiff;
|
||||
|
||||
/** 差值计算时间(如2025-10-10 23:59:00) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "差值计算时间", readConverterExp = "如=2025-10-10,2=3:59:00")
|
||||
private Date calcTime;
|
||||
|
||||
@ -104,24 +101,14 @@ public class EmsDailyEnergyData extends BaseEntity
|
||||
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;
|
||||
}
|
||||
|
||||
public void setDayRevenue(BigDecimal dayRevenue)
|
||||
{
|
||||
this.dayRevenue = dayRevenue;
|
||||
}
|
||||
|
||||
public BigDecimal getDayRevenue()
|
||||
{
|
||||
return dayRevenue;
|
||||
return dataHour;
|
||||
}
|
||||
|
||||
public void setPeakChargeDiff(BigDecimal peakChargeDiff)
|
||||
@ -220,8 +207,7 @@ public class EmsDailyEnergyData extends BaseEntity
|
||||
.append("id", getId())
|
||||
.append("siteId", getSiteId())
|
||||
.append("dataDate", getDataDate())
|
||||
.append("totalRevenue", getTotalRevenue())
|
||||
.append("dayRevenue", getDayRevenue())
|
||||
.append("dataHour", getDataHour())
|
||||
.append("peakChargeDiff", getPeakChargeDiff())
|
||||
.append("peakDischargeDiff", getPeakDischargeDiff())
|
||||
.append("highChargeDiff", getHighChargeDiff())
|
||||
|
||||
@ -49,6 +49,10 @@ public class EmsPcsSetting extends BaseEntity
|
||||
@Excel(name = "关机目标功率")
|
||||
private BigDecimal stopPower;
|
||||
|
||||
/** 目标功率倍率 */
|
||||
@Excel(name = "目标功率倍率")
|
||||
private BigDecimal powerMultiplier;
|
||||
|
||||
/** 电池簇数 */
|
||||
@Excel(name = "电池簇数")
|
||||
private Integer clusterNum;
|
||||
@ -135,6 +139,16 @@ public class EmsPcsSetting extends BaseEntity
|
||||
return stopPower;
|
||||
}
|
||||
|
||||
public BigDecimal getPowerMultiplier()
|
||||
{
|
||||
return powerMultiplier;
|
||||
}
|
||||
|
||||
public void setPowerMultiplier(BigDecimal powerMultiplier)
|
||||
{
|
||||
this.powerMultiplier = powerMultiplier;
|
||||
}
|
||||
|
||||
public void setClusterNum(Integer clusterNum)
|
||||
{
|
||||
this.clusterNum = clusterNum;
|
||||
@ -165,6 +179,7 @@ public class EmsPcsSetting extends BaseEntity
|
||||
.append("stopCommand", getStopCommand())
|
||||
.append("startPower", getStartPower())
|
||||
.append("stopPower", getStopPower())
|
||||
.append("powerMultiplier", getPowerMultiplier())
|
||||
.append("clusterNum", getClusterNum())
|
||||
.append("clusterPointAddress", getClusterPointAddress())
|
||||
.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();
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,9 @@ public class EmsPointConfig extends BaseEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "点位ID")
|
||||
private String pointId;
|
||||
|
||||
@Excel(name = "站点ID")
|
||||
private String siteId;
|
||||
|
||||
@ -60,6 +63,27 @@ public class EmsPointConfig extends BaseEntity {
|
||||
@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;
|
||||
|
||||
@Excel(name = "小数位数")
|
||||
private Integer decimalScale;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -68,6 +92,14 @@ public class EmsPointConfig extends BaseEntity {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPointId() {
|
||||
return pointId;
|
||||
}
|
||||
|
||||
public void setPointId(String pointId) {
|
||||
this.pointId = pointId;
|
||||
}
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
@ -188,10 +220,67 @@ public class EmsPointConfig extends BaseEntity {
|
||||
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;
|
||||
}
|
||||
|
||||
public Integer getDecimalScale() {
|
||||
return decimalScale;
|
||||
}
|
||||
|
||||
public void setDecimalScale(Integer decimalScale) {
|
||||
this.decimalScale = decimalScale;
|
||||
}
|
||||
|
||||
@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())
|
||||
@ -207,6 +296,13 @@ public class EmsPointConfig extends BaseEntity {
|
||||
.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("decimalScale", getDecimalScale())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
|
||||
@ -11,7 +11,10 @@ public class EmsSiteMonitorPointMatch extends BaseEntity {
|
||||
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;
|
||||
@ -44,4 +47,28 @@ public class EmsSiteMonitorPointMatch extends BaseEntity {
|
||||
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 = "站点名称")
|
||||
private String siteName;
|
||||
|
||||
/** 站点简称 */
|
||||
@Excel(name = "站点简称")
|
||||
private String siteShortName;
|
||||
|
||||
/** 站点地址 */
|
||||
@Excel(name = "站点地址")
|
||||
private String siteAddress;
|
||||
@ -77,6 +81,16 @@ public class EmsSiteSetting extends BaseEntity
|
||||
return siteName;
|
||||
}
|
||||
|
||||
public void setSiteShortName(String siteShortName)
|
||||
{
|
||||
this.siteShortName = siteShortName;
|
||||
}
|
||||
|
||||
public String getSiteShortName()
|
||||
{
|
||||
return siteShortName;
|
||||
}
|
||||
|
||||
public void setSiteAddress(String siteAddress)
|
||||
{
|
||||
this.siteAddress = siteAddress;
|
||||
@ -162,6 +176,7 @@ public class EmsSiteSetting extends BaseEntity
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("siteName", getSiteName())
|
||||
.append("siteShortName", getSiteShortName())
|
||||
.append("siteAddress", getSiteAddress())
|
||||
.append("runningTime", getRunningTime())
|
||||
.append("latitude", getLatitude())
|
||||
|
||||
@ -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)")
|
||||
private BigDecimal chargeDischargePower;
|
||||
|
||||
/** SDC下限 (%) */
|
||||
@Excel(name = "SDC下限 (%)")
|
||||
private BigDecimal sdcDown;
|
||||
|
||||
/** SDC上限 (%) */
|
||||
@Excel(name = "SDC上限 (%)")
|
||||
private BigDecimal sdcUp;
|
||||
|
||||
/** 充电状态,如“1-充电”、“2-待机” */
|
||||
@Excel(name = "充电状态,如“1-充电”、“2-待机”")
|
||||
private String chargeStatus;
|
||||
@ -83,6 +91,26 @@ public class EmsStrategyTempTimeConfig extends BaseEntity
|
||||
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)
|
||||
{
|
||||
this.chargeStatus = chargeStatus;
|
||||
@ -110,6 +138,8 @@ public class EmsStrategyTempTimeConfig extends BaseEntity
|
||||
.append("startTime", getStartTime())
|
||||
.append("endTime", getEndTime())
|
||||
.append("chargeDischargePower", getChargeDischargePower())
|
||||
.append("sdcDown", getSdcDown())
|
||||
.append("sdcUp", getSdcUp())
|
||||
.append("chargeStatus", getChargeStatus())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
package com.xzzn.ems.domain;
|
||||
|
||||
import com.xzzn.common.core.domain.BaseEntity;
|
||||
|
||||
public class SysBizRemark extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
|
||||
private String bizType;
|
||||
|
||||
private String bizKey1;
|
||||
|
||||
private String bizKey2;
|
||||
|
||||
private String delFlag;
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getBizType()
|
||||
{
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public void setBizType(String bizType)
|
||||
{
|
||||
this.bizType = bizType;
|
||||
}
|
||||
|
||||
public String getBizKey1()
|
||||
{
|
||||
return bizKey1;
|
||||
}
|
||||
|
||||
public void setBizKey1(String bizKey1)
|
||||
{
|
||||
this.bizKey1 = bizKey1;
|
||||
}
|
||||
|
||||
public String getBizKey2()
|
||||
{
|
||||
return bizKey2;
|
||||
}
|
||||
|
||||
public void setBizKey2(String bizKey2)
|
||||
{
|
||||
this.bizKey2 = bizKey2;
|
||||
}
|
||||
|
||||
public String getDelFlag()
|
||||
{
|
||||
return delFlag;
|
||||
}
|
||||
|
||||
public void setDelFlag(String delFlag)
|
||||
{
|
||||
this.delFlag = delFlag;
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,15 @@ public class AmmeterRevenueStatisListVo {
|
||||
/** 类别 */
|
||||
private String dataTime;
|
||||
|
||||
/** 是否工作日:1-工作日 0-节假日 */
|
||||
private Integer isWorkday;
|
||||
|
||||
/** 日期类型 */
|
||||
private String dayType;
|
||||
|
||||
/** 天气情况 */
|
||||
private String weatherDesc;
|
||||
|
||||
/** 组合有功-总 */
|
||||
private BigDecimal activeTotalPrice = BigDecimal.ZERO;
|
||||
|
||||
@ -44,6 +53,8 @@ public class AmmeterRevenueStatisListVo {
|
||||
/** 实际收益 */
|
||||
private BigDecimal actualRevenue = BigDecimal.ZERO;
|
||||
|
||||
private String remark;
|
||||
|
||||
public String getDataTime() {
|
||||
return dataTime;
|
||||
}
|
||||
@ -52,6 +63,30 @@ public class AmmeterRevenueStatisListVo {
|
||||
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() {
|
||||
return activeTotalPrice;
|
||||
}
|
||||
@ -139,4 +174,12 @@ public class AmmeterRevenueStatisListVo {
|
||||
public void setActualRevenue(BigDecimal actualRevenue) {
|
||||
this.actualRevenue = actualRevenue;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,8 @@ public class AmmeterStatisListVo {
|
||||
/** 效率-有功总/无功总 */
|
||||
private BigDecimal effect = BigDecimal.ZERO;
|
||||
|
||||
private String remark;
|
||||
|
||||
public String getDataTime() {
|
||||
return dataTime;
|
||||
}
|
||||
@ -149,4 +151,12 @@ public class AmmeterStatisListVo {
|
||||
public void setEffect(BigDecimal effect) {
|
||||
this.effect = effect;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,18 @@ public class BatteryDataStatsListVo {
|
||||
|
||||
/** 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")
|
||||
private Date dataTimestamp;
|
||||
@ -71,6 +83,38 @@ public class BatteryDataStatsListVo {
|
||||
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() {
|
||||
return dataTimestamp;
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BizRemarkBatchGetRequest
|
||||
{
|
||||
private String bizType;
|
||||
|
||||
private String bizKey1;
|
||||
|
||||
private List<String> bizKey2List;
|
||||
|
||||
public String getBizType()
|
||||
{
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public void setBizType(String bizType)
|
||||
{
|
||||
this.bizType = bizType;
|
||||
}
|
||||
|
||||
public String getBizKey1()
|
||||
{
|
||||
return bizKey1;
|
||||
}
|
||||
|
||||
public void setBizKey1(String bizKey1)
|
||||
{
|
||||
this.bizKey1 = bizKey1;
|
||||
}
|
||||
|
||||
public List<String> getBizKey2List()
|
||||
{
|
||||
return bizKey2List;
|
||||
}
|
||||
|
||||
public void setBizKey2List(List<String> bizKey2List)
|
||||
{
|
||||
this.bizKey2List = bizKey2List;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class BizRemarkSaveRequest
|
||||
{
|
||||
private String bizType;
|
||||
|
||||
private String bizKey1;
|
||||
|
||||
private String bizKey2;
|
||||
|
||||
private String remark;
|
||||
|
||||
public String getBizType()
|
||||
{
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public void setBizType(String bizType)
|
||||
{
|
||||
this.bizType = bizType;
|
||||
}
|
||||
|
||||
public String getBizKey1()
|
||||
{
|
||||
return bizKey1;
|
||||
}
|
||||
|
||||
public void setBizKey1(String bizKey1)
|
||||
{
|
||||
this.bizKey1 = bizKey1;
|
||||
}
|
||||
|
||||
public String getBizKey2()
|
||||
{
|
||||
return bizKey2;
|
||||
}
|
||||
|
||||
public void setBizKey2(String bizKey2)
|
||||
{
|
||||
this.bizKey2 = bizKey2;
|
||||
}
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
@ -24,11 +24,25 @@ public class DevicePointDataList
|
||||
private BigDecimal avgValue;
|
||||
// 差值(max - min)
|
||||
private BigDecimal diffValue;
|
||||
// 第一四分位数
|
||||
private BigDecimal q1;
|
||||
// 中位数
|
||||
private BigDecimal median;
|
||||
// 第三四分位数
|
||||
private BigDecimal q3;
|
||||
|
||||
public DevicePointDataList(String deviceId, List<GeneralQueryDataVo> pointValueList,String parentDeviceId,
|
||||
BigDecimal maxValue, BigDecimal minValue,
|
||||
BigDecimal avgValue, BigDecimal diffValue,
|
||||
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.pointValueList = pointValueList;
|
||||
this.parentDeviceId = parentDeviceId;
|
||||
@ -38,6 +52,9 @@ public class DevicePointDataList
|
||||
this.diffValue = diffValue;
|
||||
this.maxDate = maxDate;
|
||||
this.minDate = minDate;
|
||||
this.q1 = q1;
|
||||
this.median = median;
|
||||
this.q3 = q3;
|
||||
}
|
||||
|
||||
public DevicePointDataList(String deviceId, String parentDeviceId, List<GeneralQueryDataVo> pointValueList) {
|
||||
@ -121,4 +138,28 @@ public class DevicePointDataList
|
||||
public void setDiffValue(BigDecimal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,19 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3,7 +3,9 @@ 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;
|
||||
@ -24,6 +26,14 @@ public class PointConfigCurveRequest {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getPointId() {
|
||||
return pointId;
|
||||
}
|
||||
|
||||
public void setPointId(String pointId) {
|
||||
this.pointId = pointId;
|
||||
}
|
||||
|
||||
public String getDataKey() {
|
||||
return dataKey;
|
||||
}
|
||||
@ -32,6 +42,14 @@ public class PointConfigCurveRequest {
|
||||
this.dataKey = dataKey;
|
||||
}
|
||||
|
||||
public String getPointType() {
|
||||
return pointType;
|
||||
}
|
||||
|
||||
public void setPointType(String pointType) {
|
||||
this.pointType = pointType;
|
||||
}
|
||||
|
||||
public String getRangeType() {
|
||||
return rangeType;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class PointConfigLatestValueItemVo {
|
||||
private String siteId;
|
||||
private String pointId;
|
||||
private String deviceId;
|
||||
private String dataKey;
|
||||
|
||||
@ -13,6 +14,14 @@ public class PointConfigLatestValueItemVo {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getPointId() {
|
||||
return pointId;
|
||||
}
|
||||
|
||||
public void setPointId(String pointId) {
|
||||
this.pointId = pointId;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import java.util.Date;
|
||||
|
||||
public class PointConfigLatestValueVo {
|
||||
private String siteId;
|
||||
private String pointId;
|
||||
private String deviceId;
|
||||
private String dataKey;
|
||||
private Object pointValue;
|
||||
@ -17,6 +18,14 @@ public class PointConfigLatestValueVo {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getPointId() {
|
||||
return pointId;
|
||||
}
|
||||
|
||||
public void setPointId(String pointId) {
|
||||
this.pointId = pointId;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ public class PointNameRequest {
|
||||
|
||||
private String pointName;
|
||||
private List<String> pointNames;
|
||||
private String pointId;
|
||||
private List<String> pointIds;
|
||||
|
||||
/** 数据分组 1-分钟 2-小时 3-天 */
|
||||
private int dataUnit;
|
||||
@ -59,6 +61,22 @@ public class PointNameRequest {
|
||||
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() {
|
||||
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;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -10,10 +11,12 @@ import java.util.Date;
|
||||
public class RunningGraphRequest {
|
||||
|
||||
/** 开始时间 */
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
/** 结束时间 */
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class SingleBatteryConfigInitRequest {
|
||||
|
||||
private String siteId;
|
||||
private String scopeType;
|
||||
private String scopeDeviceId;
|
||||
private Integer targetCount;
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getScopeType() {
|
||||
return scopeType;
|
||||
}
|
||||
|
||||
public void setScopeType(String scopeType) {
|
||||
this.scopeType = scopeType;
|
||||
}
|
||||
|
||||
public String getScopeDeviceId() {
|
||||
return scopeDeviceId;
|
||||
}
|
||||
|
||||
public void setScopeDeviceId(String scopeDeviceId) {
|
||||
this.scopeDeviceId = scopeDeviceId;
|
||||
}
|
||||
|
||||
public Integer getTargetCount() {
|
||||
return targetCount;
|
||||
}
|
||||
|
||||
public void setTargetCount(Integer targetCount) {
|
||||
this.targetCount = targetCount;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class SingleBatteryConfigInitResultVo {
|
||||
|
||||
private Boolean committed;
|
||||
private String siteId;
|
||||
private String scopeType;
|
||||
private String scopeDeviceId;
|
||||
private Integer targetCount;
|
||||
private Integer existingBatteryCount;
|
||||
private Integer initializedBatteryCount;
|
||||
private Integer insertedBatteryCount;
|
||||
private Integer pointHitCount;
|
||||
private Integer fixedValueFallbackCount;
|
||||
private Integer insertedMappingCount;
|
||||
private Integer updatedMappingCount;
|
||||
private String message;
|
||||
|
||||
public Boolean getCommitted() {
|
||||
return committed;
|
||||
}
|
||||
|
||||
public void setCommitted(Boolean committed) {
|
||||
this.committed = committed;
|
||||
}
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getScopeType() {
|
||||
return scopeType;
|
||||
}
|
||||
|
||||
public void setScopeType(String scopeType) {
|
||||
this.scopeType = scopeType;
|
||||
}
|
||||
|
||||
public String getScopeDeviceId() {
|
||||
return scopeDeviceId;
|
||||
}
|
||||
|
||||
public void setScopeDeviceId(String scopeDeviceId) {
|
||||
this.scopeDeviceId = scopeDeviceId;
|
||||
}
|
||||
|
||||
public Integer getTargetCount() {
|
||||
return targetCount;
|
||||
}
|
||||
|
||||
public void setTargetCount(Integer targetCount) {
|
||||
this.targetCount = targetCount;
|
||||
}
|
||||
|
||||
public Integer getExistingBatteryCount() {
|
||||
return existingBatteryCount;
|
||||
}
|
||||
|
||||
public void setExistingBatteryCount(Integer existingBatteryCount) {
|
||||
this.existingBatteryCount = existingBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getInitializedBatteryCount() {
|
||||
return initializedBatteryCount;
|
||||
}
|
||||
|
||||
public void setInitializedBatteryCount(Integer initializedBatteryCount) {
|
||||
this.initializedBatteryCount = initializedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getInsertedBatteryCount() {
|
||||
return insertedBatteryCount;
|
||||
}
|
||||
|
||||
public void setInsertedBatteryCount(Integer insertedBatteryCount) {
|
||||
this.insertedBatteryCount = insertedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getPointHitCount() {
|
||||
return pointHitCount;
|
||||
}
|
||||
|
||||
public void setPointHitCount(Integer pointHitCount) {
|
||||
this.pointHitCount = pointHitCount;
|
||||
}
|
||||
|
||||
public Integer getFixedValueFallbackCount() {
|
||||
return fixedValueFallbackCount;
|
||||
}
|
||||
|
||||
public void setFixedValueFallbackCount(Integer fixedValueFallbackCount) {
|
||||
this.fixedValueFallbackCount = fixedValueFallbackCount;
|
||||
}
|
||||
|
||||
public Integer getInsertedMappingCount() {
|
||||
return insertedMappingCount;
|
||||
}
|
||||
|
||||
public void setInsertedMappingCount(Integer insertedMappingCount) {
|
||||
this.insertedMappingCount = insertedMappingCount;
|
||||
}
|
||||
|
||||
public Integer getUpdatedMappingCount() {
|
||||
return updatedMappingCount;
|
||||
}
|
||||
|
||||
public void setUpdatedMappingCount(Integer updatedMappingCount) {
|
||||
this.updatedMappingCount = updatedMappingCount;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class SingleBatteryMonitorImportFailureVo {
|
||||
|
||||
private Integer rowNum;
|
||||
private String siteId;
|
||||
private String stackDeviceId;
|
||||
private String clusterDeviceId;
|
||||
private String batteryDeviceId;
|
||||
private String errorMessage;
|
||||
|
||||
public Integer getRowNum() {
|
||||
return rowNum;
|
||||
}
|
||||
|
||||
public void setRowNum(Integer rowNum) {
|
||||
this.rowNum = rowNum;
|
||||
}
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getStackDeviceId() {
|
||||
return stackDeviceId;
|
||||
}
|
||||
|
||||
public void setStackDeviceId(String stackDeviceId) {
|
||||
this.stackDeviceId = stackDeviceId;
|
||||
}
|
||||
|
||||
public String getClusterDeviceId() {
|
||||
return clusterDeviceId;
|
||||
}
|
||||
|
||||
public void setClusterDeviceId(String clusterDeviceId) {
|
||||
this.clusterDeviceId = clusterDeviceId;
|
||||
}
|
||||
|
||||
public String getBatteryDeviceId() {
|
||||
return batteryDeviceId;
|
||||
}
|
||||
|
||||
public void setBatteryDeviceId(String batteryDeviceId) {
|
||||
this.batteryDeviceId = batteryDeviceId;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SingleBatteryMonitorImportResultVo {
|
||||
|
||||
private Boolean committed;
|
||||
private Integer totalRows;
|
||||
private Integer successRows;
|
||||
private Integer failureRows;
|
||||
private Integer insertedBatteryCount;
|
||||
private Integer updatedBatteryCount;
|
||||
private Integer insertedMappingCount;
|
||||
private Integer updatedMappingCount;
|
||||
private String message;
|
||||
private List<SingleBatteryMonitorImportFailureVo> failureDetails = new ArrayList<>();
|
||||
|
||||
public Boolean getCommitted() {
|
||||
return committed;
|
||||
}
|
||||
|
||||
public void setCommitted(Boolean committed) {
|
||||
this.committed = committed;
|
||||
}
|
||||
|
||||
public Integer getTotalRows() {
|
||||
return totalRows;
|
||||
}
|
||||
|
||||
public void setTotalRows(Integer totalRows) {
|
||||
this.totalRows = totalRows;
|
||||
}
|
||||
|
||||
public Integer getSuccessRows() {
|
||||
return successRows;
|
||||
}
|
||||
|
||||
public void setSuccessRows(Integer successRows) {
|
||||
this.successRows = successRows;
|
||||
}
|
||||
|
||||
public Integer getFailureRows() {
|
||||
return failureRows;
|
||||
}
|
||||
|
||||
public void setFailureRows(Integer failureRows) {
|
||||
this.failureRows = failureRows;
|
||||
}
|
||||
|
||||
public Integer getInsertedBatteryCount() {
|
||||
return insertedBatteryCount;
|
||||
}
|
||||
|
||||
public void setInsertedBatteryCount(Integer insertedBatteryCount) {
|
||||
this.insertedBatteryCount = insertedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getUpdatedBatteryCount() {
|
||||
return updatedBatteryCount;
|
||||
}
|
||||
|
||||
public void setUpdatedBatteryCount(Integer updatedBatteryCount) {
|
||||
this.updatedBatteryCount = updatedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getInsertedMappingCount() {
|
||||
return insertedMappingCount;
|
||||
}
|
||||
|
||||
public void setInsertedMappingCount(Integer insertedMappingCount) {
|
||||
this.insertedMappingCount = insertedMappingCount;
|
||||
}
|
||||
|
||||
public Integer getUpdatedMappingCount() {
|
||||
return updatedMappingCount;
|
||||
}
|
||||
|
||||
public void setUpdatedMappingCount(Integer updatedMappingCount) {
|
||||
this.updatedMappingCount = updatedMappingCount;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public List<SingleBatteryMonitorImportFailureVo> getFailureDetails() {
|
||||
return failureDetails;
|
||||
}
|
||||
|
||||
public void setFailureDetails(List<SingleBatteryMonitorImportFailureVo> failureDetails) {
|
||||
this.failureDetails = failureDetails;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
import com.xzzn.common.annotation.Excel;
|
||||
|
||||
public class SingleBatteryMonitorImportRowVo {
|
||||
|
||||
private Integer rowNum;
|
||||
|
||||
@Excel(name = "站点ID")
|
||||
private String siteId;
|
||||
|
||||
@Excel(name = "电池堆编号")
|
||||
private String stackDeviceId;
|
||||
|
||||
@Excel(name = "电池簇编号")
|
||||
private String clusterDeviceId;
|
||||
|
||||
@Excel(name = "单体编号")
|
||||
private String batteryDeviceId;
|
||||
|
||||
@Excel(name = "单体名称")
|
||||
private String batteryDeviceName;
|
||||
|
||||
@Excel(name = "电压点位ID")
|
||||
private String voltagePointId;
|
||||
|
||||
@Excel(name = "温度点位ID")
|
||||
private String temperaturePointId;
|
||||
|
||||
@Excel(name = "SOC点位ID")
|
||||
private String socPointId;
|
||||
|
||||
@Excel(name = "SOH点位ID")
|
||||
private String sohPointId;
|
||||
|
||||
public Integer getRowNum() {
|
||||
return rowNum;
|
||||
}
|
||||
|
||||
public void setRowNum(Integer rowNum) {
|
||||
this.rowNum = rowNum;
|
||||
}
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getStackDeviceId() {
|
||||
return stackDeviceId;
|
||||
}
|
||||
|
||||
public void setStackDeviceId(String stackDeviceId) {
|
||||
this.stackDeviceId = stackDeviceId;
|
||||
}
|
||||
|
||||
public String getClusterDeviceId() {
|
||||
return clusterDeviceId;
|
||||
}
|
||||
|
||||
public void setClusterDeviceId(String clusterDeviceId) {
|
||||
this.clusterDeviceId = clusterDeviceId;
|
||||
}
|
||||
|
||||
public String getBatteryDeviceId() {
|
||||
return batteryDeviceId;
|
||||
}
|
||||
|
||||
public void setBatteryDeviceId(String batteryDeviceId) {
|
||||
this.batteryDeviceId = batteryDeviceId;
|
||||
}
|
||||
|
||||
public String getBatteryDeviceName() {
|
||||
return batteryDeviceName;
|
||||
}
|
||||
|
||||
public void setBatteryDeviceName(String batteryDeviceName) {
|
||||
this.batteryDeviceName = batteryDeviceName;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,8 @@ public class SiteMonitorProjectPointMappingSaveRequest {
|
||||
|
||||
private List<SiteMonitorProjectPointMappingVo> mappings;
|
||||
|
||||
private List<String> deletedFieldCodes;
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
@ -23,4 +25,12 @@ public class SiteMonitorProjectPointMappingSaveRequest {
|
||||
public void setMappings(List<SiteMonitorProjectPointMappingVo> mappings) {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
public List<String> getDeletedFieldCodes() {
|
||||
return deletedFieldCodes;
|
||||
}
|
||||
|
||||
public void setDeletedFieldCodes(List<String> deletedFieldCodes) {
|
||||
this.deletedFieldCodes = deletedFieldCodes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,8 +16,16 @@ public class SiteMonitorProjectPointMappingVo {
|
||||
|
||||
private String fieldName;
|
||||
|
||||
private String deviceId;
|
||||
|
||||
private String deviceName;
|
||||
|
||||
private String dataPoint;
|
||||
|
||||
private String fixedDataPoint;
|
||||
|
||||
private Integer useFixedDisplay;
|
||||
|
||||
public String getModuleCode() {
|
||||
return moduleCode;
|
||||
}
|
||||
@ -81,4 +89,36 @@ public class SiteMonitorProjectPointMappingVo {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -69,6 +69,17 @@ public interface EmsDailyChargeDataMapper
|
||||
// 插入或更新站点每日充放电数据
|
||||
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);
|
||||
|
||||
|
||||
@ -68,6 +68,12 @@ public interface EmsDailyEnergyDataMapper
|
||||
|
||||
// 获取站点某日电表数据
|
||||
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);
|
||||
// 电表报表
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -13,8 +13,12 @@ public interface EmsPointConfigMapper {
|
||||
|
||||
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);
|
||||
@ -39,6 +43,12 @@ public interface EmsPointConfigMapper {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -75,4 +75,8 @@ public interface EmsPointEnumMatchMapper
|
||||
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);
|
||||
}
|
||||
|
||||
@ -14,15 +14,10 @@ public interface EmsSiteMonitorDataMapper {
|
||||
@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);
|
||||
|
||||
int updateHistoryHotColumns(@Param("tableName") String tableName,
|
||||
@Param("siteId") String siteId,
|
||||
@Param("statisMinute") java.util.Date statisMinute,
|
||||
@Param("hotSoc") String hotSoc,
|
||||
@Param("hotTotalActivePower") String hotTotalActivePower,
|
||||
@Param("hotTotalReactivePower") String hotTotalReactivePower,
|
||||
@Param("hotDayChargedCap") String hotDayChargedCap,
|
||||
@Param("hotDayDisChargedCap") String hotDayDisChargedCap,
|
||||
@Param("operName") String operName);
|
||||
}
|
||||
|
||||
@ -9,9 +9,15 @@ 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);
|
||||
|
||||
int updateEmsSiteMonitorPointMatch(EmsSiteMonitorPointMatch pointMatch);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.xzzn.ems.mapper;
|
||||
|
||||
import com.xzzn.ems.domain.SysBizRemark;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SysBizRemarkMapper
|
||||
{
|
||||
SysBizRemark selectByBizKeys(@Param("bizType") String bizType,
|
||||
@Param("bizKey1") String bizKey1,
|
||||
@Param("bizKey2") String bizKey2);
|
||||
|
||||
List<SysBizRemark> selectByBizKey2List(@Param("bizType") String bizType,
|
||||
@Param("bizKey1") String bizKey1,
|
||||
@Param("bizKey2List") List<String> bizKey2List);
|
||||
|
||||
int insertSysBizRemark(SysBizRemark bizRemark);
|
||||
|
||||
int updateSysBizRemark(SysBizRemark bizRemark);
|
||||
}
|
||||
@ -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
|
||||
*/
|
||||
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);
|
||||
// 订阅成功-处理告警
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -10,6 +10,11 @@ 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.SingleBatteryConfigInitRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo;
|
||||
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingVo;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -46,9 +51,17 @@ public interface IEmsDeviceSettingService
|
||||
|
||||
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);
|
||||
|
||||
public SingleBatteryMonitorImportResultVo importSingleBatteryMonitorMappings(String siteId, List<SingleBatteryMonitorImportRowVo> rows, String operName);
|
||||
|
||||
public SingleBatteryConfigInitResultVo initializeSingleBatteryMonitorMappings(SingleBatteryConfigInitRequest request, String operName);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -4,6 +4,7 @@ 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;
|
||||
@ -30,4 +31,6 @@ public interface IEmsPointConfigService {
|
||||
List<PointConfigLatestValueVo> getLatestValues(PointConfigLatestValueRequest request);
|
||||
|
||||
List<PointConfigCurveValueVo> getCurveData(PointConfigCurveRequest request);
|
||||
|
||||
String generateRecent7DaysData(PointConfigGenerateRecentRequest request);
|
||||
}
|
||||
|
||||
@ -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,6 +13,8 @@ public interface ISingleSiteService
|
||||
|
||||
public SiteMonitorHomeVo getSiteMonitorDataVo(String siteId);
|
||||
|
||||
public SiteMonitorHomeVo getSiteMonitorTotalDataVo(String siteId);
|
||||
|
||||
|
||||
public SiteMonitorRunningHeadInfoVo getSiteRunningHeadInfo(String siteId);
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
package com.xzzn.ems.service;
|
||||
|
||||
import com.xzzn.ems.domain.vo.BizRemarkSaveRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ISysBizRemarkService
|
||||
{
|
||||
Map<String, String> getRemarkMap(String bizType, String bizKey1, List<String> bizKey2List);
|
||||
|
||||
int saveRemark(BizRemarkSaveRequest request, String username);
|
||||
}
|
||||
@ -181,6 +181,85 @@ public class InfluxPointDataWriter {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
@ -488,6 +567,7 @@ public class InfluxPointDataWriter {
|
||||
return value == null ? "" : value.replace("\\", "\\\\").replace("'", "\\'");
|
||||
}
|
||||
|
||||
|
||||
private String escapeRegex(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
@ -546,6 +626,7 @@ public class InfluxPointDataWriter {
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@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
|
||||
public void addSubFailedAlarmRecord(String topic) {
|
||||
|
||||
@ -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
@ -4,11 +4,13 @@ import com.xzzn.common.constant.RedisKeyConstants;
|
||||
import com.xzzn.common.core.redis.RedisCache;
|
||||
import com.xzzn.common.utils.DateUtils;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.EmsDailyChargeData;
|
||||
import com.xzzn.ems.domain.EmsDailyEnergyData;
|
||||
import com.xzzn.ems.domain.EmsEnergyPriceConfig;
|
||||
import com.xzzn.ems.domain.EmsPriceTimeConfig;
|
||||
import com.xzzn.ems.domain.vo.EnergyPriceTimeRange;
|
||||
import com.xzzn.ems.domain.vo.EnergyPriceVo;
|
||||
import com.xzzn.ems.mapper.EmsDailyChargeDataMapper;
|
||||
import com.xzzn.ems.mapper.EmsDailyEnergyDataMapper;
|
||||
import com.xzzn.ems.mapper.EmsEnergyPriceConfigMapper;
|
||||
import com.xzzn.ems.mapper.EmsPriceTimeConfigMapper;
|
||||
@ -17,6 +19,7 @@ import com.xzzn.ems.service.IEmsEnergyPriceConfigService;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@ -45,6 +48,8 @@ public class EmsEnergyPriceConfigServiceImpl implements IEmsEnergyPriceConfigSer
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@Autowired
|
||||
private EmsDailyChargeDataMapper emsDailyChargeDataMapper;
|
||||
@Autowired
|
||||
private EmsDailyEnergyDataMapper emsDailyEnergyDataMapper;
|
||||
|
||||
/**
|
||||
@ -280,22 +285,21 @@ public class EmsEnergyPriceConfigServiceImpl implements IEmsEnergyPriceConfigSer
|
||||
BigDecimal dayRevenue = BigDecimal.ZERO;
|
||||
BigDecimal yesterdayRevenue = BigDecimal.ZERO;
|
||||
// 获取昨日数据
|
||||
String yesterday = DateUtils.getYesterdayDayString();
|
||||
EmsDailyEnergyData yesterdayData = emsDailyEnergyDataMapper.getDataByDate(siteId, yesterday);
|
||||
Date yesterday = DateUtils.toDate(LocalDate.now().minusDays(1));
|
||||
EmsDailyChargeData yesterdayData = emsDailyChargeDataMapper.selectBySiteIdAndDateTime(siteId, yesterday);
|
||||
if (yesterdayData != null) {
|
||||
yesterdayRevenue = yesterdayData.getDayRevenue() == null ? BigDecimal.ZERO : yesterdayData.getDayRevenue();
|
||||
}
|
||||
|
||||
// 当日实时数据
|
||||
String today = DateUtils.getDate();
|
||||
Map<String, BigDecimal> lastData = emsDailyEnergyDataMapper.getRealTimeRevenue(siteId);
|
||||
if (lastData != null) {
|
||||
totalRevenue = lastData.get("totalRevenue") == null ? BigDecimal.ZERO : lastData.get("totalRevenue");
|
||||
}
|
||||
|
||||
EmsDailyEnergyData todayData = emsDailyEnergyDataMapper.getDataByDate(siteId,today);
|
||||
if (todayData == null) {
|
||||
Map<String, BigDecimal> lastData = emsDailyEnergyDataMapper.getRealTimeRevenue(siteId);
|
||||
if (lastData != null) {
|
||||
totalRevenue = lastData.get("totalRevenue") == null ? BigDecimal.ZERO : lastData.get("totalRevenue");
|
||||
}
|
||||
} else {
|
||||
totalRevenue = todayData.getTotalRevenue() == null ? BigDecimal.ZERO : todayData.getTotalRevenue();
|
||||
if (todayData != null) {
|
||||
// 获取当月电价
|
||||
int currentMonth = LocalDate.now().getMonthValue();
|
||||
int currentYear = LocalDate.now().getYear();
|
||||
|
||||
@ -0,0 +1,144 @@
|
||||
package com.xzzn.ems.service.impl;
|
||||
|
||||
import com.xzzn.common.exception.ServiceException;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.EmsPointConfig;
|
||||
import com.xzzn.ems.domain.EmsPointCalcConfig;
|
||||
import com.xzzn.ems.service.IEmsPointConfigService;
|
||||
import com.xzzn.ems.service.IEmsPointCalcConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class EmsPointCalcConfigServiceImpl implements IEmsPointCalcConfigService {
|
||||
private static final Pattern CALC_EXPRESSION_PATTERN = Pattern.compile("^[0-9A-Za-z_+\\-*/().,?:<>=!&|\\s]+$");
|
||||
private static final String CALC_POINT_TYPE = "calc";
|
||||
|
||||
@Autowired
|
||||
private IEmsPointConfigService pointConfigService;
|
||||
|
||||
@Override
|
||||
public List<EmsPointCalcConfig> selectPointCalcConfigList(EmsPointCalcConfig pointCalcConfig) {
|
||||
EmsPointConfig query = toPointConfigQuery(pointCalcConfig);
|
||||
List<EmsPointConfig> configList = pointConfigService.selectPointConfigList(query);
|
||||
if (configList == null || configList.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return configList.stream().map(this::toCalcConfig).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmsPointCalcConfig selectPointCalcConfigById(Long id) {
|
||||
EmsPointConfig config = pointConfigService.selectPointConfigById(id);
|
||||
if (config == null || !CALC_POINT_TYPE.equalsIgnoreCase(config.getPointType())) {
|
||||
return null;
|
||||
}
|
||||
return toCalcConfig(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertPointCalcConfig(EmsPointCalcConfig pointCalcConfig, String operName) {
|
||||
if (pointCalcConfig == null || StringUtils.isBlank(pointCalcConfig.getSiteId())) {
|
||||
throw new ServiceException("站点ID不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(pointCalcConfig.getPointId())) {
|
||||
throw new ServiceException("点位ID不能为空");
|
||||
}
|
||||
validateCalcExpression(pointCalcConfig.getCalcExpression());
|
||||
return pointConfigService.insertPointConfig(toPointConfig(pointCalcConfig), operName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updatePointCalcConfig(EmsPointCalcConfig pointCalcConfig, String operName) {
|
||||
if (pointCalcConfig == null || StringUtils.isBlank(pointCalcConfig.getSiteId())) {
|
||||
throw new ServiceException("站点ID不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(pointCalcConfig.getPointId())) {
|
||||
throw new ServiceException("点位ID不能为空");
|
||||
}
|
||||
validateCalcExpression(pointCalcConfig.getCalcExpression());
|
||||
return pointConfigService.updatePointConfig(toPointConfig(pointCalcConfig), operName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deletePointCalcConfigByIds(Long[] ids) {
|
||||
return pointConfigService.deletePointConfigByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteBySiteId(String siteId) {
|
||||
if (StringUtils.isBlank(siteId)) {
|
||||
return 0;
|
||||
}
|
||||
EmsPointConfig query = new EmsPointConfig();
|
||||
query.setSiteId(siteId);
|
||||
query.setPointType(CALC_POINT_TYPE);
|
||||
List<EmsPointConfig> configList = pointConfigService.selectPointConfigList(query);
|
||||
if (configList == null || configList.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
Long[] ids = configList.stream().map(EmsPointConfig::getId).toArray(Long[]::new);
|
||||
return pointConfigService.deletePointConfigByIds(ids);
|
||||
}
|
||||
|
||||
private void validateCalcExpression(String expression) {
|
||||
if (StringUtils.isBlank(expression)) {
|
||||
throw new ServiceException("计算表达式不能为空");
|
||||
}
|
||||
if (!CALC_EXPRESSION_PATTERN.matcher(expression).matches()) {
|
||||
throw new ServiceException("计算表达式仅支持数字、字母、下划线、空格、运算符和函数语法");
|
||||
}
|
||||
}
|
||||
|
||||
private EmsPointConfig toPointConfig(EmsPointCalcConfig calcConfig) {
|
||||
EmsPointConfig pointConfig = new EmsPointConfig();
|
||||
pointConfig.setId(calcConfig.getId());
|
||||
pointConfig.setPointId(calcConfig.getPointId());
|
||||
pointConfig.setSiteId(calcConfig.getSiteId());
|
||||
pointConfig.setPointType(CALC_POINT_TYPE);
|
||||
pointConfig.setDeviceCategory(calcConfig.getDeviceCategory());
|
||||
pointConfig.setDeviceId("");
|
||||
pointConfig.setRegisterAddress("");
|
||||
pointConfig.setPointName(calcConfig.getPointName());
|
||||
pointConfig.setDataKey(calcConfig.getDataKey());
|
||||
pointConfig.setPointDesc(calcConfig.getPointDesc());
|
||||
pointConfig.setDataUnit(calcConfig.getDataUnit());
|
||||
pointConfig.setCalcExpression(calcConfig.getCalcExpression());
|
||||
pointConfig.setRemark(calcConfig.getRemark());
|
||||
return pointConfig;
|
||||
}
|
||||
|
||||
private EmsPointConfig toPointConfigQuery(EmsPointCalcConfig calcConfig) {
|
||||
EmsPointConfig query = new EmsPointConfig();
|
||||
query.setSiteId(calcConfig == null ? null : calcConfig.getSiteId());
|
||||
query.setDeviceCategory(calcConfig == null ? null : calcConfig.getDeviceCategory());
|
||||
query.setDataKey(calcConfig == null ? null : calcConfig.getDataKey());
|
||||
query.setPointDesc(calcConfig == null ? null : calcConfig.getPointDesc());
|
||||
query.setPointType(CALC_POINT_TYPE);
|
||||
return query;
|
||||
}
|
||||
|
||||
private EmsPointCalcConfig toCalcConfig(EmsPointConfig pointConfig) {
|
||||
EmsPointCalcConfig calcConfig = new EmsPointCalcConfig();
|
||||
calcConfig.setId(pointConfig.getId());
|
||||
calcConfig.setPointId(pointConfig.getPointId());
|
||||
calcConfig.setSiteId(pointConfig.getSiteId());
|
||||
calcConfig.setDeviceCategory(pointConfig.getDeviceCategory());
|
||||
calcConfig.setPointName(pointConfig.getPointName());
|
||||
calcConfig.setDataKey(pointConfig.getDataKey());
|
||||
calcConfig.setPointDesc(pointConfig.getPointDesc());
|
||||
calcConfig.setDataUnit(pointConfig.getDataUnit());
|
||||
calcConfig.setCalcExpression(pointConfig.getCalcExpression());
|
||||
calcConfig.setRemark(pointConfig.getRemark());
|
||||
calcConfig.setCreateBy(pointConfig.getCreateBy());
|
||||
calcConfig.setCreateTime(pointConfig.getCreateTime());
|
||||
calcConfig.setUpdateBy(pointConfig.getUpdateBy());
|
||||
calcConfig.setUpdateTime(pointConfig.getUpdateTime());
|
||||
return calcConfig;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsEnergyPriceConfigMapper;
|
||||
import com.xzzn.ems.mapper.EmsPcsDataMapper;
|
||||
import com.xzzn.ems.service.IEmsStatsReportService;
|
||||
import com.xzzn.ems.service.ISysBizRemarkService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@ -99,6 +100,40 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
private EmsDailyEnergyDataMapper emsDailyEnergyDataMapper;
|
||||
@Autowired
|
||||
private EmsEnergyPriceConfigMapper emsEnergyPriceConfigMapper;
|
||||
@Autowired
|
||||
private ISysBizRemarkService sysBizRemarkService;
|
||||
|
||||
private static final String STATS_REPORT_BIZ_TYPE = "stats_report";
|
||||
private static final String AMMETER_REPORT_KEY = "DBBB";
|
||||
private static final String REVENUE_REPORT_KEY = "SYBB";
|
||||
|
||||
private String buildRemarkBizKey(String siteId, String dataTime) {
|
||||
String safeSiteId = siteId == null ? "" : siteId.trim();
|
||||
String safeDate = dataTime == null ? "" : dataTime.trim();
|
||||
return safeSiteId + "_" + safeDate;
|
||||
}
|
||||
|
||||
private void fillAmmeterRemarks(String siteId, String reportKey, List<AmmeterStatisListVo> rows) {
|
||||
if (CollectionUtils.isEmpty(rows)) {
|
||||
return;
|
||||
}
|
||||
List<String> bizKeys = rows.stream()
|
||||
.map(row -> buildRemarkBizKey(siteId, row.getDataTime()))
|
||||
.collect(Collectors.toList());
|
||||
Map<String, String> remarkMap = sysBizRemarkService.getRemarkMap(STATS_REPORT_BIZ_TYPE, reportKey, bizKeys);
|
||||
rows.forEach(row -> row.setRemark(remarkMap.getOrDefault(buildRemarkBizKey(siteId, row.getDataTime()), "")));
|
||||
}
|
||||
|
||||
private void fillRevenueRemarks(String siteId, String reportKey, List<AmmeterRevenueStatisListVo> rows) {
|
||||
if (CollectionUtils.isEmpty(rows)) {
|
||||
return;
|
||||
}
|
||||
List<String> bizKeys = rows.stream()
|
||||
.map(row -> buildRemarkBizKey(siteId, row.getDataTime()))
|
||||
.collect(Collectors.toList());
|
||||
Map<String, String> remarkMap = sysBizRemarkService.getRemarkMap(STATS_REPORT_BIZ_TYPE, reportKey, bizKeys);
|
||||
rows.forEach(row -> row.setRemark(remarkMap.getOrDefault(buildRemarkBizKey(siteId, row.getDataTime()), "")));
|
||||
}
|
||||
|
||||
// 电量指标
|
||||
@Override
|
||||
@ -374,25 +409,92 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
}
|
||||
dataList.add(totalVo);*/
|
||||
|
||||
fillAmmeterRemarks(requestVo.getSiteId(), AMMETER_REPORT_KEY, dataList);
|
||||
return dataList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AmmeterRevenueStatisListVo> getAmmeterRevenueDataResult(StatisAmmeterDateRequest requestVo) {
|
||||
List<AmmeterRevenueStatisListVo> resultList = emsDailyEnergyDataMapper.getRevenueDataBySiteId(requestVo.getSiteId(),requestVo.getStartTime(),requestVo.getEndTime());
|
||||
log.info("收益报表查询开始, siteId: {}, startTime: {}, endTime: {}",
|
||||
requestVo.getSiteId(), requestVo.getStartTime(), requestVo.getEndTime());
|
||||
List<AmmeterRevenueStatisListVo> resultList = emsDailyEnergyDataMapper.getRevenueDataBySiteId(
|
||||
requestVo.getSiteId(), requestVo.getStartTime(), requestVo.getEndTime());
|
||||
if (CollectionUtils.isEmpty(resultList)) {
|
||||
log.warn("收益报表查询结果为空, siteId: {}, startTime: {}, endTime: {}",
|
||||
requestVo.getSiteId(), requestVo.getStartTime(), requestVo.getEndTime());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//计算每天总收益和当日实际收益(放电总-充电总)
|
||||
resultList.forEach(ammeterRevenue -> {
|
||||
ammeterRevenue.setActiveTotalPrice(ammeterRevenue.getActivePeakPrice().add(ammeterRevenue.getActiveHighPrice()).add(ammeterRevenue.getActiveFlatPrice()).add(ammeterRevenue.getActiveValleyPrice()));
|
||||
ammeterRevenue.setReActiveTotalPrice(ammeterRevenue.getReActivePeakPrice().add(ammeterRevenue.getReActiveHighPrice()).add(ammeterRevenue.getReActiveFlatPrice()).add(ammeterRevenue.getReActiveValleyPrice()));
|
||||
BigDecimal activePeakPrice = nz(ammeterRevenue.getActivePeakPrice());
|
||||
BigDecimal activeHighPrice = nz(ammeterRevenue.getActiveHighPrice());
|
||||
BigDecimal activeFlatPrice = nz(ammeterRevenue.getActiveFlatPrice());
|
||||
BigDecimal activeValleyPrice = nz(ammeterRevenue.getActiveValleyPrice());
|
||||
BigDecimal reActivePeakPrice = nz(ammeterRevenue.getReActivePeakPrice());
|
||||
BigDecimal reActiveHighPrice = nz(ammeterRevenue.getReActiveHighPrice());
|
||||
BigDecimal reActiveFlatPrice = nz(ammeterRevenue.getReActiveFlatPrice());
|
||||
BigDecimal reActiveValleyPrice = nz(ammeterRevenue.getReActiveValleyPrice());
|
||||
|
||||
ammeterRevenue.setActiveTotalPrice(activePeakPrice.add(activeHighPrice).add(activeFlatPrice).add(activeValleyPrice));
|
||||
ammeterRevenue.setReActiveTotalPrice(reActivePeakPrice.add(reActiveHighPrice).add(reActiveFlatPrice).add(reActiveValleyPrice));
|
||||
// 实际收益按“放电总价-充电总价”口径计算
|
||||
ammeterRevenue.setActualRevenue(ammeterRevenue.getReActiveTotalPrice().subtract(ammeterRevenue.getActiveTotalPrice()));
|
||||
});
|
||||
|
||||
int weatherMissingCount = 0;
|
||||
int allPriceZeroCount = 0;
|
||||
for (AmmeterRevenueStatisListVo row : resultList) {
|
||||
String weatherDesc = row.getWeatherDesc();
|
||||
if (weatherDesc == null || weatherDesc.trim().isEmpty() || "--".equals(weatherDesc.trim())) {
|
||||
weatherMissingCount++;
|
||||
}
|
||||
boolean allPriceZero = safeCompareToZero(row.getActivePeakPrice())
|
||||
&& safeCompareToZero(row.getActiveHighPrice())
|
||||
&& safeCompareToZero(row.getActiveFlatPrice())
|
||||
&& safeCompareToZero(row.getActiveValleyPrice())
|
||||
&& safeCompareToZero(row.getReActivePeakPrice())
|
||||
&& safeCompareToZero(row.getReActiveHighPrice())
|
||||
&& safeCompareToZero(row.getReActiveFlatPrice())
|
||||
&& safeCompareToZero(row.getReActiveValleyPrice());
|
||||
if (allPriceZero) {
|
||||
allPriceZeroCount++;
|
||||
}
|
||||
log.info("收益报表明细, date: {}, dayType: {}, weather: {}, charge[尖:{} 峰:{} 平:{} 谷:{} 总:{}], discharge[尖:{} 峰:{} 平:{} 谷:{} 总:{}], actualRevenue: {}",
|
||||
row.getDataTime(),
|
||||
row.getDayType(),
|
||||
row.getWeatherDesc(),
|
||||
row.getActivePeakPrice(),
|
||||
row.getActiveHighPrice(),
|
||||
row.getActiveFlatPrice(),
|
||||
row.getActiveValleyPrice(),
|
||||
row.getActiveTotalPrice(),
|
||||
row.getReActivePeakPrice(),
|
||||
row.getReActiveHighPrice(),
|
||||
row.getReActiveFlatPrice(),
|
||||
row.getReActiveValleyPrice(),
|
||||
row.getReActiveTotalPrice(),
|
||||
row.getActualRevenue());
|
||||
}
|
||||
log.info("收益报表查询完成, siteId: {}, startTime: {}, endTime: {}, totalRows: {}, weatherMissingRows: {}, allPriceZeroRows: {}",
|
||||
requestVo.getSiteId(),
|
||||
requestVo.getStartTime(),
|
||||
requestVo.getEndTime(),
|
||||
resultList.size(),
|
||||
weatherMissingCount,
|
||||
allPriceZeroCount);
|
||||
|
||||
fillRevenueRemarks(requestVo.getSiteId(), REVENUE_REPORT_KEY, resultList);
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private boolean safeCompareToZero(BigDecimal value) {
|
||||
return value == null || value.compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
private BigDecimal nz(BigDecimal value) {
|
||||
return value == null ? BigDecimal.ZERO : value;
|
||||
}
|
||||
|
||||
public static AmmeterRevenueStatisListVo calculateDailyBill(AmmeterStatisListVo ammeter, List<EnergyPriceConfigVo> priceList) {
|
||||
AmmeterRevenueStatisListVo ammeterRevenue = new AmmeterRevenueStatisListVo();
|
||||
ammeterRevenue.setDataTime(ammeter.getDataTime());
|
||||
@ -642,6 +744,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
cell3.setCellValue("放电量");
|
||||
Cell cell4 = row1.createCell(11);
|
||||
cell4.setCellValue("效率");
|
||||
Cell cell5Top = row1.createCell(12);
|
||||
cell5Top.setCellValue("备注");
|
||||
|
||||
// 合并充电量列
|
||||
CellRangeAddress mergeRegion1 = new CellRangeAddress(0, 0, 1, 5);
|
||||
@ -677,6 +781,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
cell15.setCellValue("总");
|
||||
Cell cell16 = row2.createCell(11);
|
||||
cell16.setCellValue("");
|
||||
Cell cell17 = row2.createCell(12);
|
||||
cell17.setCellValue("备注");
|
||||
|
||||
// 设置背景颜色
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
@ -756,6 +862,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
dataCell11.setCellValue(ammeterStatisVo.getReActiveTotalKwh().doubleValue());
|
||||
Cell dataCell12 = dataRow.createCell(11);
|
||||
dataCell12.setCellValue(ammeterStatisVo.getEffect().doubleValue());
|
||||
Cell dataCell13 = dataRow.createCell(12);
|
||||
dataCell13.setCellValue(ammeterStatisVo.getRemark() == null ? "" : ammeterStatisVo.getRemark());
|
||||
|
||||
// 根据行号设置背景色
|
||||
if (i % 2 == 0) {
|
||||
@ -798,19 +906,21 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
Row row1 = sheet.createRow(0);
|
||||
Cell cell1 = row1.createCell(0);
|
||||
cell1.setCellValue("汇总");
|
||||
Cell cell2 = row1.createCell(1);
|
||||
Cell cell2 = row1.createCell(3);
|
||||
cell2.setCellValue("充电价格");
|
||||
Cell cell3 = row1.createCell(6);
|
||||
Cell cell3 = row1.createCell(8);
|
||||
cell3.setCellValue("放电价格");
|
||||
Cell cell4 = row1.createCell(11);
|
||||
cell4.setCellValue("");
|
||||
Cell cell4 = row1.createCell(13);
|
||||
cell4.setCellValue("实际收益");
|
||||
Cell cell5Top = row1.createCell(14);
|
||||
cell5Top.setCellValue("备注");
|
||||
|
||||
// 合并充电量列
|
||||
CellRangeAddress mergeRegion1 = new CellRangeAddress(0, 0, 1, 5);
|
||||
CellRangeAddress mergeRegion1 = new CellRangeAddress(0, 0, 3, 7);
|
||||
sheet.addMergedRegion(mergeRegion1);
|
||||
|
||||
// 合并放电量列
|
||||
CellRangeAddress mergeRegion2 = new CellRangeAddress(0, 0, 6, 10);
|
||||
CellRangeAddress mergeRegion2 = new CellRangeAddress(0, 0, 8, 12);
|
||||
sheet.addMergedRegion(mergeRegion2);
|
||||
|
||||
// 设置第二行
|
||||
@ -818,27 +928,33 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
Cell cell5 = row2.createCell(0);
|
||||
cell5.setCellValue("日期");
|
||||
Cell cell6 = row2.createCell(1);
|
||||
cell6.setCellValue("尖");
|
||||
cell6.setCellValue("日期类型");
|
||||
Cell cell7 = row2.createCell(2);
|
||||
cell7.setCellValue("峰");
|
||||
cell7.setCellValue("天气情况");
|
||||
Cell cell8 = row2.createCell(3);
|
||||
cell8.setCellValue("平");
|
||||
cell8.setCellValue("尖");
|
||||
Cell cell9 = row2.createCell(4);
|
||||
cell9.setCellValue("谷");
|
||||
cell9.setCellValue("峰");
|
||||
Cell cell10 = row2.createCell(5);
|
||||
cell10.setCellValue("总");
|
||||
cell10.setCellValue("平");
|
||||
Cell cell11 = row2.createCell(6);
|
||||
cell11.setCellValue("尖");
|
||||
cell11.setCellValue("谷");
|
||||
Cell cell12 = row2.createCell(7);
|
||||
cell12.setCellValue("峰");
|
||||
cell12.setCellValue("总");
|
||||
Cell cell13 = row2.createCell(8);
|
||||
cell13.setCellValue("平");
|
||||
cell13.setCellValue("尖");
|
||||
Cell cell14 = row2.createCell(9);
|
||||
cell14.setCellValue("谷");
|
||||
cell14.setCellValue("峰");
|
||||
Cell cell15 = row2.createCell(10);
|
||||
cell15.setCellValue("总");
|
||||
cell15.setCellValue("平");
|
||||
Cell cell16 = row2.createCell(11);
|
||||
cell16.setCellValue("实际收益");
|
||||
cell16.setCellValue("谷");
|
||||
Cell cell17 = row2.createCell(12);
|
||||
cell17.setCellValue("总");
|
||||
Cell cell18 = row2.createCell(13);
|
||||
cell18.setCellValue("实际收益");
|
||||
Cell cell19 = row2.createCell(14);
|
||||
cell19.setCellValue("备注");
|
||||
|
||||
// 设置背景颜色
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
@ -908,27 +1024,33 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
Cell dataCell1 = dataRow.createCell(0);
|
||||
dataCell1.setCellValue(ammeterRevenueStatisVo.getDataTime());
|
||||
Cell dataCell2 = dataRow.createCell(1);
|
||||
dataCell2.setCellValue(ammeterRevenueStatisVo.getActivePeakPrice().doubleValue());
|
||||
dataCell2.setCellValue(ammeterRevenueStatisVo.getDayType() == null ? "" : ammeterRevenueStatisVo.getDayType());
|
||||
Cell dataCell3 = dataRow.createCell(2);
|
||||
dataCell3.setCellValue(ammeterRevenueStatisVo.getActiveHighPrice().doubleValue());
|
||||
dataCell3.setCellValue(ammeterRevenueStatisVo.getWeatherDesc() == null ? "" : ammeterRevenueStatisVo.getWeatherDesc());
|
||||
Cell dataCell4 = dataRow.createCell(3);
|
||||
dataCell4.setCellValue(ammeterRevenueStatisVo.getActiveFlatPrice().doubleValue());
|
||||
dataCell4.setCellValue(ammeterRevenueStatisVo.getActivePeakPrice().doubleValue());
|
||||
Cell dataCell5 = dataRow.createCell(4);
|
||||
dataCell5.setCellValue(ammeterRevenueStatisVo.getActiveValleyPrice().doubleValue());
|
||||
dataCell5.setCellValue(ammeterRevenueStatisVo.getActiveHighPrice().doubleValue());
|
||||
Cell dataCell6 = dataRow.createCell(5);
|
||||
dataCell6.setCellValue(ammeterRevenueStatisVo.getActiveTotalPrice().doubleValue());
|
||||
dataCell6.setCellValue(ammeterRevenueStatisVo.getActiveFlatPrice().doubleValue());
|
||||
Cell dataCell7 = dataRow.createCell(6);
|
||||
dataCell7.setCellValue(ammeterRevenueStatisVo.getReActivePeakPrice().doubleValue());
|
||||
dataCell7.setCellValue(ammeterRevenueStatisVo.getActiveValleyPrice().doubleValue());
|
||||
Cell dataCell8 = dataRow.createCell(7);
|
||||
dataCell8.setCellValue(ammeterRevenueStatisVo.getReActiveHighPrice().doubleValue());
|
||||
dataCell8.setCellValue(ammeterRevenueStatisVo.getActiveTotalPrice().doubleValue());
|
||||
Cell dataCell9 = dataRow.createCell(8);
|
||||
dataCell9.setCellValue(ammeterRevenueStatisVo.getReActiveFlatPrice().doubleValue());
|
||||
dataCell9.setCellValue(ammeterRevenueStatisVo.getReActivePeakPrice().doubleValue());
|
||||
Cell dataCell10 = dataRow.createCell(9);
|
||||
dataCell10.setCellValue(ammeterRevenueStatisVo.getReActiveValleyPrice().doubleValue());
|
||||
dataCell10.setCellValue(ammeterRevenueStatisVo.getReActiveHighPrice().doubleValue());
|
||||
Cell dataCell11 = dataRow.createCell(10);
|
||||
dataCell11.setCellValue(ammeterRevenueStatisVo.getReActiveValleyPrice().doubleValue());
|
||||
dataCell11.setCellValue(ammeterRevenueStatisVo.getReActiveFlatPrice().doubleValue());
|
||||
Cell dataCell12 = dataRow.createCell(11);
|
||||
dataCell12.setCellValue(ammeterRevenueStatisVo.getActualRevenue().doubleValue());
|
||||
dataCell12.setCellValue(ammeterRevenueStatisVo.getReActiveValleyPrice().doubleValue());
|
||||
Cell dataCell13 = dataRow.createCell(12);
|
||||
dataCell13.setCellValue(ammeterRevenueStatisVo.getReActiveTotalPrice().doubleValue());
|
||||
Cell dataCell14 = dataRow.createCell(13);
|
||||
dataCell14.setCellValue(ammeterRevenueStatisVo.getActualRevenue().doubleValue());
|
||||
Cell dataCell15 = dataRow.createCell(14);
|
||||
dataCell15.setCellValue(ammeterRevenueStatisVo.getRemark() == null ? "" : ammeterRevenueStatisVo.getRemark());
|
||||
|
||||
// 根据行号设置背景色
|
||||
if (i % 2 == 0) {
|
||||
@ -961,27 +1083,33 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService
|
||||
Cell lastRowCell1 = lastRow.createCell(0);
|
||||
lastRowCell1.setCellValue("合计");
|
||||
Cell lastRowCell2 = lastRow.createCell(1);
|
||||
lastRowCell2.setCellValue(activePeakPrice.doubleValue());
|
||||
lastRowCell2.setCellValue("-");
|
||||
Cell lastRowCell3 = lastRow.createCell(2);
|
||||
lastRowCell3.setCellValue(activeHighPrice.doubleValue());
|
||||
lastRowCell3.setCellValue("-");
|
||||
Cell lastRowCell4 = lastRow.createCell(3);
|
||||
lastRowCell4.setCellValue(activeFlatPrice.doubleValue());
|
||||
lastRowCell4.setCellValue(activePeakPrice.doubleValue());
|
||||
Cell lastRowCell5 = lastRow.createCell(4);
|
||||
lastRowCell5.setCellValue(activeValleyPrice.doubleValue());
|
||||
lastRowCell5.setCellValue(activeHighPrice.doubleValue());
|
||||
Cell lastRowCell6 = lastRow.createCell(5);
|
||||
lastRowCell6.setCellValue(activeTotalPrice.doubleValue());
|
||||
lastRowCell6.setCellValue(activeFlatPrice.doubleValue());
|
||||
Cell lastRowCell7 = lastRow.createCell(6);
|
||||
lastRowCell7.setCellValue(reActivePeakPrice.doubleValue());
|
||||
lastRowCell7.setCellValue(activeValleyPrice.doubleValue());
|
||||
Cell lastRowCell8 = lastRow.createCell(7);
|
||||
lastRowCell8.setCellValue(reActiveHighPrice.doubleValue());
|
||||
lastRowCell8.setCellValue(activeTotalPrice.doubleValue());
|
||||
Cell lastRowCell9 = lastRow.createCell(8);
|
||||
lastRowCell9.setCellValue(reActiveFlatPrice.doubleValue());
|
||||
lastRowCell9.setCellValue(reActivePeakPrice.doubleValue());
|
||||
Cell lastRowCell10 = lastRow.createCell(9);
|
||||
lastRowCell10.setCellValue(reActiveValleyPrice.doubleValue());
|
||||
lastRowCell10.setCellValue(reActiveHighPrice.doubleValue());
|
||||
Cell lastRowCell11 = lastRow.createCell(10);
|
||||
lastRowCell11.setCellValue(reActiveTotalPrice.doubleValue());
|
||||
lastRowCell11.setCellValue(reActiveFlatPrice.doubleValue());
|
||||
Cell lastRowCell12 = lastRow.createCell(11);
|
||||
lastRowCell12.setCellValue(actualRevenue.doubleValue());
|
||||
lastRowCell12.setCellValue(reActiveValleyPrice.doubleValue());
|
||||
Cell lastRowCell13 = lastRow.createCell(12);
|
||||
lastRowCell13.setCellValue(reActiveTotalPrice.doubleValue());
|
||||
Cell lastRowCell14 = lastRow.createCell(13);
|
||||
lastRowCell14.setCellValue(actualRevenue.doubleValue());
|
||||
Cell lastRowCell15 = lastRow.createCell(14);
|
||||
lastRowCell15.setCellValue("");
|
||||
Iterator<Cell> lastRowCellIterator = lastRow.cellIterator();
|
||||
while (lastRowCellIterator.hasNext()) {
|
||||
int i = lastRowCellIterator.next().getColumnIndex();
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
package com.xzzn.ems.service.impl;
|
||||
|
||||
import com.xzzn.common.utils.DateUtils;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.EmsStrategyRuntimeConfig;
|
||||
import com.xzzn.ems.mapper.EmsStrategyRuntimeConfigMapper;
|
||||
import com.xzzn.ems.service.IEmsStrategyRuntimeConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 策略运行参数配置Service业务层处理
|
||||
*
|
||||
* @author xzzn
|
||||
* @date 2026-02-13
|
||||
*/
|
||||
@Service
|
||||
public class EmsStrategyRuntimeConfigServiceImpl implements IEmsStrategyRuntimeConfigService {
|
||||
|
||||
private static final BigDecimal DEFAULT_SOC_DOWN = BigDecimal.ZERO;
|
||||
private static final BigDecimal DEFAULT_SOC_UP = new BigDecimal("100");
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_THRESHOLD = new BigDecimal("30");
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_RANGE_PERCENT = new BigDecimal("20");
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_UP = new BigDecimal("100");
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_POWER_DOWN_PERCENT = new BigDecimal("10");
|
||||
private static final BigDecimal DEFAULT_ANTI_REVERSE_HARD_STOP_THRESHOLD = new BigDecimal("20");
|
||||
private static final BigDecimal DEFAULT_POWER_SET_MULTIPLIER = new BigDecimal("10");
|
||||
private static final Integer DEFAULT_PROTECT_INTERVENE_ENABLE = 1;
|
||||
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";
|
||||
|
||||
@Autowired
|
||||
private EmsStrategyRuntimeConfigMapper runtimeConfigMapper;
|
||||
|
||||
@Override
|
||||
public EmsStrategyRuntimeConfig getBySiteId(String siteId) {
|
||||
EmsStrategyRuntimeConfig config = runtimeConfigMapper.selectBySiteId(siteId);
|
||||
if (config == null) {
|
||||
return buildDefaultConfig(siteId);
|
||||
}
|
||||
fillMissingWithDefault(config, siteId);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int saveBySiteId(EmsStrategyRuntimeConfig config) {
|
||||
fillMissingWithDefault(config, config.getSiteId());
|
||||
EmsStrategyRuntimeConfig exist = runtimeConfigMapper.selectBySiteId(config.getSiteId());
|
||||
if (exist == null) {
|
||||
config.setCreateTime(DateUtils.getNowDate());
|
||||
return runtimeConfigMapper.insert(config);
|
||||
}
|
||||
config.setUpdateTime(DateUtils.getNowDate());
|
||||
return runtimeConfigMapper.updateBySiteId(config);
|
||||
}
|
||||
|
||||
private EmsStrategyRuntimeConfig buildDefaultConfig(String siteId) {
|
||||
EmsStrategyRuntimeConfig config = new EmsStrategyRuntimeConfig();
|
||||
fillMissingWithDefault(config, siteId);
|
||||
return config;
|
||||
}
|
||||
|
||||
private void fillMissingWithDefault(EmsStrategyRuntimeConfig config, String siteId) {
|
||||
if (StringUtils.isNotEmpty(siteId)) {
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,6 +92,9 @@ public class EmsStrategyTempServiceImpl implements IEmsStrategyTempService
|
||||
temp.setStartTime(timeConfig.getStartTime());
|
||||
temp.setEndTime(timeConfig.getEndTime());
|
||||
temp.setChargeDischargePower(timeConfig.getChargeDischargePower());
|
||||
// 每个时间段可独立配置SOC上下限;为空时兼容旧的模板级配置
|
||||
temp.setSdcDown(timeConfig.getSdcDown() != null ? timeConfig.getSdcDown() : publicTemp.getSdcDown());
|
||||
temp.setSdcUp(timeConfig.getSdcUp() != null ? timeConfig.getSdcUp() : publicTemp.getSdcUp());
|
||||
temp.setChargeStatus(timeConfig.getChargeStatus());
|
||||
emsStrategyTempMapper.insertEmsStrategyTemp(temp);
|
||||
}
|
||||
|
||||
@ -0,0 +1,199 @@
|
||||
package com.xzzn.ems.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.xzzn.common.exception.ServiceException;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.common.utils.http.HttpUtils;
|
||||
import com.xzzn.ems.config.WeatherApiProperties;
|
||||
import com.xzzn.ems.domain.EmsSiteSetting;
|
||||
import com.xzzn.ems.domain.vo.StatisAmmeterDateRequest;
|
||||
import com.xzzn.ems.domain.vo.WeatherSyncResultVo;
|
||||
import com.xzzn.ems.mapper.EmsSiteSettingMapper;
|
||||
import com.xzzn.ems.mapper.EmsSiteWeatherDayMapper;
|
||||
import com.xzzn.ems.service.IEmsWeatherSyncService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Service
|
||||
public class EmsWeatherSyncServiceImpl implements IEmsWeatherSyncService {
|
||||
private static final Logger log = LoggerFactory.getLogger(EmsWeatherSyncServiceImpl.class);
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
@Autowired
|
||||
private WeatherApiProperties weatherApiProperties;
|
||||
@Autowired
|
||||
private EmsSiteSettingMapper emsSiteSettingMapper;
|
||||
@Autowired
|
||||
private EmsSiteWeatherDayMapper emsSiteWeatherDayMapper;
|
||||
|
||||
@Override
|
||||
public WeatherSyncResultVo syncWeatherByDateRange(StatisAmmeterDateRequest requestVo) {
|
||||
if (!weatherApiProperties.isEnabled()) {
|
||||
throw new ServiceException("天气同步未启用,请先设置 weather.api.enabled=true");
|
||||
}
|
||||
if (requestVo == null || StringUtils.isEmpty(requestVo.getSiteId())
|
||||
|| StringUtils.isEmpty(requestVo.getStartTime())
|
||||
|| StringUtils.isEmpty(requestVo.getEndTime())) {
|
||||
throw new ServiceException("siteId、startTime、endTime 不能为空");
|
||||
}
|
||||
LocalDate startDate = parseDate(requestVo.getStartTime(), "startTime");
|
||||
LocalDate endDate = parseDate(requestVo.getEndTime(), "endTime");
|
||||
if (endDate.isBefore(startDate)) {
|
||||
throw new ServiceException("endTime 不能早于 startTime");
|
||||
}
|
||||
|
||||
EmsSiteSetting siteSetting = emsSiteSettingMapper.selectEmsSiteSettingBySiteId(requestVo.getSiteId());
|
||||
if (siteSetting == null) {
|
||||
throw new ServiceException("未找到站点配置,siteId=" + requestVo.getSiteId());
|
||||
}
|
||||
BigDecimal latitude = siteSetting.getLatitude();
|
||||
BigDecimal longitude = siteSetting.getLongitude();
|
||||
if (latitude == null || longitude == null) {
|
||||
throw new ServiceException("站点缺少经纬度配置,siteId=" + requestVo.getSiteId());
|
||||
}
|
||||
|
||||
String url = buildWeatherUrl(latitude, longitude, startDate, endDate);
|
||||
String response = HttpUtils.sendGet(url);
|
||||
if (StringUtils.isEmpty(response)) {
|
||||
throw new ServiceException("调用天气接口失败,返回为空");
|
||||
}
|
||||
JSONObject root = JSONObject.parseObject(response);
|
||||
JSONObject daily = root == null ? null : root.getJSONObject("daily");
|
||||
JSONArray dates = daily == null ? null : daily.getJSONArray("time");
|
||||
JSONArray codes = daily == null ? null : daily.getJSONArray("weather_code");
|
||||
if (dates == null || codes == null || dates.size() == 0 || dates.size() != codes.size()) {
|
||||
throw new ServiceException("天气接口返回格式异常,daily.time/weather_code 不可用");
|
||||
}
|
||||
|
||||
WeatherSyncResultVo resultVo = new WeatherSyncResultVo();
|
||||
resultVo.setSiteId(requestVo.getSiteId());
|
||||
resultVo.setStartTime(requestVo.getStartTime());
|
||||
resultVo.setEndTime(requestVo.getEndTime());
|
||||
resultVo.setTotalDays(dates.size());
|
||||
|
||||
int updated = 0;
|
||||
int inserted = 0;
|
||||
for (int i = 0; i < dates.size(); i++) {
|
||||
String dateStr = dates.getString(i);
|
||||
int weatherCode = codes.getIntValue(i);
|
||||
String weatherDesc = mapWeatherDesc(weatherCode);
|
||||
|
||||
int updateRows = emsSiteWeatherDayMapper.updateWeatherDesc(
|
||||
requestVo.getSiteId(), dateStr, weatherDesc, weatherCode);
|
||||
if (updateRows > 0) {
|
||||
updated++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int count = emsSiteWeatherDayMapper.selectCountBySiteAndDate(requestVo.getSiteId(), dateStr);
|
||||
if (count == 0) {
|
||||
emsSiteWeatherDayMapper.insertSiteWeatherDay(
|
||||
requestVo.getSiteId(), dateStr, weatherDesc, weatherCode, "open-meteo");
|
||||
inserted++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 理论上不会到这里,防御性兜底再更新一次
|
||||
updated += emsSiteWeatherDayMapper.updateWeatherDesc(
|
||||
requestVo.getSiteId(), dateStr, weatherDesc, weatherCode);
|
||||
}
|
||||
resultVo.setUpdatedDays(updated);
|
||||
resultVo.setInsertedDays(inserted);
|
||||
resultVo.setSuccessDays(updated + inserted);
|
||||
resultVo.setMessage("天气同步完成");
|
||||
|
||||
log.info("天气同步完成, siteId: {}, startTime: {}, endTime: {}, totalDays: {}, updatedDays: {}, insertedDays: {}",
|
||||
requestVo.getSiteId(), requestVo.getStartTime(), requestVo.getEndTime(),
|
||||
resultVo.getTotalDays(), updated, inserted);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
private LocalDate parseDate(String value, String fieldName) {
|
||||
try {
|
||||
return LocalDate.parse(value, DATE_FORMATTER);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(fieldName + " 格式错误,应为 yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
private String buildWeatherUrl(BigDecimal latitude, BigDecimal longitude, LocalDate startDate, LocalDate endDate) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(weatherApiProperties.getBaseUrl())
|
||||
.append("?latitude=").append(latitude.stripTrailingZeros().toPlainString())
|
||||
.append("&longitude=").append(longitude.stripTrailingZeros().toPlainString())
|
||||
.append("&start_date=").append(startDate.format(DATE_FORMATTER))
|
||||
.append("&end_date=").append(endDate.format(DATE_FORMATTER))
|
||||
.append("&daily=weather_code")
|
||||
.append("&timezone=").append(urlEncode(weatherApiProperties.getTimezone()));
|
||||
if (StringUtils.isNotEmpty(weatherApiProperties.getApiKey())) {
|
||||
builder.append("&apikey=").append(urlEncode(weatherApiProperties.getApiKey()));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String urlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ServiceException("URL 编码失败");
|
||||
}
|
||||
}
|
||||
|
||||
private String mapWeatherDesc(int weatherCode) {
|
||||
switch (weatherCode) {
|
||||
case 0:
|
||||
return "晴";
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return "多云";
|
||||
case 45:
|
||||
case 48:
|
||||
return "雾";
|
||||
case 51:
|
||||
case 53:
|
||||
case 55:
|
||||
return "毛毛雨";
|
||||
case 56:
|
||||
case 57:
|
||||
return "冻毛毛雨";
|
||||
case 61:
|
||||
case 63:
|
||||
case 65:
|
||||
return "雨";
|
||||
case 66:
|
||||
case 67:
|
||||
return "冻雨";
|
||||
case 71:
|
||||
case 73:
|
||||
case 75:
|
||||
return "雪";
|
||||
case 77:
|
||||
return "雪粒";
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
return "阵雨";
|
||||
case 85:
|
||||
case 86:
|
||||
return "阵雪";
|
||||
case 95:
|
||||
return "雷暴";
|
||||
case 96:
|
||||
case 99:
|
||||
return "雷暴伴冰雹";
|
||||
default:
|
||||
return "未知(" + weatherCode + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -49,15 +49,12 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
if (siteIds == null || siteIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String deviceCategory = request.getDeviceCategory();
|
||||
String deviceId = request.getDeviceId();
|
||||
if ((deviceCategory == null || "".equals(deviceCategory.trim()))
|
||||
&& (deviceId == null || "".equals(deviceId.trim()))) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return emsPointConfigMapper.getPointNameList(siteIds, deviceCategory, deviceId, request.getPointName());
|
||||
return emsPointConfigMapper.getPointNameList(
|
||||
siteIds,
|
||||
request.getDeviceCategory(),
|
||||
request.getDeviceId(),
|
||||
request.getPointName()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -94,15 +91,10 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
}
|
||||
|
||||
String deviceCategory = request.getDeviceCategory();
|
||||
String requestDeviceId = request.getDeviceId();
|
||||
if ((deviceCategory == null || "".equals(deviceCategory.trim()))
|
||||
&& (requestDeviceId == null || "".equals(requestDeviceId.trim()))
|
||||
) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> pointIds = resolvePointIds(request);
|
||||
|
||||
List<String> pointNames = resolvePointNames(request);
|
||||
if (pointNames.isEmpty()) {
|
||||
if (pointIds.isEmpty() && pointNames.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@ -114,17 +106,19 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
endDate = DateUtils.adjustToEndOfDay(request.getEndDate());
|
||||
}
|
||||
|
||||
List<String> selectedDeviceIds = resolveSelectedDeviceIds(request);
|
||||
List<String> selectedDeviceIds = pointIds.isEmpty() ? resolveSelectedDeviceIds(request) : Collections.emptyList();
|
||||
List<EmsPointConfig> pointConfigs = emsPointConfigMapper.getConfigListForGeneralQuery(
|
||||
siteIds, deviceCategory, pointNames, selectedDeviceIds
|
||||
siteIds, deviceCategory, pointIds, pointNames, selectedDeviceIds
|
||||
);
|
||||
if (pointConfigs == null || pointConfigs.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<String, String> selectedPointNameById = buildSelectedPointNameById(request);
|
||||
|
||||
List<GeneralQueryDataVo> dataVoList = new ArrayList<>();
|
||||
for (EmsPointConfig pointConfig : pointConfigs) {
|
||||
dataVoList.addAll(queryPointCurve(pointConfig, request.getDataUnit(), startDate, endDate));
|
||||
String selectedPointName = selectedPointNameById.get(resolveInfluxPointKey(pointConfig));
|
||||
dataVoList.addAll(queryPointCurve(pointConfig, request.getDataUnit(), startDate, endDate, selectedPointName));
|
||||
}
|
||||
|
||||
if (dataVoList.isEmpty()) {
|
||||
@ -154,6 +148,19 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
return names.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> resolvePointIds(PointNameRequest request) {
|
||||
List<String> ids = new ArrayList<>();
|
||||
if (request.getPointIds() != null && !request.getPointIds().isEmpty()) {
|
||||
ids.addAll(request.getPointIds());
|
||||
} else if (request.getPointId() != null && !"".equals(request.getPointId().trim())) {
|
||||
ids.addAll(Arrays.stream(request.getPointId().split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return ids.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> resolveSelectedDeviceIds(PointNameRequest request) {
|
||||
List<String> selected = new ArrayList<>();
|
||||
if (request.getDeviceId() != null && !"".equals(request.getDeviceId().trim())) {
|
||||
@ -175,12 +182,18 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
return selected.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<GeneralQueryDataVo> queryPointCurve(EmsPointConfig config, int dataUnit, Date startDate, Date endDate) {
|
||||
if (config == null || config.getSiteId() == null || config.getDeviceId() == null || config.getDataKey() == null) {
|
||||
private List<GeneralQueryDataVo> queryPointCurve(EmsPointConfig config, int dataUnit, Date startDate, Date endDate,
|
||||
String selectedPointName) {
|
||||
if (config == null || config.getSiteId() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<InfluxPointDataWriter.PointValue> values = influxPointDataWriter.queryCurveData(
|
||||
config.getSiteId(), config.getDeviceId(), config.getDataKey(), startDate, endDate
|
||||
String influxPointKey = resolveInfluxPointKey(config);
|
||||
if (influxPointKey == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 与点位列表曲线保持一致:按 siteId + pointKey 查询,避免 deviceId 维度导致综合查询漏数
|
||||
List<InfluxPointDataWriter.PointValue> values = influxPointDataWriter.queryCurveDataByPointKey(
|
||||
config.getSiteId(), influxPointKey, startDate, endDate
|
||||
);
|
||||
if (values == null || values.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
@ -193,7 +206,7 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
}
|
||||
|
||||
List<GeneralQueryDataVo> result = new ArrayList<>();
|
||||
String displayDeviceId = buildDisplayDeviceId(config);
|
||||
String displayDeviceId = buildDisplayDeviceId(config, selectedPointName);
|
||||
for (Map.Entry<String, Object> entry : latestByBucket.entrySet()) {
|
||||
GeneralQueryDataVo vo = new GeneralQueryDataVo();
|
||||
vo.setSiteId(config.getSiteId());
|
||||
@ -205,10 +218,42 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
return result;
|
||||
}
|
||||
|
||||
private String buildDisplayDeviceId(EmsPointConfig config) {
|
||||
private String resolveInfluxPointKey(EmsPointConfig config) {
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
if (config.getPointId() != null && !"".equals(config.getPointId().trim())) {
|
||||
return config.getPointId().trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String buildDisplayDeviceId(EmsPointConfig config, String selectedPointName) {
|
||||
if (selectedPointName != null && !"".equals(selectedPointName.trim())) {
|
||||
return selectedPointName.trim();
|
||||
}
|
||||
String pointName = config.getPointName() == null || "".equals(config.getPointName().trim())
|
||||
? config.getDataKey() : config.getPointName().trim();
|
||||
return config.getDeviceId() + "-" + pointName;
|
||||
return pointName;
|
||||
}
|
||||
|
||||
private Map<String, String> buildSelectedPointNameById(PointNameRequest request) {
|
||||
Map<String, String> selectedNameById = new HashMap<>();
|
||||
if (request == null || request.getPointIds() == null || request.getPointNames() == null) {
|
||||
return selectedNameById;
|
||||
}
|
||||
List<String> pointIds = request.getPointIds();
|
||||
List<String> pointNames = request.getPointNames();
|
||||
int size = Math.min(pointIds.size(), pointNames.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
String pointId = pointIds.get(i);
|
||||
String pointName = pointNames.get(i);
|
||||
if (pointId == null || "".equals(pointId.trim()) || pointName == null || "".equals(pointName.trim())) {
|
||||
continue;
|
||||
}
|
||||
selectedNameById.put(pointId.trim(), pointName.trim());
|
||||
}
|
||||
return selectedNameById;
|
||||
}
|
||||
|
||||
private String formatByDataUnit(Date dataTime, int dataUnit) {
|
||||
@ -432,7 +477,8 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
|
||||
// 4. 构建DeviceItem
|
||||
return new DevicePointDataList(deviceId, pointValueList,parentDeviceId,
|
||||
stats.max, stats.min,stats.avg,stats.diff,stats.maxDate,stats.minDate);
|
||||
stats.max, stats.min,stats.avg,stats.diff,stats.maxDate,stats.minDate,
|
||||
stats.q1, stats.median, stats.q3);
|
||||
})// 关键排序步骤:先按deviceId升序,再按parentDeviceId升序
|
||||
.sorted(
|
||||
Comparator.comparing(DevicePointDataList::getDeviceId) // 第一排序键:deviceId
|
||||
@ -468,7 +514,8 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
Stats stats = clacStats(deviceDataList);
|
||||
|
||||
return new DevicePointDataList(deviceId, deviceDataList,null,
|
||||
stats.max, stats.min,stats.avg,stats.diff,stats.maxDate,stats.minDate);
|
||||
stats.max, stats.min,stats.avg,stats.diff,stats.maxDate,stats.minDate,
|
||||
stats.q1, stats.median, stats.q3);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@ -491,7 +538,7 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (validPairs.isEmpty()) {
|
||||
return new Stats(null, null, null, null, null, null);
|
||||
return new Stats(null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
// 计算最大最小值
|
||||
Optional<ValueTimePair> maxPair = validPairs.stream().max((p1, p2) -> p1.value.compareTo(p2.value));
|
||||
@ -501,8 +548,17 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
BigDecimal avgValue = sum.divide(BigDecimal.valueOf(validPairs.size()), 4, BigDecimal.ROUND_HALF_UP);
|
||||
// 增量数据,计算差值
|
||||
BigDecimal diff = maxPair.get().value.subtract(minPair.get().value);
|
||||
// 计算分位数统计值
|
||||
List<BigDecimal> sortedValues = validPairs.stream()
|
||||
.map(pair -> pair.value)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
BoxPlotData boxStats = calculateBoxPlotData(sortedValues);
|
||||
|
||||
return new Stats(maxPair.get().value,minPair.get().value,avgValue,diff,maxPair.get().time,minPair.get().time);
|
||||
return new Stats(maxPair.get().value,minPair.get().value,avgValue,diff,maxPair.get().time,minPair.get().time,
|
||||
boxStats == null ? null : boxStats.q1,
|
||||
boxStats == null ? null : boxStats.median,
|
||||
boxStats == null ? null : boxStats.q3);
|
||||
}
|
||||
|
||||
private BigDecimal convertToBigDecimal(Object pointValue) {
|
||||
@ -755,15 +811,22 @@ public class GeneralQueryServiceImpl implements IGeneralQueryService
|
||||
private final String minDate;
|
||||
private final BigDecimal avg;
|
||||
private final BigDecimal diff;
|
||||
private final BigDecimal q1;
|
||||
private final BigDecimal median;
|
||||
private final BigDecimal q3;
|
||||
|
||||
public Stats(BigDecimal max, BigDecimal min, BigDecimal avg, BigDecimal diff,
|
||||
String maxDate, String minDate) {
|
||||
String maxDate, String minDate,
|
||||
BigDecimal q1, BigDecimal median, BigDecimal q3) {
|
||||
this.max = max;
|
||||
this.maxDate = maxDate;
|
||||
this.min = min;
|
||||
this.minDate = minDate;
|
||||
this.avg = avg;
|
||||
this.diff = diff;
|
||||
this.q1 = q1;
|
||||
this.median = median;
|
||||
this.q3 = q3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
||||
package com.xzzn.ems.service.impl;
|
||||
|
||||
import com.xzzn.common.utils.DateUtils;
|
||||
import com.xzzn.common.utils.StringUtils;
|
||||
import com.xzzn.ems.domain.SysBizRemark;
|
||||
import com.xzzn.ems.domain.vo.BizRemarkSaveRequest;
|
||||
import com.xzzn.ems.mapper.SysBizRemarkMapper;
|
||||
import com.xzzn.ems.service.ISysBizRemarkService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class SysBizRemarkServiceImpl implements ISysBizRemarkService
|
||||
{
|
||||
@Autowired
|
||||
private SysBizRemarkMapper sysBizRemarkMapper;
|
||||
|
||||
@Override
|
||||
public Map<String, String> getRemarkMap(String bizType, String bizKey1, List<String> bizKey2List)
|
||||
{
|
||||
if (StringUtils.isAnyBlank(bizType, bizKey1) || bizKey2List == null || bizKey2List.isEmpty())
|
||||
{
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<SysBizRemark> remarkList = sysBizRemarkMapper.selectByBizKey2List(bizType, bizKey1, bizKey2List);
|
||||
Map<String, String> result = new LinkedHashMap<>();
|
||||
for (SysBizRemark item : remarkList)
|
||||
{
|
||||
result.put(item.getBizKey2(), StringUtils.nvl(item.getRemark(), ""));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int saveRemark(BizRemarkSaveRequest request, String username)
|
||||
{
|
||||
if (request == null || StringUtils.isAnyBlank(request.getBizType(), request.getBizKey1(), request.getBizKey2()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SysBizRemark existed = sysBizRemarkMapper.selectByBizKeys(request.getBizType(), request.getBizKey1(), request.getBizKey2());
|
||||
if (existed == null)
|
||||
{
|
||||
SysBizRemark bizRemark = new SysBizRemark();
|
||||
bizRemark.setBizType(request.getBizType());
|
||||
bizRemark.setBizKey1(request.getBizKey1());
|
||||
bizRemark.setBizKey2(request.getBizKey2());
|
||||
bizRemark.setRemark(StringUtils.nvl(request.getRemark(), ""));
|
||||
bizRemark.setCreateBy(username);
|
||||
bizRemark.setUpdateBy(username);
|
||||
bizRemark.setCreateTime(DateUtils.getNowDate());
|
||||
bizRemark.setUpdateTime(DateUtils.getNowDate());
|
||||
bizRemark.setDelFlag("0");
|
||||
return sysBizRemarkMapper.insertSysBizRemark(bizRemark);
|
||||
}
|
||||
|
||||
existed.setRemark(StringUtils.nvl(request.getRemark(), ""));
|
||||
existed.setUpdateBy(username);
|
||||
existed.setUpdateTime(DateUtils.getNowDate());
|
||||
existed.setDelFlag("0");
|
||||
return sysBizRemarkMapper.updateSysBizRemark(existed);
|
||||
}
|
||||
}
|
||||
@ -135,6 +135,8 @@ public class DevicePointMatchDataProcessor {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return pointEnumMatchList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(data -> StringUtils.isNotEmpty(data.getMatchField()))
|
||||
.collect(Collectors.groupingBy(data -> StringUtils.toCamelCase(data.getMatchField())));
|
||||
}
|
||||
|
||||
@ -237,8 +239,14 @@ public class DevicePointMatchDataProcessor {
|
||||
* 转换字段值为配置枚举值
|
||||
*/
|
||||
public void convertFieldValueToEnumMatch(String siteId, String deviceCategory, Object entity) {
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, List<EmsPointEnumMatch>> pointEnumMatchMap = this.getPointEnumMatchMap(siteId, deviceCategory);
|
||||
if (pointEnumMatchMap == null || pointEnumMatchMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Field[] fields = entity.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
String fieldName = field.getName();
|
||||
@ -252,7 +260,9 @@ public class DevicePointMatchDataProcessor {
|
||||
if (CollectionUtils.isNotEmpty(pointEnumMatchList) && matchValue != null) {
|
||||
String finalMatchValue = String.valueOf(matchValue).replace(".0", "");
|
||||
Optional<EmsPointEnumMatch> enumMatch = pointEnumMatchList.stream()
|
||||
.filter(data -> data.getDataEnumCode().equals(finalMatchValue)).findFirst();
|
||||
.filter(Objects::nonNull)
|
||||
.filter(data -> Objects.equals(data.getDataEnumCode(), finalMatchValue))
|
||||
.findFirst();
|
||||
if (enumMatch.isPresent()) {
|
||||
matchValue = enumMatch.get().getEnumCode();
|
||||
}
|
||||
|
||||
@ -512,10 +512,16 @@
|
||||
<select id="getStackPointByMinute" parameterType="com.xzzn.ems.domain.vo.DateSearchRequest" resultType="com.xzzn.ems.domain.vo.StackPointVo">
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
*,
|
||||
DATE_FORMAT(DATE_ADD(DATE_FORMAT(p.update_time, '%Y-%m-%d %H:00:00'), INTERVAL CEIL(MINUTE(p.update_time) / 5) * 5 MINUTE)
|
||||
, '%Y-%m-%d %H:%i:%s') AS group_time,
|
||||
ROW_NUMBER() OVER (PARTITION BY p.device_id, date_format(p.update_time, '%Y-%m-%d %H:00:00'), CEIL(MINUTE(p.update_time) / 5) ORDER BY p.data_update_time DESC) as rn
|
||||
p.site_id,
|
||||
p.device_id,
|
||||
p.stack_soc,
|
||||
p.stack_soh,
|
||||
p.avg_temperature,
|
||||
FROM_UNIXTIME(((UNIX_TIMESTAMP(p.update_time) + 299) DIV 300) * 300) AS group_time,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY p.device_id, ((UNIX_TIMESTAMP(p.update_time) + 299) DIV 300)
|
||||
ORDER BY p.data_update_time DESC
|
||||
) as rn
|
||||
FROM
|
||||
ems_battery_stack p
|
||||
<include refid="statisCommonFilter"/>
|
||||
@ -528,16 +534,27 @@
|
||||
avg(t.avg_temperature) as avgTemp
|
||||
FROM
|
||||
ranked as t
|
||||
where t.rn = 1
|
||||
GROUP BY t.site_id, t.group_time
|
||||
</select>
|
||||
|
||||
<select id="getStackDataByMinute" parameterType="com.xzzn.ems.domain.vo.DateSearchRequest" resultType="com.xzzn.ems.domain.vo.StackStatisListVo">
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
*,
|
||||
DATE_FORMAT(DATE_ADD(DATE_FORMAT(p.update_time, '%Y-%m-%d %H:00:00'), INTERVAL CEIL(MINUTE(p.update_time) / 5) * 5 MINUTE)
|
||||
, '%Y-%m-%d %H:%i:%s') AS group_time,
|
||||
ROW_NUMBER() OVER (PARTITION BY p.device_id, date_format(p.update_time, '%Y-%m-%d %H:00:00'), CEIL(MINUTE(p.update_time) / 5) ORDER BY p.data_update_time DESC) as rn
|
||||
p.site_id,
|
||||
p.device_id,
|
||||
p.stack_soc,
|
||||
p.stack_soh,
|
||||
p.avg_temperature,
|
||||
p.operating_temp,
|
||||
p.stack_current,
|
||||
p.stack_voltage,
|
||||
p.data_update_time,
|
||||
FROM_UNIXTIME(((UNIX_TIMESTAMP(p.update_time) + 299) DIV 300) * 300) AS group_time,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY p.device_id, ((UNIX_TIMESTAMP(p.update_time) + 299) DIV 300)
|
||||
ORDER BY p.data_update_time DESC
|
||||
) as rn
|
||||
FROM
|
||||
ems_battery_stack p
|
||||
<include refid="statisCommonFilter"/>
|
||||
@ -574,4 +591,4 @@
|
||||
ranked
|
||||
GROUP BY site_id,groupTime
|
||||
</select>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@ -7,12 +7,13 @@
|
||||
<resultMap type="EmsDailyChargeData" id="EmsDailyChargeDataResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="siteId" column="site_id" />
|
||||
<result property="deviceId" column="device_id" />
|
||||
<result property="dateTime" column="date_time" />
|
||||
<result property="totalChargeData" column="total_charge_Data" />
|
||||
<result property="totalDischargeData" column="total_discharge_Data" />
|
||||
<result property="chargeData" column="charge_data" />
|
||||
<result property="dischargeData" column="discharge_data" />
|
||||
<result property="totalRevenue" column="total_revenue" />
|
||||
<result property="dayRevenue" column="day_revenue" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
@ -21,20 +22,22 @@
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectEmsDailyChargeDataVo">
|
||||
select id, site_id, device_id, date_time, total_charge_Data, total_discharge_Data, charge_data, discharge_data, create_by, create_time, update_by, update_time, remark from ems_daily_charge_data
|
||||
select id, site_id, date_time, total_charge_Data, total_discharge_Data, charge_data, discharge_data, total_revenue, day_revenue, create_by, create_time, update_by, update_time, remark from ems_daily_charge_data
|
||||
</sql>
|
||||
|
||||
<select id="selectEmsDailyChargeDataList" parameterType="EmsDailyChargeData" resultMap="EmsDailyChargeDataResult">
|
||||
<include refid="selectEmsDailyChargeDataVo"/>
|
||||
<where>
|
||||
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
||||
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
||||
<if test="dateTime != null "> and date_time = #{dateTime}</if>
|
||||
<if test="totalChargeData != null "> and total_charge_Data = #{totalChargeData}</if>
|
||||
<if test="totalDischargeData != null "> and total_discharge_Data = #{totalDischargeData}</if>
|
||||
<if test="chargeData != null "> and charge_data = #{chargeData}</if>
|
||||
<if test="dischargeData != null "> and discharge_data = #{dischargeData}</if>
|
||||
<if test="totalRevenue != null "> and total_revenue = #{totalRevenue}</if>
|
||||
<if test="dayRevenue != null "> and day_revenue = #{dayRevenue}</if>
|
||||
</where>
|
||||
order by date_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectEmsDailyChargeDataById" parameterType="Long" resultMap="EmsDailyChargeDataResult">
|
||||
@ -42,16 +45,25 @@
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectBySiteIdAndDateTime" resultMap="EmsDailyChargeDataResult">
|
||||
<include refid="selectEmsDailyChargeDataVo"/>
|
||||
where site_id = #{siteId}
|
||||
and date(date_time) = date(#{dateTime})
|
||||
order by date_time desc
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<insert id="insertEmsDailyChargeData" parameterType="EmsDailyChargeData" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into ems_daily_charge_data
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="siteId != null">site_id,</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id,</if>
|
||||
<if test="dateTime != null">date_time,</if>
|
||||
<if test="totalChargeData != null">total_charge_Data,</if>
|
||||
<if test="totalDischargeData != null">total_discharge_Data,</if>
|
||||
<if test="chargeData != null">charge_data,</if>
|
||||
<if test="dischargeData != null">discharge_data,</if>
|
||||
<if test="totalRevenue != null">total_revenue,</if>
|
||||
<if test="dayRevenue != null">day_revenue,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
@ -60,12 +72,13 @@
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="siteId != null">#{siteId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
|
||||
<if test="dateTime != null">#{dateTime},</if>
|
||||
<if test="totalChargeData != null">#{totalChargeData},</if>
|
||||
<if test="totalDischargeData != null">#{totalDischargeData},</if>
|
||||
<if test="chargeData != null">#{chargeData},</if>
|
||||
<if test="dischargeData != null">#{dischargeData},</if>
|
||||
<if test="totalRevenue != null">#{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">#{dayRevenue},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
@ -78,12 +91,13 @@
|
||||
update ems_daily_charge_data
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="siteId != null">site_id = #{siteId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id = #{deviceId},</if>
|
||||
<if test="dateTime != null">date_time = #{dateTime},</if>
|
||||
<if test="totalChargeData != null">total_charge_Data = #{totalChargeData},</if>
|
||||
<if test="totalDischargeData != null">total_discharge_Data = #{totalDischargeData},</if>
|
||||
<if test="chargeData != null">charge_data = #{chargeData},</if>
|
||||
<if test="dischargeData != null">discharge_data = #{dischargeData},</if>
|
||||
<if test="totalRevenue != null">total_revenue = #{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">day_revenue = #{dayRevenue},</if>
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
@ -108,26 +122,28 @@
|
||||
INSERT into ems_daily_charge_data (
|
||||
id,
|
||||
site_id,
|
||||
device_id,
|
||||
date_time,
|
||||
total_charge_Data,
|
||||
total_discharge_Data,
|
||||
charge_data,
|
||||
discharge_data,
|
||||
total_revenue,
|
||||
day_revenue,
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time,
|
||||
remark
|
||||
) values (
|
||||
) values (
|
||||
#{id},
|
||||
#{siteId},
|
||||
#{deviceId},
|
||||
#{dateTime},
|
||||
#{totalChargeData},
|
||||
#{totalDischargeData},
|
||||
#{chargeData},
|
||||
#{dischargeData},
|
||||
#{totalRevenue},
|
||||
#{dayRevenue},
|
||||
#{createBy},
|
||||
#{createTime},
|
||||
#{updateBy},
|
||||
@ -139,9 +155,21 @@
|
||||
total_discharge_Data = #{totalDischargeData},
|
||||
charge_data = #{chargeData},
|
||||
discharge_data = #{dischargeData},
|
||||
total_revenue = IFNULL(#{totalRevenue}, total_revenue),
|
||||
day_revenue = IFNULL(#{dayRevenue}, day_revenue),
|
||||
update_time = NOW()
|
||||
</insert>
|
||||
|
||||
<update id="updateRevenueBySiteAndDate">
|
||||
update ems_daily_charge_data
|
||||
set total_revenue = #{totalRevenue},
|
||||
day_revenue = #{dayRevenue},
|
||||
update_by = #{updateBy},
|
||||
update_time = NOW()
|
||||
where site_id = #{siteId}
|
||||
and date(date_time) = date(#{dateTime})
|
||||
</update>
|
||||
|
||||
<select id="getAllSiteChargeData" resultType="map">
|
||||
SELECT
|
||||
SUM(t.total_charge_data) AS totalChargedCap,
|
||||
@ -207,4 +235,4 @@
|
||||
GROUP BY dateMonth
|
||||
ORDER BY dateMonth
|
||||
</select>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@ -8,8 +8,7 @@
|
||||
<result property="id" column="id" />
|
||||
<result property="siteId" column="site_id" />
|
||||
<result property="dataDate" column="data_date" />
|
||||
<result property="totalRevenue" column="total_revenue" />
|
||||
<result property="dayRevenue" column="day_revenue" />
|
||||
<result property="dataHour" column="data_hour" />
|
||||
<result property="peakChargeDiff" column="peak_charge_diff" />
|
||||
<result property="peakDischargeDiff" column="peak_discharge_diff" />
|
||||
<result property="highChargeDiff" column="high_charge_diff" />
|
||||
@ -27,7 +26,11 @@
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectEmsDailyEnergyDataVo">
|
||||
select id, site_id, data_date, total_revenue, day_revenue, peak_charge_diff, peak_discharge_diff, high_charge_diff, high_discharge_diff, flat_charge_diff, flat_discharge_diff, valley_charge_diff, valley_discharge_diff, calc_time, create_by, create_time, update_by, update_time, remark from ems_daily_energy_data
|
||||
select id, site_id, data_date, data_hour,
|
||||
peak_charge_diff, peak_discharge_diff, high_charge_diff, high_discharge_diff,
|
||||
flat_charge_diff, flat_discharge_diff, valley_charge_diff, valley_discharge_diff,
|
||||
calc_time, create_by, create_time, update_by, update_time, remark
|
||||
from ems_daily_energy_data
|
||||
</sql>
|
||||
|
||||
<select id="selectEmsDailyEnergyDataList" parameterType="EmsDailyEnergyData" resultMap="EmsDailyEnergyDataResult">
|
||||
@ -35,8 +38,7 @@
|
||||
<where>
|
||||
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
||||
<if test="dataDate != null "> and data_date = #{dataDate}</if>
|
||||
<if test="totalRevenue != null "> and total_revenue = #{totalRevenue}</if>
|
||||
<if test="dayRevenue != null "> and day_revenue = #{dayRevenue}</if>
|
||||
<if test="dataHour != null "> and data_hour = #{dataHour}</if>
|
||||
<if test="peakChargeDiff != null "> and peak_charge_diff = #{peakChargeDiff}</if>
|
||||
<if test="peakDischargeDiff != null "> and peak_discharge_diff = #{peakDischargeDiff}</if>
|
||||
<if test="highChargeDiff != null "> and high_charge_diff = #{highChargeDiff}</if>
|
||||
@ -47,6 +49,7 @@
|
||||
<if test="valleyDischargeDiff != null "> and valley_discharge_diff = #{valleyDischargeDiff}</if>
|
||||
<if test="calcTime != null "> and calc_time = #{calcTime}</if>
|
||||
</where>
|
||||
order by data_date desc, calc_time desc, id desc
|
||||
</select>
|
||||
|
||||
<select id="selectEmsDailyEnergyDataById" parameterType="Long" resultMap="EmsDailyEnergyDataResult">
|
||||
@ -59,8 +62,7 @@
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="siteId != null">site_id,</if>
|
||||
<if test="dataDate != null">data_date,</if>
|
||||
<if test="totalRevenue != null">total_revenue,</if>
|
||||
<if test="dayRevenue != null">day_revenue,</if>
|
||||
<if test="dataHour != null">data_hour,</if>
|
||||
<if test="peakChargeDiff != null">peak_charge_diff,</if>
|
||||
<if test="peakDischargeDiff != null">peak_discharge_diff,</if>
|
||||
<if test="highChargeDiff != null">high_charge_diff,</if>
|
||||
@ -79,8 +81,7 @@
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="siteId != null">#{siteId},</if>
|
||||
<if test="dataDate != null">#{dataDate},</if>
|
||||
<if test="totalRevenue != null">#{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">#{dayRevenue},</if>
|
||||
<if test="dataHour != null">#{dataHour},</if>
|
||||
<if test="peakChargeDiff != null">#{peakChargeDiff},</if>
|
||||
<if test="peakDischargeDiff != null">#{peakDischargeDiff},</if>
|
||||
<if test="highChargeDiff != null">#{highChargeDiff},</if>
|
||||
@ -103,8 +104,7 @@
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="siteId != null">site_id = #{siteId},</if>
|
||||
<if test="dataDate != null">data_date = #{dataDate},</if>
|
||||
<if test="totalRevenue != null">total_revenue = #{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">day_revenue = #{dayRevenue},</if>
|
||||
<if test="dataHour != null">data_hour = #{dataHour},</if>
|
||||
<if test="peakChargeDiff != null">peak_charge_diff = #{peakChargeDiff},</if>
|
||||
<if test="peakDischargeDiff != null">peak_discharge_diff = #{peakDischargeDiff},</if>
|
||||
<if test="highChargeDiff != null">high_charge_diff = #{highChargeDiff},</if>
|
||||
@ -138,14 +138,22 @@
|
||||
<include refid="selectEmsDailyEnergyDataVo"/>
|
||||
where data_date = #{today}
|
||||
AND site_id = #{siteId}
|
||||
AND data_hour IS NULL
|
||||
</select>
|
||||
|
||||
<select id="selectBySiteIdAndDateHour" resultMap="EmsDailyEnergyDataResult">
|
||||
<include refid="selectEmsDailyEnergyDataVo"/>
|
||||
where site_id = #{siteId}
|
||||
and data_date = DATE(#{dataDate})
|
||||
and data_hour = #{dataHour}
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<insert id="insertOrUpdateData" parameterType="com.xzzn.ems.domain.EmsDailyEnergyData"
|
||||
useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO ems_daily_energy_data (
|
||||
id, site_id, data_date,
|
||||
<if test="totalRevenue != null">total_revenue,</if>
|
||||
<if test="dayRevenue != null">day_revenue,</if>
|
||||
<if test="dataHour != null">data_hour,</if>
|
||||
<if test="peakChargeDiff != null">peak_charge_diff,</if>
|
||||
<if test="peakDischargeDiff != null">peak_discharge_diff,</if>
|
||||
<if test="highChargeDiff != null">high_charge_diff,</if>
|
||||
@ -164,8 +172,7 @@
|
||||
#{id},
|
||||
#{siteId},
|
||||
#{dataDate},
|
||||
<if test="totalRevenue != null">#{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">#{dayRevenue},</if>
|
||||
<if test="dataHour != null">#{dataHour},</if>
|
||||
<if test="peakChargeDiff != null">#{peakChargeDiff},</if>
|
||||
<if test="peakDischargeDiff != null">#{peakDischargeDiff},</if>
|
||||
<if test="highChargeDiff != null">#{highChargeDiff},</if>
|
||||
@ -181,8 +188,7 @@
|
||||
NOW(),
|
||||
#{remark}
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
<if test="totalRevenue != null">total_revenue = #{totalRevenue},</if>
|
||||
<if test="dayRevenue != null">day_revenue = #{dayRevenue},</if>
|
||||
<if test="dataHour != null">data_hour = #{dataHour},</if>
|
||||
<if test="peakChargeDiff != null">peak_charge_diff = #{peakChargeDiff},</if>
|
||||
<if test="peakDischargeDiff != null">peak_discharge_diff = #{peakDischargeDiff},</if>
|
||||
<if test="highChargeDiff != null">high_charge_diff = #{highChargeDiff},</if>
|
||||
@ -196,67 +202,138 @@
|
||||
</insert>
|
||||
|
||||
<select id="getDataBySiteId" resultType="com.xzzn.ems.domain.vo.AmmeterStatisListVo">
|
||||
select t.data_date as dataTime,
|
||||
t.peak_charge_diff as activePeakKwh,
|
||||
t.peak_discharge_diff as reActivePeakKwh,
|
||||
t.high_charge_diff as activeHighKwh,
|
||||
t.high_discharge_diff as reActiveHighKwh,
|
||||
t.flat_charge_diff as activeFlatKwh,
|
||||
t.flat_discharge_diff as reActiveFlatKwh,
|
||||
t.valley_charge_diff as activeValleyKwh,
|
||||
t.valley_discharge_diff as reActiveValleyKwh
|
||||
from ems_daily_energy_data t
|
||||
where 1=1
|
||||
<if test="siteId != null">
|
||||
and t.site_id = #{siteId}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
and t.data_date >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
and t.data_date <= #{endTime}
|
||||
</if>
|
||||
select DATE_FORMAT(r.dataDate, '%Y-%m-%d') as dataTime,
|
||||
r.activePeakKwh,
|
||||
r.reActivePeakKwh,
|
||||
r.activeHighKwh,
|
||||
r.reActiveHighKwh,
|
||||
r.activeFlatKwh,
|
||||
r.reActiveFlatKwh,
|
||||
r.activeValleyKwh,
|
||||
r.reActiveValleyKwh
|
||||
from (
|
||||
-- 优先使用按天汇总记录(data_hour is null)
|
||||
select DATE(t.data_date) as dataDate,
|
||||
t.peak_charge_diff as activePeakKwh,
|
||||
t.peak_discharge_diff as reActivePeakKwh,
|
||||
t.high_charge_diff as activeHighKwh,
|
||||
t.high_discharge_diff as reActiveHighKwh,
|
||||
t.flat_charge_diff as activeFlatKwh,
|
||||
t.flat_discharge_diff as reActiveFlatKwh,
|
||||
t.valley_charge_diff as activeValleyKwh,
|
||||
t.valley_discharge_diff as reActiveValleyKwh
|
||||
from ems_daily_energy_data t
|
||||
where t.data_hour is null
|
||||
<if test="siteId != null and siteId != ''">
|
||||
and t.site_id = #{siteId}
|
||||
</if>
|
||||
<if test="startTime != null and startTime != ''">
|
||||
and t.data_date >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
and t.data_date < DATE_ADD(#{endTime}, INTERVAL 1 DAY)
|
||||
</if>
|
||||
|
||||
union all
|
||||
|
||||
-- 若某天没有日汇总记录,则按小时数据汇总兜底
|
||||
select DATE(h.data_date) as dataDate,
|
||||
SUM(IFNULL(h.peak_charge_diff, 0)) as activePeakKwh,
|
||||
SUM(IFNULL(h.peak_discharge_diff, 0)) as reActivePeakKwh,
|
||||
SUM(IFNULL(h.high_charge_diff, 0)) as activeHighKwh,
|
||||
SUM(IFNULL(h.high_discharge_diff, 0)) as reActiveHighKwh,
|
||||
SUM(IFNULL(h.flat_charge_diff, 0)) as activeFlatKwh,
|
||||
SUM(IFNULL(h.flat_discharge_diff, 0)) as reActiveFlatKwh,
|
||||
SUM(IFNULL(h.valley_charge_diff, 0)) as activeValleyKwh,
|
||||
SUM(IFNULL(h.valley_discharge_diff, 0)) as reActiveValleyKwh
|
||||
from ems_daily_energy_data h
|
||||
where h.data_hour is not null
|
||||
<if test="siteId != null and siteId != ''">
|
||||
and h.site_id = #{siteId}
|
||||
</if>
|
||||
<if test="startTime != null and startTime != ''">
|
||||
and h.data_date >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
and h.data_date < DATE_ADD(#{endTime}, INTERVAL 1 DAY)
|
||||
</if>
|
||||
and not exists (
|
||||
select 1
|
||||
from ems_daily_energy_data d
|
||||
where d.site_id = h.site_id
|
||||
and DATE(d.data_date) = DATE(h.data_date)
|
||||
and d.data_hour is null
|
||||
)
|
||||
group by h.site_id, DATE(h.data_date)
|
||||
) r
|
||||
order by r.dataDate desc
|
||||
</select>
|
||||
|
||||
<select id="getLastTotalRevenue" resultType="java.math.BigDecimal">
|
||||
select t.total_revenue
|
||||
from ems_daily_energy_data t
|
||||
where t.site_id = #{siteId}
|
||||
and t.data_date < CURDATE()
|
||||
order by t.data_date desc limit 1
|
||||
from ems_daily_charge_data t
|
||||
where t.site_id = #{siteId}
|
||||
and date(t.date_time) < CURDATE()
|
||||
order by t.date_time desc
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="getRealTimeRevenue" resultType="java.util.Map">
|
||||
select t.total_revenue as totalRevenue, t.day_revenue as dayRevenue
|
||||
from ems_daily_energy_data t
|
||||
where t.site_id = #{siteId}
|
||||
order by t.data_date desc limit 1
|
||||
from ems_daily_charge_data t
|
||||
where t.site_id = #{siteId}
|
||||
order by t.date_time desc
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="getRevenueDataBySiteId" resultType="com.xzzn.ems.domain.vo.AmmeterRevenueStatisListVo">
|
||||
select
|
||||
t.data_date as dataTime,
|
||||
ROUND(t.peak_charge_diff * pc.peak, 3) as activePeakPrice,
|
||||
ROUND(t.peak_discharge_diff * pc.peak, 3) as reActivePeakPrice,
|
||||
ROUND(t.high_charge_diff * pc.high, 3) as activeHighPrice,
|
||||
ROUND(t.high_discharge_diff * pc.high, 3) as reActiveHighPrice,
|
||||
ROUND(t.flat_charge_diff * pc.flat, 3) as activeFlatPrice,
|
||||
ROUND(t.flat_discharge_diff * pc.flat, 3) as reActiveFlatPrice,
|
||||
ROUND(t.valley_charge_diff * pc.valley, 3) as activeValleyPrice,
|
||||
ROUND(t.valley_discharge_diff * pc.valley, 3) as reActiveValleyPrice
|
||||
DATE_FORMAT(t.data_date, '%Y-%m-%d') as dataTime,
|
||||
COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) < 5 THEN 1 ELSE 0 END) as isWorkday,
|
||||
CASE
|
||||
WHEN COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) < 5 THEN 1 ELSE 0 END) = 1 THEN '工作日'
|
||||
ELSE '节假日'
|
||||
END as dayType,
|
||||
COALESCE(NULLIF(TRIM(w.weather_desc), ''), '--') as weatherDesc,
|
||||
ROUND(SUM(IFNULL(t.peak_charge_diff, 0) * IFNULL(pc.peak, 0)), 3) as activePeakPrice,
|
||||
ROUND(SUM(IFNULL(t.peak_discharge_diff, 0) * IFNULL(pc.peak, 0)), 3) as reActivePeakPrice,
|
||||
ROUND(SUM(IFNULL(t.high_charge_diff, 0) * IFNULL(pc.high, 0)), 3) as activeHighPrice,
|
||||
ROUND(SUM(IFNULL(t.high_discharge_diff, 0) * IFNULL(pc.high, 0)), 3) as reActiveHighPrice,
|
||||
ROUND(SUM(IFNULL(t.flat_charge_diff, 0) * IFNULL(pc.flat, 0)), 3) as activeFlatPrice,
|
||||
ROUND(SUM(IFNULL(t.flat_discharge_diff, 0) * IFNULL(pc.flat, 0)), 3) as reActiveFlatPrice,
|
||||
ROUND(SUM(IFNULL(t.valley_charge_diff, 0) * IFNULL(pc.valley, 0)), 3) as activeValleyPrice,
|
||||
ROUND(SUM(IFNULL(t.valley_discharge_diff, 0) * IFNULL(pc.valley, 0)), 3) as reActiveValleyPrice,
|
||||
ROUND(
|
||||
SUM(
|
||||
(IFNULL(t.peak_discharge_diff, 0) - IFNULL(t.peak_charge_diff, 0)) * IFNULL(pc.peak, 0)
|
||||
+ (IFNULL(t.high_discharge_diff, 0) - IFNULL(t.high_charge_diff, 0)) * IFNULL(pc.high, 0)
|
||||
+ (IFNULL(t.flat_discharge_diff, 0) - IFNULL(t.flat_charge_diff, 0)) * IFNULL(pc.flat, 0)
|
||||
+ (IFNULL(t.valley_discharge_diff, 0) - IFNULL(t.valley_charge_diff, 0)) * IFNULL(pc.valley, 0)
|
||||
),
|
||||
3
|
||||
) as actualRevenue
|
||||
from ems_daily_energy_data t
|
||||
left join (
|
||||
select
|
||||
id, site_id, peak, high, flat, valley,
|
||||
CONCAT(year, '-', LPAD(month, 2, '0')) as yearMonth
|
||||
from ems_energy_price_config
|
||||
where 1=1
|
||||
<if test="siteId != null">
|
||||
and site_id = #{siteId}
|
||||
</if>
|
||||
order by year, month
|
||||
) pc on pc.yearMonth = DATE_FORMAT(t.data_date, '%Y-%m')
|
||||
left join ems_calendar_day c on c.calendar_date = t.data_date
|
||||
left join ems_site_weather_day w on w.site_id = t.site_id and w.calendar_date = t.data_date
|
||||
left join ems_energy_price_config pc on pc.id = COALESCE(
|
||||
(
|
||||
select p.id
|
||||
from ems_energy_price_config p
|
||||
where p.site_id = t.site_id
|
||||
and STR_TO_DATE(CONCAT(p.year, '-', LPAD(p.month, 2, '0'), '-01'), '%Y-%m-%d') <= DATE_FORMAT(t.data_date, '%Y-%m-01')
|
||||
order by STR_TO_DATE(CONCAT(p.year, '-', LPAD(p.month, 2, '0'), '-01'), '%Y-%m-%d') desc
|
||||
limit 1
|
||||
),
|
||||
(
|
||||
select p2.id
|
||||
from ems_energy_price_config p2
|
||||
where p2.site_id = t.site_id
|
||||
order by STR_TO_DATE(CONCAT(p2.year, '-', LPAD(p2.month, 2, '0'), '-01'), '%Y-%m-%d') asc
|
||||
limit 1
|
||||
)
|
||||
)
|
||||
where 1=1
|
||||
and t.data_hour is not null
|
||||
<if test="siteId != null">
|
||||
and t.site_id = #{siteId}
|
||||
</if>
|
||||
@ -266,6 +343,10 @@
|
||||
<if test="endTime != null">
|
||||
and t.data_date <= #{endTime}
|
||||
</if>
|
||||
group by t.data_date,
|
||||
COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) < 5 THEN 1 ELSE 0 END),
|
||||
COALESCE(NULLIF(TRIM(w.weather_desc), ''), '--')
|
||||
order by t.data_date asc
|
||||
|
||||
</select>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user