|
@@ -13,6 +13,7 @@ package com.ruoyi.ems.handle;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.huashe.common.exception.Assert;
|
|
|
import com.huashe.common.utils.DateUtils;
|
|
|
+import com.ruoyi.common.redis.service.RedisService;
|
|
|
import com.ruoyi.ems.config.InDoorEnergyConfig;
|
|
|
import com.ruoyi.ems.core.InDoorEnergyTemplate;
|
|
|
import com.ruoyi.ems.domain.ElecMeterH;
|
|
@@ -35,6 +36,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
@@ -70,6 +72,9 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
@Resource
|
|
|
private InDoorEnergyConfig config;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
+
|
|
|
@Override
|
|
|
public List<MeterDevice> getMeterDeviceList() {
|
|
|
return meterDeviceService.selectByModel(MODE_CODE);
|
|
@@ -130,16 +135,16 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 能耗数据抄报
|
|
|
+ * 采集室内能耗计量数据
|
|
|
+ *
|
|
|
+ * @return 采集条数
|
|
|
*/
|
|
|
- @Override
|
|
|
- public int meterHourProd() {
|
|
|
+ public int meterCollect() {
|
|
|
int cnt = 0;
|
|
|
|
|
|
try {
|
|
|
// 获取所有能源设备列表
|
|
|
List<EmsDevice> deviceList = getDeviceList();
|
|
|
- List<MeterDevice> meterDeviceList = getMeterDeviceList();
|
|
|
|
|
|
// 遍历每个能源设备
|
|
|
if (CollectionUtils.isNotEmpty(deviceList)) {
|
|
@@ -147,7 +152,7 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
InDoorEnergyTemplate template = new InDoorEnergyTemplate(config.getUrl());
|
|
|
|
|
|
for (EmsDevice emsDevice : deviceList) {
|
|
|
- cnt += meterDevHourProd(template, emsDevice, meterDeviceList);
|
|
|
+ cnt += meterDevCollect(template, emsDevice);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -158,8 +163,7 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
return cnt;
|
|
|
}
|
|
|
|
|
|
- private int meterDevHourProd(InDoorEnergyTemplate template, EmsDevice emsDevice,
|
|
|
- List<MeterDevice> meterDeviceList) {
|
|
|
+ private int meterDevCollect(InDoorEnergyTemplate template, EmsDevice emsDevice) {
|
|
|
int cnt = 0;
|
|
|
|
|
|
try {
|
|
@@ -189,6 +193,108 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
String dataStr = resJson.getString("ResultPointObjArr");
|
|
|
List<CodesVal> retList = JSONObject.parseArray(dataStr, CodesVal.class);
|
|
|
|
|
|
+ // 更新设备属性
|
|
|
+ updateDeviceAttrList(attrValues, retList);
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("meterDevHourProd error! deviceCode:{}", emsDevice.getDeviceCode(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return cnt;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateDeviceAttrList(List<EmsObjAttrValue> attrValues, List<CodesVal> retList) {
|
|
|
+ try {
|
|
|
+ // 将新采集数据转换为Map
|
|
|
+ Map<String, CodesVal> codesValMap = retList.stream()
|
|
|
+ .collect(Collectors.toMap(CodesVal::getPointId, Function.identity()));
|
|
|
+
|
|
|
+ for (EmsObjAttrValue dbAttr : attrValues) {
|
|
|
+ // 更新列表中的值
|
|
|
+ boolean dbNeedUpdate = false;
|
|
|
+ String dbAttrValue = dbAttr.getAttrValue();
|
|
|
+ List<ObjAttrTableItem> dbItems = JSON.parseArray(dbAttrValue, ObjAttrTableItem.class);
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(dbItems)) {
|
|
|
+ Map<String, ObjAttrTableItem> itemMap = dbItems.stream()
|
|
|
+ .collect(Collectors.toMap(ObjAttrTableItem::getKey, Function.identity()));
|
|
|
+
|
|
|
+ for (Map.Entry<String, ObjAttrTableItem> dbItemEntry : itemMap.entrySet()) {
|
|
|
+ String pointId = dbItemEntry.getKey();
|
|
|
+ ObjAttrTableItem dbItem = dbItemEntry.getValue();
|
|
|
+
|
|
|
+ CodesVal syncCodesVal = codesValMap.get(pointId);
|
|
|
+
|
|
|
+ if (null != syncCodesVal) {
|
|
|
+ // 更新缓存中的数据
|
|
|
+ String hKey = NEW_HOUR_READING + "-" + pointId;
|
|
|
+ redisService.setCacheMapValue(dbAttr.getObjCode(), hKey, syncCodesVal.getValue());
|
|
|
+
|
|
|
+ if (!StringUtils.equals(syncCodesVal.getValue(), dbItem.getValue()) || !StringUtils.equals(
|
|
|
+ syncCodesVal.getTime(), dbItem.getUpdateTime())) {
|
|
|
+ dbNeedUpdate = true;
|
|
|
+
|
|
|
+ dbItem.setValue(syncCodesVal.getValue());
|
|
|
+ dbItem.setUpdateTime(syncCodesVal.getTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果有更新,则保存回数据库
|
|
|
+ if (dbNeedUpdate) {
|
|
|
+ dbAttrValue = JSON.toJSONString(dbItems);
|
|
|
+ dbAttr.setAttrValue(dbAttrValue);
|
|
|
+ objAttrValueService.updateObjAttrValue(dbAttr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("更新设备属性异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 能耗数据抄报
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int meterHourProd() {
|
|
|
+ int cnt = 0;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取所有能源设备列表
|
|
|
+ List<EmsDevice> deviceList = getDeviceList();
|
|
|
+ List<MeterDevice> meterDeviceList = getMeterDeviceList();
|
|
|
+
|
|
|
+ // 遍历每个能源设备
|
|
|
+ if (CollectionUtils.isNotEmpty(deviceList)) {
|
|
|
+ for (EmsDevice emsDevice : deviceList) {
|
|
|
+ cnt += meterDevHourProd(emsDevice, meterDeviceList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("能耗数据抄报异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return cnt;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int meterDevHourProd(EmsDevice emsDevice, List<MeterDevice> meterDeviceList) {
|
|
|
+ int cnt = 0;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询当前设备的接口属性值
|
|
|
+ List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(MODE_CODE,
|
|
|
+ emsDevice.getDeviceCode());
|
|
|
+ attrValues = attrValues.stream()
|
|
|
+ // 过滤条件:attrKey以"interface"开头
|
|
|
+ .filter(attr -> StringUtils.startsWith(attr.getAttrKey(), "interface"))
|
|
|
+ // 收集为新的List
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ Set<String> pointIdSet = getPointIds(attrValues);
|
|
|
+
|
|
|
// 电表过滤
|
|
|
List<MeterDevice> elecDevs = meterDeviceList.stream()
|
|
|
.filter(device -> pointIdSet.contains(device.getDeviceCode()) && 45 == device.getMeterCls())
|
|
@@ -196,7 +302,7 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
|
|
|
// 电表抄表数据保存
|
|
|
if (CollectionUtils.isNotEmpty(elecDevs)) {
|
|
|
- cnt += saveElecMeterReading(elecDevs, retList);
|
|
|
+ cnt += saveElecMeterReading(emsDevice, elecDevs);
|
|
|
}
|
|
|
|
|
|
// 水表过滤
|
|
@@ -206,11 +312,8 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
|
|
|
// 水表抄表数据保存
|
|
|
if (CollectionUtils.isNotEmpty(waterDevs)) {
|
|
|
- cnt += saveWaterMeterReading(waterDevs, retList);
|
|
|
+ cnt += saveWaterMeterReading(emsDevice, waterDevs);
|
|
|
}
|
|
|
-
|
|
|
- // 更新设备属性
|
|
|
- updateDeviceAttrList(attrValues, retList);
|
|
|
}
|
|
|
catch (Exception e) {
|
|
|
log.error("meterDevHourProd error! deviceCode:{}", emsDevice.getDeviceCode(), e);
|
|
@@ -219,33 +322,28 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
return cnt;
|
|
|
}
|
|
|
|
|
|
- private int saveElecMeterReading(List<MeterDevice> deviceList, List<CodesVal> retList) {
|
|
|
- Map<String, CodesVal> retMap = retList.stream().collect(Collectors.toMap(CodesVal::getPointId, val -> val));
|
|
|
+ private int saveElecMeterReading(EmsDevice gwDevice, List<MeterDevice> deviceList) {
|
|
|
Map<String, Price> priceMap = new ConcurrentHashMap<>();
|
|
|
List<ElecMeterH> meterHList = new ArrayList<>();
|
|
|
+ Date date = DateUtils.adjustHour(new Date(), -1);
|
|
|
|
|
|
- for (MeterDevice device : deviceList) {
|
|
|
+ for (MeterDevice meterDevice : deviceList) {
|
|
|
// 读取最新抄表值
|
|
|
- CodesVal codesVal = retMap.get(device.getDeviceCode());
|
|
|
+ String newMeterReading = redisService.getCacheMapValue(gwDevice.getDeviceCode(),
|
|
|
+ NEW_HOUR_READING + "-" + meterDevice.getDeviceCode());
|
|
|
|
|
|
- if (null != codesVal) {
|
|
|
- // 读取最新抄表值
|
|
|
- String newMeterReading = codesVal.getValue();
|
|
|
- Date date = DateUtils.stringToDate(codesVal.getTime(), "yyyy-MM-dd HH:mm:ss");
|
|
|
-
|
|
|
- // 获取设备属性缓存
|
|
|
- Map<String, String> attrMap = attrCache.computeIfAbsent(device.getDeviceCode(),
|
|
|
- k -> new ConcurrentHashMap<>());
|
|
|
+ if (null != newMeterReading) {
|
|
|
+ String lastCacheKey = LAST_HOUR_READING + "-" + meterDevice.getDeviceCode();
|
|
|
|
|
|
// 读取历史抄表
|
|
|
- String lastMeterReading = attrMap.get(LAST_HOUR_READING);
|
|
|
+ String lastMeterReading = redisService.getCacheMapValue(gwDevice.getDeviceCode(), lastCacheKey);
|
|
|
|
|
|
- // 组装电表抄报数据
|
|
|
- ElecMeterH elecMeterH = getElecMeterH(device, lastMeterReading, newMeterReading);
|
|
|
+ ElecMeterH elecMeterH = getElecMeterH(gwDevice.getDeviceCode(), meterDevice, lastMeterReading,
|
|
|
+ newMeterReading);
|
|
|
|
|
|
if (null != elecMeterH) {
|
|
|
- Price price = priceMap.computeIfAbsent(device.getAreaCode(),
|
|
|
- k -> priceService.getElecHourPrice(device.getAreaCode(), date));
|
|
|
+ Price price = priceMap.computeIfAbsent(gwDevice.getAreaCode(),
|
|
|
+ k -> priceService.getElecHourPrice(gwDevice.getAreaCode(), date));
|
|
|
completeElecPrice(elecMeterH, price);
|
|
|
meterHList.add(elecMeterH);
|
|
|
}
|
|
@@ -255,32 +353,60 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
return CollectionUtils.isNotEmpty(meterHList) ? elecMeterHService.insertBatch(meterHList) : 0;
|
|
|
}
|
|
|
|
|
|
- private int saveWaterMeterReading(List<MeterDevice> deviceList, List<CodesVal> retList) {
|
|
|
- Map<String, CodesVal> retMap = retList.stream().collect(Collectors.toMap(CodesVal::getPointId, val -> val));
|
|
|
+ @Override
|
|
|
+ public ElecMeterH getElecMeterH(String deviceCode, MeterDevice mDevice, String lastMeterReading,
|
|
|
+ String newMeterReading) {
|
|
|
+ ElecMeterH elecMeterH = null;
|
|
|
+ String cacheKey = LAST_HOUR_READING + "-" + mDevice.getDeviceCode();
|
|
|
+
|
|
|
+ // 缓存不为空,使用缓存抄表计算
|
|
|
+ if (StringUtils.isNotEmpty(lastMeterReading)) {
|
|
|
+ elecMeterH = execElecHourMeter(mDevice, lastMeterReading, newMeterReading);
|
|
|
+ // 本周期抄表完成,将新抄表值覆盖作为下个周期的起始
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
+ }
|
|
|
+ // 缓存为空,使用数据库记录计算
|
|
|
+ else {
|
|
|
+ ElecMeterH dbElecMeterH = elecMeterHService.selectLatelyItem(deviceCode);
|
|
|
+
|
|
|
+ if (null != dbElecMeterH && null != dbElecMeterH.getMeterReading()) {
|
|
|
+ elecMeterH = execElecHourMeter(mDevice, String.valueOf(dbElecMeterH.getMeterReading()),
|
|
|
+ newMeterReading);
|
|
|
+ // 本周期抄表完成,将新抄表值覆盖作为下个周期的起始
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // 无缓存也无数据库记录,则认为是首次上报
|
|
|
+ if (StringUtils.isNotEmpty(newMeterReading)) {
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return elecMeterH;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int saveWaterMeterReading(EmsDevice gwDevice, List<MeterDevice> deviceList) {
|
|
|
Map<String, FdEnergyPriceConfig> priceMap = new ConcurrentHashMap<>();
|
|
|
List<WaterMeterH> meterHList = new ArrayList<>();
|
|
|
|
|
|
- for (MeterDevice device : deviceList) {
|
|
|
+ for (MeterDevice meterDevice : deviceList) {
|
|
|
// 读取最新抄表值
|
|
|
- CodesVal codesVal = retMap.get(device.getDeviceCode());
|
|
|
-
|
|
|
- if (null != codesVal) {
|
|
|
- // 读取最新抄表值
|
|
|
- String newMeterReading = codesVal.getValue();
|
|
|
+ String newMeterReading = redisService.getCacheMapValue(gwDevice.getDeviceCode(),
|
|
|
+ NEW_HOUR_READING + "-" + meterDevice.getDeviceCode());
|
|
|
|
|
|
- // 获取设备属性缓存
|
|
|
- Map<String, String> attrMap = attrCache.computeIfAbsent(device.getDeviceCode(),
|
|
|
- k -> new ConcurrentHashMap<>());
|
|
|
+ if (null != newMeterReading) {
|
|
|
+ String lastCacheKey = LAST_HOUR_READING + "-" + meterDevice.getDeviceCode();
|
|
|
|
|
|
// 读取历史抄表
|
|
|
- String lastMeterReading = attrMap.get(LAST_HOUR_READING);
|
|
|
+ String lastMeterReading = redisService.getCacheMapValue(gwDevice.getDeviceCode(), lastCacheKey);
|
|
|
|
|
|
- // 组装电表抄报数据
|
|
|
- WaterMeterH waterMeterH = getWaterMeterH(device, lastMeterReading, newMeterReading);
|
|
|
+ // 组装水表抄报数据
|
|
|
+ WaterMeterH waterMeterH = getWaterMeterH(gwDevice.getDeviceCode(), meterDevice, lastMeterReading, newMeterReading);
|
|
|
|
|
|
if (null != waterMeterH) {
|
|
|
- FdEnergyPriceConfig price = priceMap.computeIfAbsent(device.getAreaCode(),
|
|
|
- k -> fdEnergyPriceConfigService.selectByAreaCode(device.getAreaCode(), 70));
|
|
|
+ FdEnergyPriceConfig price = priceMap.computeIfAbsent(gwDevice.getAreaCode(),
|
|
|
+ k -> fdEnergyPriceConfigService.selectByAreaCode(gwDevice.getAreaCode(), 70));
|
|
|
completeWaterPrice(waterMeterH, price);
|
|
|
meterHList.add(waterMeterH);
|
|
|
}
|
|
@@ -290,45 +416,39 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
|
|
|
return CollectionUtils.isNotEmpty(meterHList) ? waterMeterHService.insertBatch(meterHList) : 0;
|
|
|
}
|
|
|
|
|
|
- private void updateDeviceAttrList(List<EmsObjAttrValue> attrValues, List<CodesVal> retList) {
|
|
|
- try {
|
|
|
- Map<String, CodesVal> codesValMap = retList.stream()
|
|
|
- .collect(Collectors.toMap(CodesVal::getPointId, Function.identity()));
|
|
|
-
|
|
|
- for (EmsObjAttrValue objAttr : attrValues) {
|
|
|
- // 更新列表中的值
|
|
|
- boolean updated = false;
|
|
|
- String attrValue = objAttr.getAttrValue();
|
|
|
- List<ObjAttrTableItem> tableItems = JSON.parseArray(attrValue, ObjAttrTableItem.class);
|
|
|
+ @Override
|
|
|
+ public WaterMeterH getWaterMeterH(String deviceCode, MeterDevice mDevice, String lastMeterReading,
|
|
|
+ String newMeterReading) {
|
|
|
+ WaterMeterH waterMeterH = null;
|
|
|
+ String cacheKey = LAST_HOUR_READING + "-" + mDevice.getDeviceCode();
|
|
|
|
|
|
- if (CollectionUtils.isNotEmpty(tableItems)) {
|
|
|
- Map<String, ObjAttrTableItem> itemMap = tableItems.stream()
|
|
|
- .collect(Collectors.toMap(ObjAttrTableItem::getKey, Function.identity()));
|
|
|
+ // 缓存不为空,使用缓存抄表计算
|
|
|
+ if (StringUtils.isNotEmpty(lastMeterReading)) {
|
|
|
+ waterMeterH = execWaterHourMeter(mDevice, lastMeterReading, newMeterReading);
|
|
|
|
|
|
- for (Map.Entry<String, ObjAttrTableItem> itemEntry : itemMap.entrySet()) {
|
|
|
- String itemKey = itemEntry.getKey();
|
|
|
- ObjAttrTableItem item = itemEntry.getValue();
|
|
|
+ // 更新缓存
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
+ }
|
|
|
+ // 缓存为空,使用数据库记录计算
|
|
|
+ else {
|
|
|
+ WaterMeterH dbWaterMeterH = waterMeterHService.selectLatelyItem(mDevice.getDeviceCode());
|
|
|
|
|
|
- if (codesValMap.containsKey(itemKey)) {
|
|
|
- updated = true;
|
|
|
- CodesVal codesVal = codesValMap.get(itemKey);
|
|
|
- item.setValue(codesVal.getValue());
|
|
|
- item.setUpdateTime(codesVal.getTime());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if (null != dbWaterMeterH && null != dbWaterMeterH.getMeterReading()) {
|
|
|
+ waterMeterH = execWaterHourMeter(mDevice, String.valueOf(dbWaterMeterH.getMeterReading()),
|
|
|
+ newMeterReading);
|
|
|
|
|
|
- // 如果有更新,则保存回数据库
|
|
|
- if (updated) {
|
|
|
- attrValue = JSON.toJSONString(tableItems);
|
|
|
- objAttr.setAttrValue(attrValue);
|
|
|
- objAttrValueService.updateObjAttrValue(objAttr);
|
|
|
+ // 更新缓存
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // 无缓存也无数据库记录,则认为是首次上报
|
|
|
+ if (StringUtils.isNotEmpty(newMeterReading)) {
|
|
|
+ updateCacheAfterSuccess(deviceCode, cacheKey, newMeterReading);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- catch (Exception e) {
|
|
|
- log.error("更新设备属性异常", e);
|
|
|
- }
|
|
|
+
|
|
|
+ return waterMeterH;
|
|
|
}
|
|
|
|
|
|
private Set<String> getPointIds(List<EmsObjAttrValue> attrValues) {
|