diff --git a/fastbee-admin/src/main/resources/application-dev.yml b/fastbee-admin/src/main/resources/application-dev.yml
index c73727ba..68a7be53 100644
--- a/fastbee-admin/src/main/resources/application-dev.yml
+++ b/fastbee-admin/src/main/resources/application-dev.yml
@@ -129,7 +129,7 @@ emqx:
ApiSecret: emqx.api.123
# sip 配置
sip:
- enabled: true # 是否启用视频监控SIP,true为启用
+ enabled: false # 是否启用视频监控SIP,true为启用
## 本地调试时,绑定网卡局域网IP,设备在同一局域网,设备接入IP填写绑定IP
## 部署服务端时,默认绑定容器IP,设备接入IP填写服务器公网IP
ip: 192.168.110.160 # 本服务启动的 IP
diff --git a/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java b/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java
index ec6d5b7f..65dbaa7e 100644
--- a/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java
+++ b/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java
@@ -239,10 +239,18 @@ public interface FastBeeConstant {
String DEVICE_PRE_KEY = "TSLV:";
/**
- * 物模型缓存
+ * 物模型缓存(产品级)
+ * Key格式:TSL:{productId} hKey: identifier value: thingsModel
*/
String TSL_PRE_KEY = "TSL:";
+ /**
+ * 设备级计算物模型缓存
+ * Key格式:TSLD:{deviceId} hKey: identifier value: thingsModel
+ * 用于存储设备级别的纯计算物模型,device_id > 0
+ */
+ String TSLD_PRE_KEY = "TSLD:";
+
String MODBUS_PRE_KEY = "MODBUS:";
/**
diff --git a/fastbee-common/src/main/java/com/fastbee/common/core/redis/RedisKeyBuilder.java b/fastbee-common/src/main/java/com/fastbee/common/core/redis/RedisKeyBuilder.java
index 067576fd..18d5ecd2 100644
--- a/fastbee-common/src/main/java/com/fastbee/common/core/redis/RedisKeyBuilder.java
+++ b/fastbee-common/src/main/java/com/fastbee/common/core/redis/RedisKeyBuilder.java
@@ -54,13 +54,21 @@ public class RedisKeyBuilder {
}
/**
- * 物模型缓存key
+ * 物模型缓存key(产品级)
* 物模型命名空间:Key:TSL:{productId} hkey: identity value: thingsModel
*/
public static String buildTSLCacheKey(Long productId) {
return FastBeeConstant.REDIS.TSL_PRE_KEY + productId;
}
+ /**
+ * 设备级计算物模型缓存key
+ * 物模型命名空间:Key:TSLD:{SerialNumber} hkey: identity value: thingsModel
+ */
+ public static String buildDeviceTSLCacheKey(String serialNumber) {
+ return FastBeeConstant.REDIS.TSLD_PRE_KEY + serialNumber;
+ }
+
public static String buildModbusKey(Long productId) {
return FastBeeConstant.REDIS.MODBUS_PRE_KEY + productId;
}
diff --git a/fastbee-common/src/main/java/com/fastbee/common/core/thingsModel/ThingsModelSimpleItem.java b/fastbee-common/src/main/java/com/fastbee/common/core/thingsModel/ThingsModelSimpleItem.java
index 0fe2ebd0..5744fa02 100644
--- a/fastbee-common/src/main/java/com/fastbee/common/core/thingsModel/ThingsModelSimpleItem.java
+++ b/fastbee-common/src/main/java/com/fastbee/common/core/thingsModel/ThingsModelSimpleItem.java
@@ -39,6 +39,11 @@ public class ThingsModelSimpleItem {
**/
private String remark;
+ /**
+ * 是否纯计算型物模型
+ */
+ private boolean isCalculated;
+
public ThingsModelSimpleItem(String id, String value, String remark) {
this.id = id;
@@ -88,4 +93,12 @@ public class ThingsModelSimpleItem {
public void setName(String name) {
this.name = name;
}
+
+ public boolean isCalculated() {
+ return isCalculated;
+ }
+
+ public void setCalculated(boolean calculated) {
+ isCalculated = calculated;
+ }
}
diff --git a/fastbee-protocol/fastbee-protocol-collect/src/main/java/com/fastbee/modbus/codec/ModbusProtocol.java b/fastbee-protocol/fastbee-protocol-collect/src/main/java/com/fastbee/modbus/codec/ModbusProtocol.java
index d82b03e6..6aa9e07c 100644
--- a/fastbee-protocol/fastbee-protocol-collect/src/main/java/com/fastbee/modbus/codec/ModbusProtocol.java
+++ b/fastbee-protocol/fastbee-protocol-collect/src/main/java/com/fastbee/modbus/codec/ModbusProtocol.java
@@ -19,11 +19,9 @@ import com.fastbee.common.utils.StringUtils;
import com.fastbee.common.utils.gateway.CRC16Utils;
import com.fastbee.common.utils.modbus.BitUtils;
import com.fastbee.helper.ModbusProtocolHelper;
-import com.fastbee.iot.cache.ICalculatedThingsModelCache;
import com.fastbee.iot.cache.IModbusConfigCache;
-import com.fastbee.iot.domain.Device;
+import com.fastbee.iot.cache.ITSLCache;
import com.fastbee.iot.domain.ModbusConfig;
-import com.fastbee.iot.mapper.DeviceMapper;
import com.fastbee.iot.mapper.ModbusConfigMapper;
import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem;
import com.fastbee.iot.service.ISubGatewayService;
@@ -40,7 +38,6 @@ import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -63,14 +60,12 @@ public class ModbusProtocol implements IProtocol {
private IModbusConfigCache modbusConfigCache;
@Resource
private ISubGatewayService subGatewayService;
- @Resource
- private DeviceMapper deviceMapper;
@Resource
private ModbusConfigMapper modbusConfigMapper;
@Resource
- private ICalculatedThingsModelCache calculatedThingsModelCache;
+ private ITSLCache itslCache;
@Override
public DeviceReport decode(DeviceData deviceData, String clientId) {
@@ -103,16 +98,16 @@ public class ModbusProtocol implements IProtocol {
case Read01:
case Read02:
//起始地址
- String address0102 = getCacheModbusAddress(deviceData.getSerialNumber(), slaveId, code);
+ String address0102 = getCacheModbusAddress(productId, slaveId, code);
//读线圈或读离散型寄存器处理
handleRead0102(productId, message, address0102, values);
break;
case Read03:
case Read04:
//起始地址
- String address0304 = getCacheModbusAddress(deviceData.getSerialNumber(), slaveId, code);
+ String address0304 = getCacheModbusAddress(productId, slaveId, code);
//读输入、保持寄存器
- handleRead0304(productId, message, address0304, values, hexDump);
+ handleRead0304(deviceData.getSerialNumber(), productId, message, address0304, values, hexDump);
break;
case Write06:
case Write05:
@@ -191,13 +186,14 @@ public class ModbusProtocol implements IProtocol {
/**
* 处理读保持寄存器/输入寄存器
*
+ * @param serialNumber 设备序列号
* @param productId 产品id
* @param message 数据
* @param address 起始地址
* @param simpleItemList 返回的物模型值
* @param sourceStr 原始报文字符串
*/
- private void handleRead0304(Long productId, ModbusRtu message, String address, List simpleItemList, String sourceStr) {
+ private void handleRead0304(String serialNumber, Long productId, ModbusRtu message, String address, List simpleItemList, String sourceStr) {
short[] data = message.getData();
int length = data.length;
if (length == 1) {
@@ -318,50 +314,35 @@ public class ModbusProtocol implements IProtocol {
}
// 处理纯计算物模型:查询产品下所有纯计算物模型,构造 ThingsModelSimpleItem,值为 "0"
- handleCalculatedThingsModels(productId, simpleItemList, isReadOnly);
+ handleCalculatedThingsModels(serialNumber, simpleItemList);
}
}
/**
- * 处理纯计算物模型
- * 从缓存获取纯计算物模型列表,构造 ThingsModelSimpleItem,值为 "0"
- * 后续在计算环节会统一处理所有物模型(包括纯计算物模型)
+ * 从redis获取 纯计算物模型(设备级别物模型)
*
- * @param productId 产品ID
+ * @param serialNumber 设备编号
* @param simpleItemList 物模型值列表
- * @param isReadOnly 是否只读
*/
- private void handleCalculatedThingsModels(Long productId, List simpleItemList, int isReadOnly) {
+ private void handleCalculatedThingsModels(String serialNumber, List simpleItemList) {
+
try {
- // 从缓存获取纯计算物模型标识符集合(支持产品级别和设备级别)
- Set calculatedIdentifiers = calculatedThingsModelCache.getCalculatedIdentifiers(productId, null);
-
- if (calculatedIdentifiers.isEmpty()) {
- return;
- }
-
- // 获取已上报的物模型标识符集合(避免重复)
- Set reportedIdentifiers = simpleItemList.stream()
- .map(ThingsModelSimpleItem::getId)
- .collect(Collectors.toSet());
-
- // 为纯计算物模型构造 ThingsModelSimpleItem
- for (String identifier : calculatedIdentifiers) {
- // 跳过已上报的物模型
- if (reportedIdentifiers.contains(identifier)) {
- continue;
- }
-
- // 构造 ThingsModelSimpleItem,值为 "0"
+ Map calculatedModelMap = itslCache.getDeviceCalculatedModelMap(serialNumber);
+
+ // 构造 ThingsModelSimpleItem,值为 "0"
+ for (Map.Entry entry : calculatedModelMap.entrySet()) {
+ String identifier = entry.getKey();
+
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
simpleItem.setId(identifier);
simpleItem.setValue("0"); // 初始值设为0,后续在计算环节会重新计算
simpleItem.setTs(DateUtils.getNowDate());
+ simpleItem.setCalculated(true);
simpleItemList.add(simpleItem);
- log.debug("=>添加纯计算物模型到上报列表,产品ID:[{}],标识符:[{}]", productId, identifier);
+ log.debug("=>添加纯计算物模型到上报列表,设备:[{}],标识符:[{}]", serialNumber, identifier);
}
} catch (Exception e) {
- log.error("=>处理纯计算物模型时发生错误,产品ID:[{}],错误:{}", productId, e.getMessage(), e);
+ log.error("=>处理纯计算物模型时发生错误,设备:[{}],错误:{}", serialNumber, e.getMessage(), e);
}
}
@@ -484,9 +465,9 @@ public class ModbusProtocol implements IProtocol {
}
/**
- * 获取modbus地址
+ * 获取寄存器最小modbus地址,从最小的寄存器地址开始解码
*/
- private String getCacheModbusAddress(String serialNumber, int salveId, int code) {
+ private String getCacheModbusAddress(Long productId, int salveId, int code) {
// String key = RedisKeyBuilder.buildModbusRuntimeCacheKey(serialNumber);
// Set commandSet = redisCache.zRange(key, 0, -1);
//
@@ -502,13 +483,14 @@ public class ModbusProtocol implements IProtocol {
// log.warn("解析指令异常: {}", e.getMessage());
// }
// }
+ // todo 拿缓存
// 2. 无匹配时查询数据库
try {
- Device device = deviceMapper.selectDeviceBySerialNumber(serialNumber);
- if (device == null) return "0";
+// Device device = deviceMapper.selectDeviceBySerialNumber(serialNumber);
+// if (device == null) return "0";
- List configs = modbusConfigMapper.selectModbusConfigListByProductId(device.getProductId());
+ List configs = modbusConfigMapper.selectModbusConfigListByProductId(productId);
if (CollectionUtils.isEmpty(configs)) return "0";
return configs.stream()
diff --git a/fastbee-server/iot-server-core/src/main/java/com/fastbee/server/handler/DelimiterBasedFrameDecoder.java b/fastbee-server/iot-server-core/src/main/java/com/fastbee/server/handler/DelimiterBasedFrameDecoder.java
index 7e48b12f..6e0d5c9d 100644
--- a/fastbee-server/iot-server-core/src/main/java/com/fastbee/server/handler/DelimiterBasedFrameDecoder.java
+++ b/fastbee-server/iot-server-core/src/main/java/com/fastbee/server/handler/DelimiterBasedFrameDecoder.java
@@ -125,12 +125,13 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
if (minDelim != null) {
int minDelimLength = minDelim.value.length;
ByteBuf frame = null;
+ boolean keepDelimiterForNextFrame = shouldKeepDelimiterForNextFrame(minDelim) && minFrameLength > 0;
if (discardingTooLongFrame) {
// 如果true,将长度不符合报文丢弃
// 初始化原来的值
discardingTooLongFrame = false;
- buffer.skipBytes(minFrameLength + minDelimLength);
+ buffer.skipBytes(minFrameLength + (keepDelimiterForNextFrame ? 0 : minDelimLength));
int tooLongFrameLength = this.tooLongFrameLength;
this.tooLongFrameLength = 0;
@@ -142,10 +143,16 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
/*小于最小长度帧处理*/
if (minFrameLength > maxFrameLength) {
//放弃读取帧
- buffer.skipBytes(minFrameLength + minDelimLength);
+ buffer.skipBytes(minFrameLength + (keepDelimiterForNextFrame ? 0 : minDelimLength));
fail(minFrameLength);
return null;
}
+
+ if (keepDelimiterForNextFrame) {
+ frame = buffer.readRetainedSlice(minFrameLength);
+ return frame;
+ }
+
/*是否需要跳过某字节*/
if (minDelim.strip) {
//忽略长度等于0的报文
@@ -182,6 +189,15 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
return null;
}
}
+
+ /**
+ * 7E 分隔符需要保留给下一帧作为帧头使用(仅在存在前置数据时)。
+ */
+ private boolean shouldKeepDelimiterForNextFrame(Delimiter delimiter) {
+ return !delimiter.strip
+ && delimiter.value.length == 1
+ && (delimiter.value[0] & 0xFF) == 0x7E;
+ }
/**
* 检测7E帧格式(注册包/心跳包)
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ICalculatedThingsModelCache.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ICalculatedThingsModelCache.java
deleted file mode 100644
index b785bb0c..00000000
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ICalculatedThingsModelCache.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.fastbee.iot.cache;
-
-import java.util.Set;
-
-/**
- * 纯计算物模型缓存接口
- * 支持产品级别和设备级别的缓存
- * 支持本地缓存和 Redis 缓存的切换
- *
- * @author Sumuxi
- * @date 2026-01-02
- */
-public interface ICalculatedThingsModelCache {
-
- /**
- * 获取产品下的纯计算物模型标识符集合
- * @param productId 产品ID
- * @return 纯计算物模型标识符集合
- */
- Set getCalculatedIdentifiersByProduct(Long productId);
-
- /**
- * 获取设备下的纯计算物模型标识符集合
- * 如果设备有自定义物模型,返回设备级别的;否则返回产品级别的
- * @param productId 产品ID
- * @param deviceId 设备ID(可选,未来扩展)
- * @return 纯计算物模型标识符集合
- */
- Set getCalculatedIdentifiers(Long productId, Long deviceId);
-
- /**
- * 设置产品下的纯计算物模型标识符集合
- * @param productId 产品ID
- * @param identifiers 纯计算物模型标识符集合
- */
- void setCalculatedIdentifiersByProduct(Long productId, Set identifiers);
-
- /**
- * 刷新产品下的纯计算物模型缓存
- * @param productId 产品ID
- */
- void refreshCalculatedCache(Long productId);
-
- /**
- * 清除产品下的纯计算物模型缓存
- * @param productId 产品ID
- */
- void clearCalculatedCache(Long productId);
-
- /**
- * 判断是否使用 Redis 缓存
- * @return true-使用Redis,false-使用本地缓存
- */
- boolean isRedisCacheEnabled();
-}
-
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ITSLCache.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ITSLCache.java
index 3c512bbb..ff959769 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ITSLCache.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/ITSLCache.java
@@ -61,7 +61,7 @@ public interface ITSLCache {
* \"name\":\"光强\",\"order\":0,\"regId\":\"light\",\"type\":1}]}
*
*/
- public String setCacheThingsModelByProductId(Long productId);
+ String setCacheThingsModelByProductId(Long productId);
/**
* 获取map物模型 --返回 Map
@@ -90,7 +90,7 @@ public interface ITSLCache {
* value:PropertyDto
*
*/
- public Map setCacheThMapByProductId(Long productId);
+ Map setCacheThMapByProductId(Long productId);
/**
* 获取单个物模型缓存
@@ -99,6 +99,40 @@ public interface ITSLCache {
* @param identify 标识符
* @return PropertyDto
*/
- public ThingsModelValueItem getSingleThingModels(Long productId, String identify);
+ ThingsModelValueItem getSingleThingModels(Long productId, String identify);
+
+ // ==================== 设备级计算物模型缓存方法 ====================
+
+ /**
+ * 获取设备级计算物模型缓存(Map形式)
+ *
+ * @param serialNumber 设备ID
+ * @return Map<标识符, ThingsModelValueItem>
+ */
+ Map getDeviceCalculatedModelMap(String serialNumber);
+
+ /**
+ * 刷新设备级计算物模型缓存
+ *
+ * @param serialNumber 设备ID
+ * @return Map<标识符, ThingsModelValueItem>
+ */
+ Map refreshDeviceCalculatedModelCache(String serialNumber);
+
+ /**
+ * 清除设备级计算物模型缓存
+ *
+ * @param serialNumber 设备ID
+ */
+ void clearDeviceCalculatedModelCache(String serialNumber);
+
+ /**
+ * 获取单个设备级计算物模型
+ *
+ * @param serialNumber 设备ID
+ * @param identifier 标识符
+ * @return ThingsModelValueItem
+ */
+ ThingsModelValueItem getSingleDeviceCalculatedModel(String serialNumber, String identifier);
}
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelCacheImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelCacheImpl.java
deleted file mode 100644
index 23858419..00000000
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelCacheImpl.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package com.fastbee.iot.cache.impl;
-
-import com.fastbee.iot.cache.ICalculatedThingsModelCache;
-import com.fastbee.iot.domain.ThingsModel;
-import com.fastbee.iot.service.IThingsModelService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
-
-import javax.annotation.Resource;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-/**
- * 纯计算物模型缓存实现(本地缓存)
- * 使用 ConcurrentHashMap 维护本地缓存
- * 适用于计算型物模型数量较少、单机部署的场景
- *
- * @author sumuxi
- * @date 2026/01/02
- */
-@Service("calculatedThingsModelCache")
-@ConditionalOnProperty(name = "fastbee.cache.calculated-things-model.use-redis", havingValue = "false", matchIfMissing = true)
-@Slf4j
-public class CalculatedThingsModelCacheImpl implements ICalculatedThingsModelCache {
-
- /**
- * 本地缓存:productId -> Set(纯计算物模型标识符集合)
- */
- private final ConcurrentHashMap> calculatedCache = new ConcurrentHashMap<>();
-
- /**
- * 设备级别缓存:deviceId -> Set(未来扩展)
- * 当设备有自定义物模型选择时使用
- */
- private final ConcurrentHashMap> deviceCalculatedCache = new ConcurrentHashMap<>();
-
- @Resource
- private IThingsModelService thingsModelService;
-
- /**
- * 是否启用 Redis 缓存(通过配置控制)
- * 默认 false,使用本地缓存
- * 当计算型物模型数量较多或需要集群部署时,设置为 true
- */
- @Value("${fastbee.cache.calculated-things-model.use-redis:false}")
- private boolean useRedisCache;
-
- /**
- * 本地缓存大小阈值
- * 超过此阈值建议切换到 Redis 缓存
- */
- @Value("${fastbee.cache.calculated-things-model.local-cache-threshold:1000}")
- private int localCacheThreshold;
-
- @Override
- public Set getCalculatedIdentifiersByProduct(Long productId) {
- if (productId == null) {
- return Collections.emptySet();
- }
-
- // 从本地缓存获取
- Set identifiers = calculatedCache.get(productId);
- if (identifiers != null) {
- return identifiers;
- }
-
- // 缓存未命中,从数据库加载
- refreshCalculatedCache(productId);
- return calculatedCache.getOrDefault(productId, Collections.emptySet());
- }
-
- @Override
- public Set getCalculatedIdentifiers(Long productId, Long deviceId) {
- // 如果设备有自定义物模型选择,优先返回设备级别的
- if (deviceId != null) {
- Set deviceIdentifiers = deviceCalculatedCache.get(deviceId);
- if (deviceIdentifiers != null) {
- return deviceIdentifiers;
- }
- }
-
- // 否则返回产品级别的
- return getCalculatedIdentifiersByProduct(productId);
- }
-
- @Override
- public void setCalculatedIdentifiersByProduct(Long productId, Set identifiers) {
- if (productId == null) {
- return;
- }
-
- // 检查缓存大小,超过阈值时记录警告
- if (calculatedCache.size() > localCacheThreshold) {
- log.warn("=>纯计算物模型本地缓存大小超过阈值[{}],建议切换到Redis缓存", localCacheThreshold);
- }
-
- calculatedCache.put(productId, identifiers != null ? identifiers : Collections.emptySet());
- }
-
- @Override
- public void refreshCalculatedCache(Long productId) {
- if (productId == null) {
- return;
- }
-
- try {
- // 查询产品下所有物模型
- ThingsModel queryModel = new ThingsModel();
- queryModel.setProductId(productId);
- List allThingsModels = thingsModelService.selectThingsModelList(queryModel);
-
- if (CollectionUtils.isEmpty(allThingsModels)) {
- calculatedCache.put(productId, Collections.emptySet());
- return;
- }
-
- // 筛选出纯计算物模型(isCalculated == 1)
- Set calculatedIdentifiers = allThingsModels.stream()
- .filter(model -> model.getIsCalculated() != null && model.getIsCalculated() == 1)
- .map(ThingsModel::getIdentifier)
- .collect(Collectors.toSet());
-
- calculatedCache.put(productId, calculatedIdentifiers);
- log.debug("=>刷新纯计算物模型本地缓存成功,产品ID:[{}],数量:[{}]", productId, calculatedIdentifiers.size());
- } catch (Exception e) {
- log.error("=>刷新纯计算物模型本地缓存失败,产品ID:[{}],错误:{}", productId, e.getMessage(), e);
- calculatedCache.put(productId, Collections.emptySet());
- }
- }
-
- @Override
- public void clearCalculatedCache(Long productId) {
- if (productId != null) {
- calculatedCache.remove(productId);
- }
- }
-
- @Override
- public boolean isRedisCacheEnabled() {
- return useRedisCache;
- }
-}
-
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelRedisCacheImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelRedisCacheImpl.java
deleted file mode 100644
index 91e435de..00000000
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/CalculatedThingsModelRedisCacheImpl.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-package com.fastbee.iot.cache.impl;
-
-import com.alibaba.fastjson2.JSON;
-import com.fastbee.common.core.redis.RedisCache;
-import com.fastbee.common.core.redis.RedisKeyBuilder;
-import com.fastbee.iot.cache.ICalculatedThingsModelCache;
-import com.fastbee.iot.domain.ThingsModel;
-import com.fastbee.iot.service.IThingsModelService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
-
-import javax.annotation.Resource;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-*/
-/**
- * 纯计算物模型缓存实现(Redis缓存)
- * 使用 Redis 维护缓存,支持集群部署
- * 适用于计算型物模型数量较多、集群部署的场景
- *
- * @author Sumuxi
- * @date 2026-01-02
- *//*
-
-@Service("calculatedThingsModelRedisCache")
-@ConditionalOnProperty(name = "fastbee.cache.calculated-things-model.use-redis", havingValue = "true")
-@Slf4j
-public class CalculatedThingsModelRedisCacheImpl implements ICalculatedThingsModelCache {
-
- */
-/**
- * 缓存过期时间(秒),默认 24 小时
- *//*
-
- @Value("${fastbee.cache.calculated-things-model.redis-ttl:86400}")
- private long redisTtl;
-
- @Resource
- private RedisCache redisCache;
-
- @Resource
- private IThingsModelService thingsModelService;
-
- @Override
- public Set getCalculatedIdentifiersByProduct(Long productId) {
- if (productId == null) {
- return Collections.emptySet();
- }
-
- String cacheKey = RedisKeyBuilder.buildCalculatedThingsModelKey(productId);
- String cacheValue = redisCache.getCacheObject(cacheKey);
-
- if (cacheValue != null) {
- try {
- @SuppressWarnings("unchecked")
- Set result = JSON.parseObject(cacheValue, Set.class);
- return result != null ? result : Collections.emptySet();
- } catch (Exception e) {
- log.warn("=>解析纯计算物模型Redis缓存失败,产品ID:[{}],错误:{}", productId, e.getMessage());
- }
- }
-
- // 缓存未命中,从数据库加载
- refreshCalculatedCache(productId);
- cacheValue = redisCache.getCacheObject(cacheKey);
- if (cacheValue != null) {
- try {
- @SuppressWarnings("unchecked")
- Set result = JSON.parseObject(cacheValue, Set.class);
- return result != null ? result : Collections.emptySet();
- } catch (Exception e) {
- log.warn("=>解析纯计算物模型Redis缓存失败,产品ID:[{}],错误:{}", productId, e.getMessage());
- }
- }
-
- return Collections.emptySet();
- }
-
- @Override
- public Set getCalculatedIdentifiers(Long productId, Long deviceId) {
- // 如果设备有自定义物模型选择,优先返回设备级别的
- if (deviceId != null) {
- String deviceCacheKey = RedisKeyBuilder.buildCalculatedThingsModelDeviceKey(deviceId);
- String deviceCacheValue = redisCache.getCacheObject(deviceCacheKey);
- if (deviceCacheValue != null) {
- try {
- @SuppressWarnings("unchecked")
- Set result = JSON.parseObject(deviceCacheValue, Set.class);
- return result != null ? result : Collections.emptySet();
- } catch (Exception e) {
- log.warn("=>解析设备纯计算物模型Redis缓存失败,设备ID:[{}],错误:{}", deviceId, e.getMessage());
- }
- }
- }
-
- // 否则返回产品级别的
- return getCalculatedIdentifiersByProduct(productId);
- }
-
- @Override
- public void setCalculatedIdentifiersByProduct(Long productId, Set identifiers) {
- if (productId == null) {
- return;
- }
-
- String cacheKey = RedisKeyBuilder.buildCalculatedThingsModelKey(productId);
- String cacheValue = JSON.toJSONString(identifiers != null ? identifiers : Collections.emptySet());
- redisCache.setCacheObject(cacheKey, cacheValue, (int) redisTtl, java.util.concurrent.TimeUnit.SECONDS);
- }
-
- @Override
- public void refreshCalculatedCache(Long productId) {
- if (productId == null) {
- return;
- }
-
- try {
- // 查询产品下所有物模型
- ThingsModel queryModel = new ThingsModel();
- queryModel.setProductId(productId);
- List allThingsModels = thingsModelService.selectThingsModelList(queryModel);
-
- if (CollectionUtils.isEmpty(allThingsModels)) {
- setCalculatedIdentifiersByProduct(productId, Collections.emptySet());
- return;
- }
-
- // 筛选出纯计算物模型(isCalculated == 1)
- Set calculatedIdentifiers = allThingsModels.stream()
- .filter(model -> model.getIsCalculated() != null && model.getIsCalculated() == 1)
- .map(ThingsModel::getIdentifier)
- .collect(Collectors.toSet());
-
- setCalculatedIdentifiersByProduct(productId, calculatedIdentifiers);
- log.debug("=>刷新纯计算物模型Redis缓存成功,产品ID:[{}],数量:[{}]", productId, calculatedIdentifiers.size());
- } catch (Exception e) {
- log.error("=>刷新纯计算物模型Redis缓存失败,产品ID:[{}],错误:{}", productId, e.getMessage(), e);
- setCalculatedIdentifiersByProduct(productId, Collections.emptySet());
- }
- }
-
- @Override
- public void clearCalculatedCache(Long productId) {
- if (productId != null) {
- String cacheKey = RedisKeyBuilder.buildCalculatedThingsModelKey(productId);
- redisCache.deleteObject(cacheKey);
- }
- }
-
- @Override
- public boolean isRedisCacheEnabled() {
- return true;
- }
-}
-
-*/
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/ModbusConfigCacheImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/ModbusConfigCacheImpl.java
index 5d441339..971ca208 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/ModbusConfigCacheImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/ModbusConfigCacheImpl.java
@@ -76,6 +76,10 @@ public class ModbusConfigCacheImpl implements IModbusConfigCache {
resultMap.put(entry.getKey() + "", valueStr);
}
String modbusKey = RedisKeyBuilder.buildModbusKey(productId);
+ // 先删除缓存,再插入缓存——完成缓存更新
+ if (redisCache.containsKey(modbusKey)) {
+ redisCache.deleteObject(modbusKey);
+ }
redisCache.hashPutAll(modbusKey, resultMap);
return listMap;
}
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLCacheImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLCacheImpl.java
index 36a9c596..877f416b 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLCacheImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLCacheImpl.java
@@ -23,10 +23,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -159,11 +156,9 @@ public class TSLCacheImpl implements ITSLCache {
/*组装成原格式数据*/
Map> result = thingsModelMap.values().stream().map(x -> JSON.parseObject(x, ThingsModelValueItem.class))
.collect(Collectors.groupingBy(dto -> ThingsModelType.getName(dto.getType())));
- if (result != null) {
- for (List itemList : result.values()) {
- for (ThingsModelValueItem item : itemList) {
- convertModelName(item, SecurityUtils.getLanguage());
- }
+ for (List itemList : result.values()) {
+ for (ThingsModelValueItem item : itemList) {
+ convertModelName(item, SecurityUtils.getLanguage());
}
}
String jsonString = JSON.toJSONString(result);
@@ -289,6 +284,7 @@ public class TSLCacheImpl implements ITSLCache {
// 数据库查询物模型集合
ThingsModel model = new ThingsModel();
model.setProductId(productId);
+ model.setIsCalculated(0); // 只查询产品级物模型
model.setLimitValue(SecurityUtils.getLanguage());
List thingsModels = thingsModelService.selectThingsModelList(model);
//modbus配置参数整合到物模型
@@ -325,12 +321,132 @@ public class TSLCacheImpl implements ITSLCache {
/*缓存到redis*/
String cacheKey = RedisKeyBuilder.buildTSLCacheKey(productId);
- //先删除缓存
+ // 先删除缓存
if (redisCache.containsKey(cacheKey)) {
redisCache.deleteObject(cacheKey);
}
+ // 再插入缓存——完成缓存更新
redisCache.hashPutAll(cacheKey, thingsModelMap);
return thingsModelMap;
}
+ // ==================== 设备级计算物模型缓存方法 ====================
+
+ /**
+ * 获取设备级计算物模型缓存(Map形式)
+ *
+ * @param serialNumber 设备ID
+ * @return Map<标识符, ThingsModelValueItem>
+ */
+ @Override
+ public Map getDeviceCalculatedModelMap(String serialNumber) {
+ if (StringUtils.isEmpty(serialNumber)) {
+ return Collections.emptyMap();
+ }
+ String cacheKey = RedisKeyBuilder.buildDeviceTSLCacheKey(serialNumber);
+ Map map = redisCache.getCacheMap(cacheKey);
+ if (!CollectionUtils.isEmpty(map)) {
+ Map itemMap = map.values().stream()
+ .map(v -> JSON.parseObject(v.toString(), ThingsModelValueItem.class))
+ .collect(Collectors.toMap(ThingsModelValueItem::getId, Function.identity()));
+ for (ThingsModelValueItem item : itemMap.values()) {
+ convertModelName(item, SecurityUtils.getLanguage());
+ }
+ return itemMap;
+ }
+ // 缓存未命中,从数据库加载
+ return refreshDeviceCalculatedModelCache(serialNumber);
+ }
+
+ /**
+ * 刷新设备级计算物模型缓存
+ *
+ * @param serialNumber 设备ID
+ * @return Map<标识符, ThingsModelValueItem>
+ */
+ @Override
+ public Map refreshDeviceCalculatedModelCache(String serialNumber) {
+ if (StringUtils.isEmpty(serialNumber)) {
+ return Collections.emptyMap();
+ }
+ // 从数据库查询设备级计算物模型
+ ThingsModel model = new ThingsModel();
+ model.setSerialNumber(serialNumber);
+ model.setIsCalculated(1); // 查询设备级物模型
+ List models = thingsModelService.selectThingsModelList(model);
+ if (CollectionUtils.isEmpty(models)) {
+ // 清除可能存在的旧缓存
+ clearDeviceCalculatedModelCache(serialNumber);
+ return Collections.emptyMap();
+ }
+
+ // 转换为缓存格式
+ Map cacheMap = models.stream().collect(Collectors.toMap(
+ ThingsModel::getIdentifier,
+ thingsModel -> {
+ ThingsModelValueItem dto = new ThingsModelValueItem();
+ BeanUtils.copyProperties(thingsModel, dto);
+ dto.setDatatype(JSONObject.parseObject(thingsModel.getSpecs(), Datatype.class))
+ .setId(thingsModel.getIdentifier())
+ .setName(thingsModel.getModelName())
+ .setName_zh_CN(thingsModel.getModelName_zh_CN())
+ .setName_en_US(thingsModel.getModelName_en_US())
+ .setOrder(thingsModel.getModelOrder())
+ .setModelId(thingsModel.getModelId())
+ .setFormula(thingsModel.getFormula())
+ .setIsCalculated(thingsModel.getIsCalculated());
+ return JSONObject.toJSONString(dto);
+ }
+ ));
+
+ // 缓存到Redis——先删再写
+ String cacheKey = RedisKeyBuilder.buildDeviceTSLCacheKey(serialNumber);
+ if (redisCache.containsKey(cacheKey)) {
+ redisCache.deleteObject(cacheKey);
+ }
+ redisCache.hashPutAll(cacheKey, cacheMap);
+
+ // 返回转换后的Map
+ return cacheMap.values().stream()
+ .map(v -> JSON.parseObject(v, ThingsModelValueItem.class))
+ .collect(Collectors.toMap(ThingsModelValueItem::getId, Function.identity()));
+ }
+
+ /**
+ * 清除设备级计算物模型缓存
+ *
+ * @param serialNumber 设备ID
+ */
+ @Override
+ public void clearDeviceCalculatedModelCache(String serialNumber) {
+ if (StringUtils.isNotEmpty(serialNumber)) {
+ String cacheKey = RedisKeyBuilder.buildDeviceTSLCacheKey(serialNumber);
+ redisCache.deleteObject(cacheKey);
+ }
+ }
+
+ /**
+ * 获取单个设备级计算物模型
+ *
+ * @param serialNumber 设备ID
+ * @param identifier 标识符
+ * @return ThingsModelValueItem
+ */
+ @Override
+ public ThingsModelValueItem getSingleDeviceCalculatedModel(String serialNumber, String identifier) {
+ if (StringUtils.isEmpty(serialNumber) || StringUtils.isEmpty(identifier)) {
+ return null;
+ }
+ String cacheKey = RedisKeyBuilder.buildDeviceTSLCacheKey(serialNumber);
+ String itemStr = redisCache.getCacheMapValue(cacheKey, identifier);
+ if (StringUtils.isEmpty(itemStr)) {
+ // 尝试刷新缓存后再获取
+ Map modelMap = getDeviceCalculatedModelMap(serialNumber);
+ return modelMap.get(identifier);
+ }
+ ThingsModelValueItem item = JSONObject.parseObject(itemStr, ThingsModelValueItem.class);
+ convertModelName(item, SecurityUtils.getLanguage());
+ return item;
+ }
+
}
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLValueCacheImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLValueCacheImpl.java
index c4e0bfae..20100f7c 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLValueCacheImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/cache/impl/TSLValueCacheImpl.java
@@ -43,8 +43,8 @@ public class TSLValueCacheImpl implements ITSLValueCache {
public List getCacheDeviceStatus(Long productId, String deviceNumber) {
String key = RedisKeyBuilder.buildTSLVCacheKey(productId, deviceNumber);
Map map = redisCache.hashEntity(key);
- List valueList = new ArrayList<>();
- if (map == null || map.size() == 0) {
+ List valueList;
+ if (map == null || map.isEmpty()) {
// 缓存设备状态(物模型值)到redis
valueList = addCacheDeviceStatus(productId, deviceNumber);
} else {
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/domain/ThingsModel.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/domain/ThingsModel.java
index 6ad5372d..5a25dd40 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/domain/ThingsModel.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/domain/ThingsModel.java
@@ -63,6 +63,18 @@ public class ThingsModel extends BaseEntity {
@ApiModelProperty("产品名称")
private String productName;
+ /**
+ * 设备ID(0表示产品级物模型,>0表示设备级计算物模型)
+ */
+ @ApiModelProperty(value = "设备ID", notes = "0表示产品级物模型,>0表示设备级计算物模型")
+ private Long deviceId;
+
+ /**
+ * 设备编号
+ */
+ @ApiModelProperty("设备编号")
+ private String serialNumber;
+
/**
* 租户ID
*/
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java
index 24fd58cb..a2481b84 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java
@@ -156,7 +156,6 @@ public class DeviceServiceImpl implements IDeviceService {
@Value("${server.tcp.port}")
private Long tcpPort;
-
// select cache
/**
@@ -165,7 +164,8 @@ public class DeviceServiceImpl implements IDeviceService {
* @param deviceId 设备主键
* @return 设备
*/
-// @Cacheable(cacheNames = "Device", key = "#root.methodName + ':' + #serialNumber", unless = "#result == null")
+ // @Cacheable(cacheNames = "Device", key = "#root.methodName + ':' +
+ // #serialNumber", unless = "#result == null")
@Override
public Device selectDeviceByDeviceId(Long deviceId) {
Device device = deviceMapper.selectDeviceByDeviceId(deviceId);
@@ -174,7 +174,7 @@ public class DeviceServiceImpl implements IDeviceService {
// redis中获取设备状态(物模型值)
device.setThingsModelValue(JSONObject.toJSONString(list));
}
- //查询关联的监控设备
+ // 查询关联的监控设备
SipRelation sipRelation = new SipRelation();
sipRelation.setReDeviceId(deviceId);
List sipRelationList = sipRelationService.selectSipRelationList(sipRelation);
@@ -280,7 +280,8 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Caching(evict = {
@CacheEvict(cacheNames = "Device", key = "'selectDeviceBySerialNumber:' + #device.getSerialNumber()"),
-// @CacheEvict(cacheNames = "Device", key = "'selectDeviceByDeviceId:' + #device.getSerialNumber()"),
+ // @CacheEvict(cacheNames = "Device", key = "'selectDeviceByDeviceId:' +
+ // #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectDeviceStatusAndTransportStatus:' + #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectProtocolBySerialNumber:' + #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectShortDeviceBySerialNumber:' + #device.getSerialNumber()")
@@ -312,7 +313,8 @@ public class DeviceServiceImpl implements IDeviceService {
@Caching(evict = {
@CacheEvict(cacheNames = "Device", key = "'selectDeviceBySerialNumber:' + #device.getSerialNumber()"),
-// @CacheEvict(cacheNames = "Device", key = "'selectDeviceByDeviceId:' + #device.getSerialNumber()"),
+ // @CacheEvict(cacheNames = "Device", key = "'selectDeviceByDeviceId:' +
+ // #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectDeviceStatusAndTransportStatus:' + #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectProtocolBySerialNumber:' + #device.getSerialNumber()"),
@CacheEvict(cacheNames = "Device", key = "'selectShortDeviceBySerialNumber:' + #device.getSerialNumber()")
@@ -331,7 +333,7 @@ public class DeviceServiceImpl implements IDeviceService {
@CacheEvict(cacheNames = "Device", allEntries = true)
@Override
public AjaxResult deleteDeviceByDeviceId(Long deviceId) {
- //查询设备
+ // 查询设备
Device device = deviceMapper.selectDeviceByDeviceId(deviceId);
SysUser user = getLoginUser().getUser();
Long sceneUserId;
@@ -356,7 +358,8 @@ public class DeviceServiceImpl implements IDeviceService {
}
// 设备下不能有场景联动
List sceneDeviceBindVOList = sceneDeviceMapper.listSceneDeviceBind(device.getSerialNumber());
- if (null != sceneDeviceBindVOList.stream().filter(s -> s.getUserId().equals(sceneUserId)).findAny().orElse(null)) {
+ if (null != sceneDeviceBindVOList.stream().filter(s -> s.getUserId().equals(sceneUserId)).findAny()
+ .orElse(null)) {
return AjaxResult.error("删除失败,请先删除对应设备下的场景联动");
}
// 查绑定用户被分享用户配置的场景,需要把场景删掉
@@ -393,7 +396,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (null != shareSceneIds && shareSceneIds.length > 0) {
sceneService.deleteSceneBySceneIds(shareSceneIds);
}
- // 删除设备分组。 租户、管理员和设备所有者
+ // 删除设备分组。 租户、管理员和设备所有者
deviceMapper.deleteDeviceGroupByDeviceId(new UserIdDeviceIdModel(null, deviceId));
// 删除设备用户。
deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null, deviceId));
@@ -402,7 +405,7 @@ public class DeviceServiceImpl implements IDeviceService {
// deviceJobService.deleteJobByDeviceIds(new Long[]{deviceId});
// 批量删除设备监测日志
logService.deleteDeviceLogByDeviceNumber(device.getSerialNumber());
- // 批量删除设备事件日志 DeviceNumber
+ // 批量删除设备事件日志 DeviceNumber
eventLogService.deleteEventLogBySerialNumber(device.getSerialNumber());
// 批量删除设备功能日志
functionLogService.deleteFunctionLogByDeviceNumber(device.getSerialNumber());
@@ -412,12 +415,12 @@ public class DeviceServiceImpl implements IDeviceService {
String key = RedisKeyBuilder.buildTSLVCacheKey(device.getProductId(), device.getSerialNumber());
redisCache.deleteObject(key);
// 删除设备
- deviceMapper.deleteDeviceByDeviceIds(new Long[]{deviceId});
+ deviceMapper.deleteDeviceByDeviceIds(new Long[] { deviceId });
// redis中删除规则脚本
String cacheKey = RedisKeyBuilder.buildDeviceMsgCacheKey(device.getSerialNumber());
redisCache.deleteObject(cacheKey);
// 删除设备
- deviceMapper.deleteDeviceByDeviceIds(new Long[]{deviceId});
+ deviceMapper.deleteDeviceByDeviceIds(new Long[] { deviceId });
// 删除tcp协议设备缓存
String tcpKey1 = RedisKeyBuilder.buildModbusTcpCacheKey(device.getSerialNumber());
String tcpKey2 = RedisKeyBuilder.buildModbusTcpRuntimeCacheKey(device.getSerialNumber());
@@ -445,7 +448,6 @@ public class DeviceServiceImpl implements IDeviceService {
return AjaxResult.success();
}
-
/**
* TODO-2.3 查询设备统计信息
*
@@ -486,7 +488,6 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.selectProductAuthenticate(model);
}
-
/**
* 更新设备的物模型
*
@@ -497,33 +498,47 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
@DSTransactional
- public List reportDeviceThingsModelValue(ThingsModelValuesInput input, int type, boolean isShadow) {
- String key = RedisKeyBuilder.buildTSLVCacheKey(input.getProductId(), input.getDeviceNumber());
+ public List reportDeviceThingsModelValue(ThingsModelValuesInput input, int type,
+ boolean isShadow) {
+ String serialNumber = input.getDeviceNumber();
+ String key = RedisKeyBuilder.buildTSLVCacheKey(input.getProductId(), serialNumber);
Map maps = new HashMap<>();
List list = new ArrayList<>();
- //属性存储集合
+ // 属性存储集合
List deviceLogList = new ArrayList<>();
- //指令存储集合
+ // 指令存储集合
List functionLogList = new ArrayList<>();
- //事件存储集合
+ // 事件存储集合
List eventLogList = new ArrayList<>();
// 获取当前时间
Date nowDate = DateUtils.getNowDate();
- for (ThingsModelSimpleItem item : input.getThingsModelValueRemarkItem()) {
+ List thingsModelValueRemarkItem = input.getThingsModelValueRemarkItem();
+ // 判断是否有纯计算物模型 有:需要获取设备级别物模型 无:直接使用产品级别物模型即可
+ boolean isCalculated = thingsModelValueRemarkItem.stream().anyMatch(ThingsModelSimpleItem::isCalculated);
+ Map calculatedModelMap = new HashMap<>();
+ if (isCalculated) {
+ calculatedModelMap = itslCache.getDeviceCalculatedModelMap(serialNumber);
+ }
+ for (ThingsModelSimpleItem item : thingsModelValueRemarkItem) {
String identity = item.getId();
- String serialNumber = input.getDeviceNumber();
if (identity.startsWith("array_")) {
identity = identity.substring(9);
}
-
- ThingsModelValueItem thingModels = thingsModelService.getSingleThingModels(input.getProductId(), identity);
+ ThingsModelValueItem thingModels;
+ if (item.isCalculated()) {
+ // itslCache.getSingleDeviceCalculatedModel(serialNumber, identity);
+ thingModels = calculatedModelMap.get(identity);
+ } else {
+ thingModels = thingsModelService.getSingleThingModels(input.getProductId(), identity);
+ }
if (Objects.isNull(thingModels)) {
log.warn("=>查询物模型为空[{}],标识符:[{}]", input.getProductId(), identity);
continue; // 跳过当前物模型的处理
}
// 获取设备实时值
- ValueItem cacheIdentifier = itslValueCache.getCacheIdentifier(input.getProductId(), input.getDeviceNumber(), thingModels.getId());
+ ValueItem cacheIdentifier = itslValueCache.getCacheIdentifier(input.getProductId(), serialNumber,
+ thingModels.getId());
if (Objects.isNull(cacheIdentifier)) {
log.warn("=>查询物模型值为空[{}],标识符:[{}]", input.getProductId(), identity);
}
@@ -531,9 +546,9 @@ public class DeviceServiceImpl implements IDeviceService {
String value = item.getValue();
item.setName(thingModels.getName());
- /* ★★★★★★★★★★★★★★★★★★★★★★ 数据计算 -开始 ★★★★★★★★★★★★★★★★★★★★★★*/
- //有计算公式的,经过计算公式
- if (thingModels != null && thingModels.getFormula() != null && !"".equals(thingModels.getFormula())) {
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 数据计算 -开始 ★★★★★★★★★★★★★★★★★★★★★★ */
+ // 有计算公式的,经过计算公式
+ if (thingModels.getFormula() != null && StringUtils.isNotEmpty(thingModels.getFormula())) {
Map params = new HashMap<>();
// %s 表示当前物模型的值(保持向后兼容)
params.put("%s", value);
@@ -549,7 +564,7 @@ public class DeviceServiceImpl implements IDeviceService {
try {
// 优先从当前消息中查找
String refValue = null;
- for (ThingsModelSimpleItem currentItem : input.getThingsModelValueRemarkItem()) {
+ for (ThingsModelSimpleItem currentItem : thingsModelValueRemarkItem) {
String currentId = currentItem.getId();
if (currentId.startsWith("array_")) {
currentId = currentId.substring(9);
@@ -564,9 +579,8 @@ public class DeviceServiceImpl implements IDeviceService {
if (refValue == null) {
ValueItem refValueItem = itslValueCache.getCacheIdentifier(
input.getProductId(),
- input.getDeviceNumber(),
- refIdentifier
- );
+ serialNumber,
+ refIdentifier);
if (refValueItem != null && StringUtils.isNotEmpty(refValueItem.getValue())) {
refValue = refValueItem.getValue();
}
@@ -590,15 +604,15 @@ public class DeviceServiceImpl implements IDeviceService {
log.info("=>纯计算物模型结果[{}],标识符:[{}],结果:{}", input.getProductId(), identity, value);
item.setValue(value);
}
- /* ★★★★★★★★★★★★★★★★★★★★★★ 数据计算 -结束 ★★★★★★★★★★★★★★★★★★★★★★*/
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 数据计算 -结束 ★★★★★★★★★★★★★★★★★★★★★★ */
- /* ★★★★★★★★★★★★★★★★★★★★★★ 处理数据 - 开始 ★★★★★★★★★★★★★★★★★★★★★★*/
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 处理数据 - 开始 ★★★★★★★★★★★★★★★★★★★★★★ */
ValueItem valueItem = new ValueItem();
valueItem.setId(identity);
if (id.startsWith("array_")) {
// 查询是否有缓存,如果没有先进行缓存
if (!redisCache.containsKey(key)) {
- Device device = this.selectDeviceBySerialNumber(input.getDeviceNumber());
+ Device device = this.selectDeviceBySerialNumber(serialNumber);
this.selectDeviceByDeviceId(device.getDeviceId());
}
@@ -623,7 +637,7 @@ public class DeviceServiceImpl implements IDeviceService {
valueItem.setShadow(String.join(",", shadows));
}
redisCache.setCacheMapValue(key, identity, JSONObject.toJSONString(valueItem));
- //maps.put(identity, JSONObject.toJSONString(valueItem));
+ // maps.put(identity, JSONObject.toJSONString(valueItem));
} else {
if (isShadow) {
valueItem.setShadow(value);
@@ -638,11 +652,11 @@ public class DeviceServiceImpl implements IDeviceService {
}
maps.put(identity, JSONObject.toJSONString(valueItem));
}
- /* ★★★★★★★★★★★★★★★★★★★★★★ 处理数据 - 结束 ★★★★★★★★★★★★★★★★★★★★★★*/
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 处理数据 - 结束 ★★★★★★★★★★★★★★★★★★★★★★ */
- /*★★★★★★★★★★★★★★★★★★★★★★ 存储数据 - 开始 ★★★★★★★★★★★★★★★★★★★★★★*/
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 存储数据 - 开始 ★★★★★★★★★★★★★★★★★★★★★★ */
ThingsModelType modelType = ThingsModelType.getType(thingModels.getType());
- Device device = this.selectDeviceBySerialNumber(input.getDeviceNumber());
+ Device device = this.selectDeviceBySerialNumber(serialNumber);
switch (modelType) {
case PROP:
if (1 == thingModels.getIsHistory()) {
@@ -670,7 +684,7 @@ public class DeviceServiceImpl implements IDeviceService {
FunctionLog function = new FunctionLog();
function.setCreateTime(nowDate);
function.setFunValue(value);
- function.setSerialNumber(input.getDeviceNumber());
+ function.setSerialNumber(serialNumber);
function.setIdentify(id);
function.setShowValue(value);
// 属性获取
@@ -703,22 +717,20 @@ public class DeviceServiceImpl implements IDeviceService {
redisCache.hashPutAll(key, maps);
// 存储历史数据——批量
if (!CollectionUtils.isEmpty(deviceLogList) && !isShadow) {
-// for (DeviceLog deviceLog : deviceLogList) {
-// logService.saveDeviceLog(deviceLog);
-// }
+ // for (DeviceLog deviceLog : deviceLogList) {
+ // logService.saveDeviceLog(deviceLog);
+ // }
logService.saveDeviceLogBatch(deviceLogList);
}
- //指令存储,影子模式不存储
+ // 指令存储,影子模式不存储
if (!CollectionUtils.isEmpty(functionLogList) && !isShadow) {
functionLogService.insertBatch(functionLogList);
}
if (!CollectionUtils.isEmpty(eventLogList)) {
- //事件存储
+ // 事件存储
eventLogService.saveBatch(eventLogList);
}
- /* ★★★★★★★★★★★★★★★★★★★★★★ 存储数据 - 结束 ★★★★★★★★★★★★★★★★★★★★★★*/
-
- // 注意:纯计算物模型已在 ModbusProtocol 中构造 ThingsModelSimpleItem(值为0)
+ /* ★★★★★★★★★★★★★★★★★★★★★★ 存储数据 - 结束 ★★★★★★★★★★★★★★★★★★★★★★ */
return list;
}
@@ -751,17 +763,17 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
public List selectDeviceList(Device device) {
-// SysUser user = getLoginUser().getUser();
-// List roles = user.getRoles();
-// for (int i = 0; i < roles.size(); i++) {
-// if (roles.get(i).getRoleKey().equals("tenant")) {
-// // 租户查看产品下所有设备
-// device.setTenantId(user.getUserId());
-// } else if (roles.get(i).getRoleKey().equals("general")) {
-// // 用户查看自己设备
-// device.setUserId(user.getUserId());
-// }
-// }
+ // SysUser user = getLoginUser().getUser();
+ // List roles = user.getRoles();
+ // for (int i = 0; i < roles.size(); i++) {
+ // if (roles.get(i).getRoleKey().equals("tenant")) {
+ // // 租户查看产品下所有设备
+ // device.setTenantId(user.getUserId());
+ // } else if (roles.get(i).getRoleKey().equals("general")) {
+ // // 用户查看自己设备
+ // device.setUserId(user.getUserId());
+ // }
+ // }
return deviceMapper.selectDeviceList(device);
}
@@ -773,17 +785,17 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
public List selectUnAuthDeviceList(Device device) {
-// SysUser user = getLoginUser().getUser();
-// List roles = user.getRoles();
-// for (int i = 0; i < roles.size(); i++) {
-// if (roles.get(i).getRoleKey().equals("tenant")) {
-// // 租户查看产品下所有设备
-// device.setTenantId(user.getUserId());
-// } else if (roles.get(i).getRoleKey().equals("general")) {
-// // 用户查看自己设备
-// device.setUserId(user.getUserId());
-// }
-// }
+ // SysUser user = getLoginUser().getUser();
+ // List roles = user.getRoles();
+ // for (int i = 0; i < roles.size(); i++) {
+ // if (roles.get(i).getRoleKey().equals("tenant")) {
+ // // 租户查看产品下所有设备
+ // device.setTenantId(user.getUserId());
+ // } else if (roles.get(i).getRoleKey().equals("general")) {
+ // // 用户查看自己设备
+ // device.setUserId(user.getUserId());
+ // }
+ // }
return deviceMapper.selectUnAuthDeviceList(device);
}
@@ -795,17 +807,17 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
public List selectDeviceListByGroup(Device device) {
-// SysUser user = getLoginUser().getUser();
-// List roles = user.getRoles();
-// for (int i = 0; i < roles.size(); i++) {
-// if (roles.get(i).getRoleKey().equals("tenant")) {
-// // 租户查看产品下所有设备
-// device.setTenantId(user.getUserId());
-// } else if (roles.get(i).getRoleKey().equals("general")) {
-// // 用户查看自己设备
-// device.setUserId(user.getUserId());
-// }
-// }
+ // SysUser user = getLoginUser().getUser();
+ // List roles = user.getRoles();
+ // for (int i = 0; i < roles.size(); i++) {
+ // if (roles.get(i).getRoleKey().equals("tenant")) {
+ // // 租户查看产品下所有设备
+ // device.setTenantId(user.getUserId());
+ // } else if (roles.get(i).getRoleKey().equals("general")) {
+ // // 用户查看自己设备
+ // device.setUserId(user.getUserId());
+ // }
+ // }
return deviceMapper.selectDeviceListByGroup(device);
}
@@ -845,7 +857,8 @@ public class DeviceServiceImpl implements IDeviceService {
SysUser user = getLoginUser().getUser();
if (null != user.getDept()) {
Long tenantId = user.getDept().getDeptUserId();
- serialNumberList = list.stream().filter(d -> tenantId.equals(d.getTenantId())).map(DeviceShortOutput::getSerialNumber).collect(Collectors.toList());
+ serialNumberList = list.stream().filter(d -> tenantId.equals(d.getTenantId()))
+ .map(DeviceShortOutput::getSerialNumber).collect(Collectors.toList());
} else {
serialNumberList = list.stream().map(DeviceShortOutput::getSerialNumber).collect(Collectors.toList());
}
@@ -870,19 +883,42 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public DeviceShortOutput selectDeviceRunningStatusByDeviceId(Long deviceId) {
DeviceShortOutput device = deviceMapper.selectDeviceRunningStatusByDeviceId(deviceId);
- JSONObject thingsModelObject = JSONObject.parseObject(itslCache.getCacheThingsModelByProductId(device.getProductId()));
+ // 1. 获取产品级物模型
+ JSONObject thingsModelObject = JSONObject
+ .parseObject(itslCache.getCacheThingsModelByProductId(device.getProductId()));
JSONArray properties = thingsModelObject.getJSONArray("properties");
JSONArray functions = thingsModelObject.getJSONArray("functions");
- List thingsModelValueItems = itslValueCache.getCacheDeviceStatus(device.getProductId(), device.getSerialNumber());
+ List thingsModelValueItems = itslValueCache.getCacheDeviceStatus(device.getProductId(),
+ device.getSerialNumber());
// 物模型转换赋值
List thingsList = new ArrayList<>();
- //判断一下properties 和 functions是否为空, 否则报空指针
+ // 判断一下properties 和 functions是否为空, 否则报空指针
if (!CollectionUtils.isEmpty(properties)) {
thingsList.addAll(convertJsonToThingsList(properties, thingsModelValueItems, 1));
}
if (!CollectionUtils.isEmpty(functions)) {
thingsList.addAll(convertJsonToThingsList(functions, thingsModelValueItems, 2));
}
+
+ // 2. 获取设备级计算物模型并合并
+ Map deviceCalculatedMap = itslCache
+ .getDeviceCalculatedModelMap(device.getSerialNumber());
+ if (!CollectionUtils.isEmpty(deviceCalculatedMap)) {
+ for (ThingsModelValueItem item : deviceCalculatedMap.values()) {
+ // 获取缓存值
+ ValueItem valueItem = thingsModelValueItems.stream()
+ .filter(v -> v.getId().equals(item.getId()))
+ .findFirst()
+ .orElse(null);
+ if (valueItem != null) {
+ item.setValue(valueItem.getValue());
+ item.setShadow(valueItem.getShadow());
+ item.setTs(valueItem.getTs());
+ }
+ thingsList.add(item);
+ }
+ }
+
device.setThingsModels(thingsList);
return device;
@@ -897,7 +933,8 @@ public class DeviceServiceImpl implements IDeviceService {
* @return
*/
@Async
- public List convertJsonToThingsList(JSONArray jsonArray, List thingsModelValues, Integer type) {
+ public List convertJsonToThingsList(JSONArray jsonArray, List thingsModelValues,
+ Integer type) {
List thingsModelList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
ThingsModelValueItem thingsModel = new ThingsModelValueItem();
@@ -905,11 +942,15 @@ public class DeviceServiceImpl implements IDeviceService {
JSONObject datatypeJson = thingsJson.getJSONObject("datatype");
thingsModel.setId(thingsJson.getString("id"));
thingsModel.setName(thingsJson.getString("name"));
- thingsModel.setIsMonitor(thingsJson.getInteger("isMonitor") == null ? 0 : thingsJson.getInteger("isMonitor"));
- thingsModel.setIsReadonly(thingsJson.getInteger("isReadonly") == null ? 0 : thingsJson.getInteger("isReadonly"));
+ thingsModel
+ .setIsMonitor(thingsJson.getInteger("isMonitor") == null ? 0 : thingsJson.getInteger("isMonitor"));
+ thingsModel.setIsReadonly(
+ thingsJson.getInteger("isReadonly") == null ? 0 : thingsJson.getInteger("isReadonly"));
thingsModel.setIsChart(thingsJson.getInteger("isChart") == null ? 0 : thingsJson.getInteger("isChart"));
- thingsModel.setIsSharePerm(thingsJson.getInteger("isSharePerm") == null ? 0 : thingsJson.getInteger("isSharePerm"));
- thingsModel.setIsHistory(thingsJson.getInteger("isHistory") == null ? 0 : thingsJson.getInteger("isHistory"));
+ thingsModel.setIsSharePerm(
+ thingsJson.getInteger("isSharePerm") == null ? 0 : thingsJson.getInteger("isSharePerm"));
+ thingsModel
+ .setIsHistory(thingsJson.getInteger("isHistory") == null ? 0 : thingsJson.getInteger("isHistory"));
thingsModel.setIsApp(thingsJson.getInteger("isApp") == null ? 0 : thingsJson.getInteger("isApp"));
thingsModel.setOrder(thingsJson.getInteger("order") == null ? 0 : thingsJson.getInteger("order"));
thingsModel.setType(type);
@@ -957,9 +998,10 @@ public class DeviceServiceImpl implements IDeviceService {
* @param parentIdentifier 上级标识符
* @return
*/
- private Datatype convertJsonToDataType(JSONObject datatypeJson, List thingsModelValues, Integer type, String parentIdentifier) {
+ private Datatype convertJsonToDataType(JSONObject datatypeJson, List thingsModelValues, Integer type,
+ String parentIdentifier) {
Datatype dataType = new Datatype();
- //有些物模型数据定义为空的情况兼容
+ // 有些物模型数据定义为空的情况兼容
if (datatypeJson == null) {
return dataType;
}
@@ -986,10 +1028,12 @@ public class DeviceServiceImpl implements IDeviceService {
} else if (dataType.getType().equals("object")) {
JSONArray jsonArray = JSON.parseArray(datatypeJson.getString("params"));
// 物模型值过滤(parentId_开头)
- thingsModelValues = thingsModelValues.stream().filter(x -> x.getId().startsWith(parentIdentifier)).collect(Collectors.toList());
+ thingsModelValues = thingsModelValues.stream().filter(x -> x.getId().startsWith(parentIdentifier))
+ .collect(Collectors.toList());
List thingsList = convertJsonToThingsList(jsonArray, thingsModelValues, type);
// 排序
- thingsList = thingsList.stream().sorted(Comparator.comparing(ThingsModelValueItem::getOrder).reversed()).collect(Collectors.toList());
+ thingsList = thingsList.stream().sorted(Comparator.comparing(ThingsModelValueItem::getOrder).reversed())
+ .collect(Collectors.toList());
dataType.setParams(thingsList);
} else if (dataType.getType().equals("array")) {
dataType.setArrayType(datatypeJson.getString("arrayType"));
@@ -998,10 +1042,12 @@ public class DeviceServiceImpl implements IDeviceService {
// 对象数组
JSONArray jsonArray = datatypeJson.getJSONArray("params");
// 物模型值过滤(parentId_开头)
- thingsModelValues = thingsModelValues.stream().filter(x -> x.getId().startsWith(parentIdentifier)).collect(Collectors.toList());
+ thingsModelValues = thingsModelValues.stream().filter(x -> x.getId().startsWith(parentIdentifier))
+ .collect(Collectors.toList());
List thingsList = convertJsonToThingsList(jsonArray, thingsModelValues, type);
// 排序
- thingsList = thingsList.stream().sorted(Comparator.comparing(ThingsModelValueItem::getOrder).reversed()).collect(Collectors.toList());
+ thingsList = thingsList.stream().sorted(Comparator.comparing(ThingsModelValueItem::getOrder).reversed())
+ .collect(Collectors.toList());
// 数组类型物模型里面对象赋值
List[] arrayParams = new List[dataType.getArrayCount()];
for (int i = 0; i < dataType.getArrayCount(); i++) {
@@ -1053,7 +1099,7 @@ public class DeviceServiceImpl implements IDeviceService {
throw new ServiceException("设备编号:" + device.getSerialNumber() + " 已经存在,新增失败");
}
SysUser sysUser = getLoginUser().getUser();
- //添加设备
+ // 添加设备
device.setCreateTime(DateUtils.getNowDate());
device.setTenantId(sysUser.getDept().getDeptUserId());
device.setTenantName(sysUser.getDept().getDeptUserName());
@@ -1067,7 +1113,8 @@ public class DeviceServiceImpl implements IDeviceService {
setLocation(user.getLoginIp(), device);
deviceMapper.insertDevice(device);
// 处理modbus产品
- if (FastBeeConstant.PROTOCOL.ModbusRtu.equals(product.getProtocolCode()) || FastBeeConstant.PROTOCOL.ModbusTcp.equals(product.getProtocolCode())) {
+ if (FastBeeConstant.PROTOCOL.ModbusRtu.equals(product.getProtocolCode())
+ || FastBeeConstant.PROTOCOL.ModbusTcp.equals(product.getProtocolCode())) {
this.handleModbusConfig(device, product);
}
// redis缓存设备默认状态(物模型值)
@@ -1104,15 +1151,18 @@ public class DeviceServiceImpl implements IDeviceService {
return;
}
productSubGatewayList.sort(Comparator.comparing(ProductSubGatewayVO::getSlaveId));
- List subProductIdList = productSubGatewayList.stream().map(ProductSubGatewayVO::getSubProductId).collect(Collectors.toList());
+ List subProductIdList = productSubGatewayList.stream().map(ProductSubGatewayVO::getSubProductId)
+ .collect(Collectors.toList());
LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.in(ProductModbusJob::getProductId, subProductIdList);
List productModbusJobList = productModbusJobMapper.selectList(queryWrapper1);
- Map> productModbusJobMap = productModbusJobList.stream().collect(Collectors.groupingBy(ProductModbusJob::getProductId));
+ Map> productModbusJobMap = productModbusJobList.stream()
+ .collect(Collectors.groupingBy(ProductModbusJob::getProductId));
// 新增子设备、绑定子设备、子设备生成轮询
for (ProductSubGatewayVO productSubGatewayVO : productSubGatewayList) {
Device addDevice = new Device();
- addDevice.setDeviceName(productSubGatewayVO.getSubProductName() + "_" + productSubGatewayVO.getSlaveId());
+ addDevice.setDeviceName(
+ productSubGatewayVO.getSubProductName() + "_" + productSubGatewayVO.getSlaveId());
addDevice.setProductId(productSubGatewayVO.getSubProductId());
addDevice.setProductName(productSubGatewayVO.getSubProductName());
String serialNumber = this.generationDeviceNum(1);
@@ -1134,7 +1184,8 @@ public class DeviceServiceImpl implements IDeviceService {
subGateway.setCreateBy(addDevice.getCreateBy());
subGateway.setCreateTime(new Date());
subGatewayMapper.insertGateway(subGateway);
- List productModbusList = productModbusJobMap.get(productSubGatewayVO.getSubProductId());
+ List productModbusList = productModbusJobMap
+ .get(productSubGatewayVO.getSubProductId());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(productModbusList)) {
for (ProductModbusJob productModbusJob : productModbusList) {
ModbusJob modbusJob = new ModbusJob();
@@ -1164,12 +1215,12 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult deviceRelateUser(DeviceRelateUserInput params) {
- Long userId = params.getUserId(); //终端用户id
+ Long userId = params.getUserId(); // 终端用户id
// 查询用户信息
SysUser sysUser = userService.selectUserById(userId);
for (DeviceNumberAndProductId item : params.getDeviceNumberAndProductIds()) {
Device existDevice = deviceMapper.selectDeviceBySerialNumber(item.getDeviceNumber());
- //查看设备是否已经分配
+ // 查看设备是否已经分配
if (!Objects.isNull(existDevice)) {
if (null != sysUser.getDeptId()) {
return AjaxResult.error("租户不允许绑定已存在的设备,设备编号:" + item.getDeviceNumber());
@@ -1183,7 +1234,8 @@ public class DeviceServiceImpl implements IDeviceService {
}
}
// 先删除设备的所有用户
- //deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null, existDevice.getDeviceId()));
+ // deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null,
+ // existDevice.getDeviceId()));
// 添加新的设备用户
DeviceUser deviceUser = new DeviceUser();
deviceUser.setUserId(sysUser.getUserId());
@@ -1265,13 +1317,14 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public ThingsModelShadow getDeviceShadowThingsModel(Device device) {
// 物模型值
- List thingsModelValueItems = itslValueCache.getCacheDeviceStatus(device.getProductId(), device.getSerialNumber());
+ List thingsModelValueItems = itslValueCache.getCacheDeviceStatus(device.getProductId(),
+ device.getSerialNumber());
ThingsModelShadow shadow = new ThingsModelShadow();
// 查询出设置的影子值
- //List shadowList = new ArrayList<>();
+ // List shadowList = new ArrayList<>();
for (ValueItem item : thingsModelValueItems) {
if (!item.getShadow().equals(item.getValue()) && !item.getShadow().isEmpty()) {
- //处理id
+ // 处理id
String id = item.getId();
if (item.getShadow().contains(",")) {
String[] shadows = item.getShadow().split(",");
@@ -1297,7 +1350,6 @@ public class DeviceServiceImpl implements IDeviceService {
return shadow;
}
-
/**
* 生成设备唯一编号
*
@@ -1308,7 +1360,7 @@ public class DeviceServiceImpl implements IDeviceService {
// 设备编号:D + userId + 15位随机字母和数字
SysUser user = getLoginUser().getUser();
String number;
- //Hex随机字符串
+ // Hex随机字符串
if (type == 3) {
number = toolService.generateRandomHex(12);
} else {
@@ -1433,8 +1485,8 @@ public class DeviceServiceImpl implements IDeviceService {
deviceUserMapper.insertDeviceUser(deviceUser);
}
// 更新设备用户信息 多租户版本不需要
-// device.setTenantId(device.getTenantId());
-// device.setTenantName(sysUser.getUserName());
+ // device.setTenantId(device.getTenantId());
+ // device.setTenantName(sysUser.getUserName());
}
device.setUpdateTime(DateUtils.getNowDate());
if (deviceEntity.getActiveTime() == null || deviceEntity.getActiveTime().equals("")) {
@@ -1459,7 +1511,6 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.selectDevicesByProductId(productId, hasSub);
}
-
/**
* 批量更新设备状态
*
@@ -1472,7 +1523,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (CollectionUtils.isEmpty(serialNumbers)) {
return;
}
- //设备离线
+ // 设备离线
if (DeviceStatus.OFFLINE.equals(status)) {
deviceMapper.batchChangeOffline(serialNumbers);
} else if (DeviceStatus.ONLINE.equals(status)) {
@@ -1514,21 +1565,28 @@ public class DeviceServiceImpl implements IDeviceService {
String password;
if (ProductAuthConstant.AUTHORIZE.equals(deviceMqttVO.getIsAuthorize())) {
// 查询产品授权码
- List productAuthorizeList = productAuthorizeService.listByProductId(deviceMqttVO.getProductId());
+ List productAuthorizeList = productAuthorizeService
+ .listByProductId(deviceMqttVO.getProductId());
if (CollectionUtils.isEmpty(productAuthorizeList)) {
throw new ServiceException("产品已启用授权,获取设备授权码失败,请先配置授权码");
}
- List collect = productAuthorizeList.stream().filter(p -> p.getProductId().equals(deviceMqttVO.getDeviceId())).collect(Collectors.toList());
- ProductAuthorize productAuthorize = CollectionUtils.isEmpty(collect) ? productAuthorizeList.get(0) : collect.get(0);
+ List collect = productAuthorizeList.stream()
+ .filter(p -> p.getProductId().equals(deviceMqttVO.getDeviceId())).collect(Collectors.toList());
+ ProductAuthorize productAuthorize = CollectionUtils.isEmpty(collect) ? productAuthorizeList.get(0)
+ : collect.get(0);
password = deviceMqttVO.getMqttPassword() + "&" + productAuthorize.getAuthorizeCode();
} else {
password = deviceMqttVO.getMqttPassword();
}
- String clientId = ProductAuthConstant.CLIENT_ID_AUTH_TYPE_SIMPLE + "&" + deviceMqttVO.getSerialNumber() + "&" + deviceMqttVO.getProductId() + "&" + deviceMqttVO.getTenantId();
+ String clientId = ProductAuthConstant.CLIENT_ID_AUTH_TYPE_SIMPLE + "&" + deviceMqttVO.getSerialNumber() + "&"
+ + deviceMqttVO.getProductId() + "&" + deviceMqttVO.getTenantId();
// 组装返回结果
- connectVO.setClientId(clientId).setUsername(deviceMqttVO.getMqttAccount()).setPasswd(password).setPort(brokerPort);
- connectVO.setSubscribeTopic("/" + deviceMqttVO.getProductId() + "/" + deviceMqttVO.getSerialNumber() + "/function/get");
- connectVO.setReportTopic("/" + deviceMqttVO.getProductId() + "/" + deviceMqttVO.getSerialNumber() + "/property/post");
+ connectVO.setClientId(clientId).setUsername(deviceMqttVO.getMqttAccount()).setPasswd(password)
+ .setPort(brokerPort);
+ connectVO.setSubscribeTopic(
+ "/" + deviceMqttVO.getProductId() + "/" + deviceMqttVO.getSerialNumber() + "/function/get");
+ connectVO.setReportTopic(
+ "/" + deviceMqttVO.getProductId() + "/" + deviceMqttVO.getSerialNumber() + "/property/post");
return connectVO;
}
@@ -1548,7 +1606,7 @@ public class DeviceServiceImpl implements IDeviceService {
*/
private void setLocation(String ip, Device device) {
String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
- //String address = "未知地址";
+ // String address = "未知地址";
// 内网不查询
if (IpUtils.internalIp(ip)) {
device.setNetworkAddress("内网IP");
@@ -1576,13 +1634,15 @@ public class DeviceServiceImpl implements IDeviceService {
String BAIDU_URL = "http://api.map.baidu.com/geocoding/v3/";
city = StrUtil.isEmpty(city) ? "湖南省长沙市岳麓区" : city;
String encodedAddress = URLEncoder.encode(city, StandardCharsets.UTF_8.toString());
- String baiduResponse = HttpUtils.sendGet(BAIDU_URL, "address=" + encodedAddress + "&output=json&ak=" + baiduAK, Constants.UTF8);
+ String baiduResponse = HttpUtils.sendGet(BAIDU_URL, "address=" + encodedAddress + "&output=json&ak=" + baiduAK,
+ Constants.UTF8);
if (!StringUtils.isEmpty(baiduResponse)) {
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
device.setLongitude(location.getBigDecimal("lng"));
device.setLatitude(location.getBigDecimal("lat"));
- System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:" + location.getBigDecimal("lat"));
+ System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:"
+ + location.getBigDecimal("lat"));
}
}
@@ -1597,7 +1657,6 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.getDeviceNumsByProductId(productId);
}
-
/**
* 重置设备状态
*
@@ -1616,7 +1675,8 @@ public class DeviceServiceImpl implements IDeviceService {
if (null == product) {
return "导入失败,产品信息为空";
}
- List serialNumberList = deviceImportVOList.stream().map(DeviceImportVO::getSerialNumber).collect(Collectors.toList());
+ List serialNumberList = deviceImportVOList.stream().map(DeviceImportVO::getSerialNumber)
+ .collect(Collectors.toList());
List oldSerialNumberList = deviceMapper.checkExistBySerialNumbers(serialNumberList);
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(oldSerialNumberList)) {
return "以下设备编号(" + JSON.toJSONString(oldSerialNumberList) + ")已存在,请修改后重试";
@@ -1645,12 +1705,16 @@ public class DeviceServiceImpl implements IDeviceService {
int result = deviceMapper.insertBatchDevice(deviceList);
// 新增导入记录
DeviceRecord deviceRecord = new DeviceRecord();
- deviceRecord.setOperateDeptId(loginUser.getDeptId()).setProductId(productId).setType(DeviceRecordTypeEnum.IMPORT.getType())
- .setTotal(deviceList.size()).setTenantId(loginUser.getUser().getDept().getDeptUserId()).setTenantName(loginUser.getUser().getDept().getDeptUserName());
+ deviceRecord.setOperateDeptId(loginUser.getDeptId()).setProductId(productId)
+ .setType(DeviceRecordTypeEnum.IMPORT.getType())
+ .setTotal(deviceList.size()).setTenantId(loginUser.getUser().getDept().getDeptUserId())
+ .setTenantName(loginUser.getUser().getDept().getDeptUserName());
if (result > 0) {
- deviceRecord.setStatus(StatusEnum.SUCCESS.getStatus()).setSuccessQuantity(deviceList.size()).setFailQuantity(0);
+ deviceRecord.setStatus(StatusEnum.SUCCESS.getStatus()).setSuccessQuantity(deviceList.size())
+ .setFailQuantity(0);
} else {
- deviceRecord.setStatus(StatusEnum.FAIL.getStatus()).setSuccessQuantity(0).setFailQuantity(deviceList.size());
+ deviceRecord.setStatus(StatusEnum.FAIL.getStatus()).setSuccessQuantity(0)
+ .setFailQuantity(deviceList.size());
}
deviceRecord.setCreateBy(loginUser.getUsername());
deviceRecordMapper.insertDeviceRecord(deviceRecord);
@@ -1664,7 +1728,8 @@ public class DeviceServiceImpl implements IDeviceService {
if (null == product) {
return "导入失败,产品信息为空";
}
- List serialNumberList = deviceAssignmentVOS.stream().map(DeviceAssignmentVO::getSerialNumber).collect(Collectors.toList());
+ List serialNumberList = deviceAssignmentVOS.stream().map(DeviceAssignmentVO::getSerialNumber)
+ .collect(Collectors.toList());
List oldSerialNumberList = deviceMapper.checkExistBySerialNumbers(serialNumberList);
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(oldSerialNumberList)) {
return "以下设备编号(" + JSON.toJSONString(oldSerialNumberList) + ")已存在,请修改后重试";
@@ -1701,8 +1766,11 @@ public class DeviceServiceImpl implements IDeviceService {
int result = deviceMapper.insertBatchDevice(deviceList);
// 新增导入记录
DeviceRecord deviceRecord = new DeviceRecord();
- deviceRecord.setOperateDeptId(loginUser.getDeptId()).setTargetDeptId(deptId).setTargetDeptId(deptId).setProductId(productId).setDistributeType(DeviceDistributeTypeEnum.IMPORT.getType())
- .setType(DeviceRecordTypeEnum.ASSIGNMENT.getType()).setTotal(deviceList.size()).setTenantId(loginUser.getUser().getDept().getDeptUserId()).setTenantName(loginUser.getUser().getDept().getDeptUserName());
+ deviceRecord.setOperateDeptId(loginUser.getDeptId()).setTargetDeptId(deptId).setTargetDeptId(deptId)
+ .setProductId(productId).setDistributeType(DeviceDistributeTypeEnum.IMPORT.getType())
+ .setType(DeviceRecordTypeEnum.ASSIGNMENT.getType()).setTotal(deviceList.size())
+ .setTenantId(loginUser.getUser().getDept().getDeptUserId())
+ .setTenantName(loginUser.getUser().getDept().getDeptUserName());
List deviceRecordList = new ArrayList<>();
if (result > 0) {
deviceRecord.setStatus(StatusEnum.SUCCESS.getStatus());
@@ -1717,10 +1785,15 @@ public class DeviceServiceImpl implements IDeviceService {
int insertRecordStatus = deviceRecordMapper.insertDeviceRecord(deviceRecord);
for (Device device : deviceList) {
DeviceRecord deviceRecord1 = new DeviceRecord();
- deviceRecord1.setOperateDeptId(loginUser.getDeptId()).setTargetDeptId(deptId).setProductId(productId).setDeviceId(device.getDeviceId())
- .setType(DeviceRecordTypeEnum.ASSIGNMENT_DETAIL.getType()).setParentId(deviceRecord.getId()).setSerialNumber(device.getSerialNumber())
- .setDistributeType(DeviceDistributeTypeEnum.IMPORT.getType()).setTenantId(loginUser.getUser().getDept().getDeptUserId()).setTenantName(loginUser.getUser().getDept().getDeptUserName());
- deviceRecord1.setStatus(insertRecordStatus > 0 ? StatusEnum.SUCCESS.getStatus() : StatusEnum.FAIL.getStatus());
+ deviceRecord1.setOperateDeptId(loginUser.getDeptId()).setTargetDeptId(deptId).setProductId(productId)
+ .setDeviceId(device.getDeviceId())
+ .setType(DeviceRecordTypeEnum.ASSIGNMENT_DETAIL.getType()).setParentId(deviceRecord.getId())
+ .setSerialNumber(device.getSerialNumber())
+ .setDistributeType(DeviceDistributeTypeEnum.IMPORT.getType())
+ .setTenantId(loginUser.getUser().getDept().getDeptUserId())
+ .setTenantName(loginUser.getUser().getDept().getDeptUserName());
+ deviceRecord1
+ .setStatus(insertRecordStatus > 0 ? StatusEnum.SUCCESS.getStatus() : StatusEnum.FAIL.getStatus());
deviceRecord1.setCreateBy(loginUser.getUsername());
deviceRecordList.add(deviceRecord1);
}
@@ -1750,11 +1823,14 @@ public class DeviceServiceImpl implements IDeviceService {
if (null == sysUser) {
return AjaxResult.error("机构管理员不存在");
}
- List deviceIdList = Arrays.stream(deviceIds.split(",")).map(d -> Long.parseLong(d.trim())).distinct().collect(Collectors.toList());
+ List deviceIdList = Arrays.stream(deviceIds.split(",")).map(d -> Long.parseLong(d.trim())).distinct()
+ .collect(Collectors.toList());
int result = deviceMapper.updateTenantIdByDeptIds(deptUserId, sysUser.getUserName(), deviceIdList);
DeviceRecord deviceRecord = new DeviceRecord();
- deviceRecord.setOperateDeptId(user.getDeptId()).setTargetDeptId(deptId).setTargetDeptId(deptId).setDistributeType(DeviceDistributeTypeEnum.SELECT.getType())
- .setType(DeviceRecordTypeEnum.ASSIGNMENT.getType()).setTotal(deviceIdList.size()).setTenantId(user.getDept().getDeptUserId()).setTenantName(user.getDept().getDeptUserName());
+ deviceRecord.setOperateDeptId(user.getDeptId()).setTargetDeptId(deptId).setTargetDeptId(deptId)
+ .setDistributeType(DeviceDistributeTypeEnum.SELECT.getType())
+ .setType(DeviceRecordTypeEnum.ASSIGNMENT.getType()).setTotal(deviceIdList.size())
+ .setTenantId(user.getDept().getDeptUserId()).setTenantName(user.getDept().getDeptUserName());
if (result > 0) {
deviceRecord.setStatus(StatusEnum.SUCCESS.getStatus());
deviceRecord.setSuccessQuantity(deviceIdList.size());
@@ -1773,8 +1849,10 @@ public class DeviceServiceImpl implements IDeviceService {
deviceRecord1.setOperateDeptId(user.getDeptId()).setTargetDeptId(deptId).setDeviceId(device.getDeviceId())
.setProductId(device.getProductId()).setSerialNumber(device.getSerialNumber())
.setType(DeviceRecordTypeEnum.ASSIGNMENT_DETAIL.getType()).setParentId(deviceRecord.getId())
- .setDistributeType(DeviceDistributeTypeEnum.SELECT.getType()).setTenantId(user.getDept().getDeptUserId()).setTenantName(user.getDept().getDeptUserName());
- deviceRecord1.setStatus(insertRecordStatus > 0 ? StatusEnum.SUCCESS.getStatus() : StatusEnum.FAIL.getStatus());
+ .setDistributeType(DeviceDistributeTypeEnum.SELECT.getType())
+ .setTenantId(user.getDept().getDeptUserId()).setTenantName(user.getDept().getDeptUserName());
+ deviceRecord1
+ .setStatus(insertRecordStatus > 0 ? StatusEnum.SUCCESS.getStatus() : StatusEnum.FAIL.getStatus());
deviceRecord1.setCreateBy(user.getUserName());
deviceRecordList.add(deviceRecord1);
}
@@ -1795,7 +1873,8 @@ public class DeviceServiceImpl implements IDeviceService {
if (null == sysUser) {
return AjaxResult.error("机构管理员不存在");
}
- List deviceIdList = Arrays.stream(deviceIds.split(",")).map(d -> Long.parseLong(d.trim())).distinct().collect(Collectors.toList());
+ List deviceIdList = Arrays.stream(deviceIds.split(",")).map(d -> Long.parseLong(d.trim())).distinct()
+ .collect(Collectors.toList());
int result = deviceMapper.updateTenantIdByDeptIds(deptUserId, sysUser.getUserName(), deviceIdList);
List deviceRecordList = new ArrayList<>();
List deviceList = deviceMapper.selectDeviceListByDeviceIds(deviceIdList);
@@ -1803,7 +1882,9 @@ public class DeviceServiceImpl implements IDeviceService {
DeviceRecord deviceRecord1 = new DeviceRecord();
deviceRecord1.setOperateDeptId(deptId).setTargetDeptId(recoveryDeptId).setDeviceId(device.getDeviceId())
.setProductId(device.getProductId()).setSerialNumber(device.getSerialNumber())
- .setType(DeviceRecordTypeEnum.RECOVERY.getType()).setTenantId(loginUser.getUser().getDept().getDeptUserId()).setTenantName(loginUser.getUser().getDept().getDeptUserName());
+ .setType(DeviceRecordTypeEnum.RECOVERY.getType())
+ .setTenantId(loginUser.getUser().getDept().getDeptUserId())
+ .setTenantName(loginUser.getUser().getDept().getDeptUserName());
deviceRecord1.setStatus(result > 0 ? StatusEnum.SUCCESS.getStatus() : StatusEnum.FAIL.getStatus());
deviceRecord1.setCreateBy(loginUser.getUsername());
deviceRecordList.add(deviceRecord1);
@@ -1833,16 +1914,16 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.selectDeviceByChannelId(channelId);
}
-
@Override
public List listThingsModel(Long deviceId) {
DeviceShortOutput device = deviceMapper.selectDeviceRunningStatusByDeviceId(deviceId);
if (null == device) {
return new ArrayList<>();
}
- //管理员可以下发,其他看指令控制
+ // 管理员可以下发,其他看指令控制
int canSend = getLoginUser().getUserId().equals(getLoginUser().getDeptUserId()) ? 1 : 0;
- List list = thingsModelService.getCacheAndHandleArrayByProductId(device.getProductId(), device.getSerialNumber());
+ List list = thingsModelService.getCacheAndHandleArrayByProductId(device.getProductId(),
+ device.getSerialNumber());
for (ThingsModelDTO thingsModelDTO : list) {
thingsModelDTO.setProductId(device.getProductId());
thingsModelDTO.setSerialNumber(device.getSerialNumber());
@@ -1853,7 +1934,8 @@ public class DeviceServiceImpl implements IDeviceService {
subGateway.setGwDeviceId(deviceId);
List subDeviceListVOList = subGatewayMapper.selectGatewayList(subGateway);
for (SubDeviceListVO subDeviceListVO : subDeviceListVOList) {
- List subList = thingsModelService.getCacheAndHandleArrayByProductId(subDeviceListVO.getSubProductId(), subDeviceListVO.getSubDeviceNo());
+ List subList = thingsModelService.getCacheAndHandleArrayByProductId(
+ subDeviceListVO.getSubProductId(), subDeviceListVO.getSubDeviceNo());
for (ThingsModelDTO thingsModelDTO : subList) {
thingsModelDTO.setProductId(subDeviceListVO.getSubProductId());
thingsModelDTO.setSerialNumber(subDeviceListVO.getSubDeviceNo());
@@ -1863,21 +1945,22 @@ public class DeviceServiceImpl implements IDeviceService {
}
list.addAll(subList);
}
- //指令控制
+ // 指令控制
jurisdictionThingsModel(list, deviceId);
return list;
}
private void jurisdictionThingsModel(List list, Long deviceId) {
Long userId = SecurityUtils.getUserId();
- //查询是否有指令控制
+ // 查询是否有指令控制
List orderControls = orderControlService.selectByUserId(userId, deviceId);
- if (CollectionUtils.isEmpty(orderControls)) return;
+ if (CollectionUtils.isEmpty(orderControls))
+ return;
List modelIdList = new ArrayList<>();
for (OrderControl control : orderControls) {
String selectOrder = control.getSelectOrder();
String[] split = selectOrder.split(",");
- //判断是否生效
+ // 判断是否生效
boolean just = just(control);
if (just) {
List ids = Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList());
@@ -1906,11 +1989,12 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public void updateByOrder(Long userId, Long deviceId) {
- //处理指令权限问题 ,非管理员角色
+ // 处理指令权限问题 ,非管理员角色
List controlList = orderControlService.selectByUserId(userId, deviceId);
- controlList = controlList.stream().filter(control -> Objects.equals(control.getStatus(), "1")).collect(Collectors.toList());
+ controlList = controlList.stream().filter(control -> Objects.equals(control.getStatus(), "1"))
+ .collect(Collectors.toList());
if (!CollectionUtils.isEmpty(controlList)) {
- //更新次数
+ // 更新次数
OrderControl control = controlList.get(0);
control.setCount(control.getCount() - 1);
orderControlService.updateOrderControl(control);
@@ -1928,7 +2012,6 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.listDeviceGroupByGroupIds(groupIds);
}
-
/**
* 查询产品下所有设备,返回设备编号
*
@@ -1940,7 +2023,4 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceMapper.selectSerialNumbersByProductId(productId);
}
-
-
}
-
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ModbusConfigServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ModbusConfigServiceImpl.java
index 11847954..d39cda66 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ModbusConfigServiceImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ModbusConfigServiceImpl.java
@@ -125,6 +125,7 @@ public class ModbusConfigServiceImpl implements IModbusConfigService {
this.updateModbusConfig(config);
}
}
+ // 将寄存器配置保存到redis缓存
modbusConfigCache.setModbusConfigCacheByProductId(productId);
}
diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ThingsModelServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ThingsModelServiceImpl.java
index a2fb98ab..c037fb95 100644
--- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ThingsModelServiceImpl.java
+++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ThingsModelServiceImpl.java
@@ -12,7 +12,6 @@ import com.fastbee.common.exception.ServiceException;
import com.fastbee.common.utils.DateUtils;
import com.fastbee.common.utils.SecurityUtils;
import com.fastbee.common.utils.StringUtils;
-import com.fastbee.iot.cache.ICalculatedThingsModelCache;
import com.fastbee.iot.cache.ITSLCache;
import com.fastbee.iot.domain.*;
import com.fastbee.iot.mapper.*;
@@ -68,8 +67,6 @@ public class ThingsModelServiceImpl implements IThingsModelService {
private ITSLValueCache thingModelCache;
@Resource
private ITSLCache itslCache;
- @Resource
- private ICalculatedThingsModelCache calculatedThingsModelCache;
private static List getSceneModelData(SceneModelDevice sceneModelDevice, List thingsModelDTOList) {
List modelDataList = new ArrayList<>();
@@ -142,11 +139,16 @@ public class ThingsModelServiceImpl implements IThingsModelService {
*/
@Override
public int insertThingsModel(ThingsModel thingsModel) {
+ // 去除计算公式中的空格
+ if (StringUtils.isNotEmpty(thingsModel.getFormula())) {
+ thingsModel.setFormula(thingsModel.getFormula().replaceAll("\\s+", ""));
+ }
ThingsModel input = new ThingsModel();
input.setProductId(thingsModel.getProductId());
+ input.setIsCalculated(0); // 只需要查产品的物模型即可
input.setLanguage(SecurityUtils.getLanguage());
List list = thingsModelMapper.selectThingsModelList(input);
- Boolean isRepeat = list.stream().anyMatch(x -> x.getIdentifier().equals(thingsModel.getIdentifier()));
+ boolean isRepeat = list.stream().anyMatch(x -> x.getIdentifier().equals(thingsModel.getIdentifier()));
if (!isRepeat) {
SysUser user = getLoginUser().getUser();
if (null != user.getDeptId()) {
@@ -157,21 +159,19 @@ public class ThingsModelServiceImpl implements IThingsModelService {
thingsModel.setTenantName(user.getUserName());
}
thingsModel.setCreateTime(DateUtils.getNowDate());
- // 自动判断是否为纯计算物模型:如果公式包含{},则设置为1(纯计算)
- if (thingsModel.getIsCalculated() == null) {
- thingsModel.setIsCalculated(determineIsCalculated(thingsModel.getFormula()));
- }
+ // 插入物模型数据库
int result = thingsModelMapper.insertThingsModel(thingsModel);
- // 更新redis缓存
- itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
- // 刷新纯计算物模型缓存
- if (result > 0) {
- calculatedThingsModelCache.refreshCalculatedCache(thingsModel.getProductId());
+ // 更新redis缓存:IsCalculated=1为纯计算物模型
+ if (thingsModel.getIsCalculated() != null && thingsModel.getIsCalculated() == 1) {
+ itslCache.refreshDeviceCalculatedModelCache(thingsModel.getSerialNumber());
+ } else {
+ itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
}
+
if (result > 0) {
// 更新场景管理变量
List sceneModelDeviceList = sceneModelDeviceMapper.listDeviceByProductId(thingsModel.getProductId());
- if (org.apache.commons.collections4.CollectionUtils.isEmpty(sceneModelDeviceList)) {
+ if (CollectionUtils.isEmpty(sceneModelDeviceList)) {
return result;
}
List thingsModelDTOList = this.changeObjectOrArray(thingsModel);
@@ -219,15 +219,15 @@ public class ThingsModelServiceImpl implements IThingsModelService {
thingsModel.setIsChart(template.getIsChart());
thingsModel.setIsHistory(template.getIsHistory());
thingsModel.setModelOrder(template.getModelOrder());
- thingsModel.setIsCalculated(determineIsCalculated(thingsModel.getFormula()));
- Boolean isRepeat = dbList.stream().anyMatch(x -> x.getIdentifier().equals(thingsModel.getIdentifier()));
+ thingsModel.setIsCalculated(0);
+ boolean isRepeat = dbList.stream().anyMatch(x -> x.getIdentifier().equals(thingsModel.getIdentifier()));
if (isRepeat) {
repeatCount = repeatCount + 1;
} else {
list.add(thingsModel);
}
}
- if (list.size() > 0) {
+ if (!list.isEmpty()) {
int result = thingsModelMapper.insertBatchThingsModel(list);
if (result > 0) {
// 更新场景管理变量
@@ -245,8 +245,6 @@ public class ThingsModelServiceImpl implements IThingsModelService {
}
//更新redis缓存
itslCache.setCacheThingsModelByProductId(input.getProductId());
- // 刷新纯计算物模型缓存
- calculatedThingsModelCache.refreshCalculatedCache(input.getProductId());
}
return repeatCount;
}
@@ -271,16 +269,12 @@ public class ThingsModelServiceImpl implements IThingsModelService {
Boolean isRepeat = list.stream().anyMatch(x -> x.getIdentifier().equals(thingsModel.getIdentifier()) && x.getModelId().longValue() != thingsModel.getModelId());
if (!isRepeat) {
thingsModel.setUpdateTime(DateUtils.getNowDate());
- // 自动判断是否为纯计算物模型:如果公式包含{},则设置为1(纯计算)
- if (thingsModel.getIsCalculated() == null) {
- thingsModel.setIsCalculated(determineIsCalculated(thingsModel.getFormula()));
- }
int result = thingsModelMapper.updateThingsModel(thingsModel);
// 更新redis缓存
- itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
- // 刷新纯计算物模型缓存
- if (result > 0) {
- calculatedThingsModelCache.refreshCalculatedCache(thingsModel.getProductId());
+ if (thingsModel.getIsCalculated() != null && thingsModel.getIsCalculated() == 1) {
+ itslCache.refreshDeviceCalculatedModelCache(thingsModel.getSerialNumber());
+ } else {
+ itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
}
if (result > 0) {
List sceneModelDataList = sceneModelDataMapper.selectSceneDeviceThingsModelList(thingsModel.getModelId());
@@ -320,12 +314,9 @@ public class ThingsModelServiceImpl implements IThingsModelService {
if (result > 0) {
sceneModelDataMapper.deleteThingsModelByDatasourceId(modelIds);
}
- // 更新redis缓存
+ // 更新redis缓存 产品和设备物模型都干掉
itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
- // 刷新纯计算物模型缓存
- if (result > 0 && thingsModel != null && thingsModel.getProductId() != null) {
- calculatedThingsModelCache.refreshCalculatedCache(thingsModel.getProductId());
- }
+ itslCache.refreshDeviceCalculatedModelCache(thingsModel.getSerialNumber());
return result;
}
@@ -341,12 +332,11 @@ public class ThingsModelServiceImpl implements IThingsModelService {
ThingsModel thingsModel = thingsModelMapper.selectThingsModelByModelId(modelId, SecurityUtils.getLanguage());
int result = thingsModelMapper.deleteThingsModelByModelId(modelId);
// 更新redis缓存
- if (thingsModel != null && thingsModel.getProductId() != null) {
- itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
- // 刷新纯计算物模型缓存
- if (result > 0) {
- calculatedThingsModelCache.refreshCalculatedCache(thingsModel.getProductId());
+ if (thingsModel != null) {
+ if (thingsModel.getProductId() != null) {
+ itslCache.setCacheThingsModelByProductId(thingsModel.getProductId());
}
+ itslCache.refreshDeviceCalculatedModelCache(thingsModel.getSerialNumber());
}
return result;
}
@@ -354,8 +344,8 @@ public class ThingsModelServiceImpl implements IThingsModelService {
/**
* 获取单个物模型获取
*
- * @param productId
- * @param identify
+ * @param productId 产品ID
+ * @param identify 物模型标识符
* @return
*/
@Override
@@ -695,6 +685,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
if (null == productId) {
return new ArrayList<>();
}
+ // 1、获取产品物模型
Map map = itslCache.getCacheThMapByProductId(productId);
List thingsModelDTOList = new ArrayList<>();
for (Map.Entry entry : map.entrySet()) {
@@ -702,6 +693,15 @@ public class ThingsModelServiceImpl implements IThingsModelService {
thingsModelDTOList.addAll(this.changeObjectOrArray(thingsModel));
}
+ // 2. 获取设备级计算物模型并合并
+ if (StringUtils.isNotEmpty(serialNumber)) {
+ Map deviceCalculatedMap = itslCache.getDeviceCalculatedModelMap(serialNumber);
+ for (Map.Entry entry : deviceCalculatedMap.entrySet()) {
+ ThingsModel thingsModel = this.propertyDtoChangeThingsModel(entry.getValue());
+ thingsModelDTOList.addAll(this.changeObjectOrArray(thingsModel));
+ }
+ }
+
thingsModelDTOList.sort(Comparator.comparing(ThingsModelDTO::getModelOrder));
if (StringUtils.isEmpty(serialNumber)) {
return thingsModelDTOList;
diff --git a/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml b/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml
index be3cfb54..53bb3997 100644
--- a/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml
+++ b/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml
@@ -163,15 +163,71 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- select device_id, device_name, product_id, product_name, tenant_id, tenant_name, serial_number,gw_dev_code, firmware_version, status, rssi,is_shadow ,is_simulate,location_way,things_model_value,network_address, network_ip, longitude, latitude, active_time, create_time, update_time, img_url,summary,remark,slave_id from iot_device
+ select device_id,
+ device_name,
+ product_id,
+ product_name,
+ tenant_id,
+ tenant_name,
+ serial_number,
+ gw_dev_code,
+ firmware_version,
+ status,
+ rssi,
+ is_shadow,
+ is_simulate,
+ location_way,
+ things_model_value,
+ network_address,
+ network_ip,
+ longitude,
+ latitude,
+ active_time,
+ create_time,
+ update_time,
+ img_url,
+ summary,
+ remark,
+ slave_id
+ from iot_device
- select device_id, device_name, product_id, product_name, tenant_id, tenant_name, serial_number, firmware_version, status,rssi,is_shadow ,is_simulate,location_way,things_model_value, active_time,img_url,slave_id from iot_device
+ select device_id,
+ device_name,
+ product_id,
+ product_name,
+ tenant_id,
+ tenant_name,
+ serial_number,
+ firmware_version,
+ status,
+ rssi,
+ is_shadow,
+ is_simulate,
+ location_way,
+ things_model_value,
+ active_time,
+ img_url,
+ slave_id
+ from iot_device
- select device_id, device_name,product_id, serial_number,tenant_id, tenant_name, status,is_shadow,is_simulate, rssi ,location_way,things_model_value, active_time from iot_device
+ select device_id,
+ device_name,
+ product_id,
+ serial_number,
+ tenant_id,
+ tenant_name,
+ status,
+ is_shadow,
+ is_simulate,
+ rssi,
+ location_way,
+ things_model_value,
+ active_time
+ from iot_device