20251223:物模型支持计算(以另一个物模型上报数据计算得出)
This commit is contained in:
parent
898687ea09
commit
7e612e03eb
@ -701,6 +701,24 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
eventLogService.saveBatch(eventLogList);
|
||||
}
|
||||
/* ★★★★★★★★★★★★★★★★★★★★★★ 存储数据 - 结束 ★★★★★★★★★★★★★★★★★★★★★★*/
|
||||
|
||||
/* ★★★★★★★★★★★★★★★★★★★★★★ 自动计算依赖物模型 - 开始 ★★★★★★★★★★★★★★★★★★★★★★*/
|
||||
// 记录所有已更新的物模型标识符(设备上报的)
|
||||
Set<String> updatedIdentifiers = new HashSet<>();
|
||||
for (ThingsModelSimpleItem item : input.getThingsModelValueRemarkItem()) {
|
||||
String identity = item.getId();
|
||||
if (identity.startsWith("array_")) {
|
||||
identity = identity.substring(9);
|
||||
}
|
||||
updatedIdentifiers.add(identity);
|
||||
}
|
||||
|
||||
// 自动计算依赖已更新物模型的其他物模型(纯计算型物模型)
|
||||
if (!updatedIdentifiers.isEmpty() && !isShadow) {
|
||||
calculateDependentThingsModels(input, updatedIdentifiers, key, maps, deviceLogList, type, isPowerOnTriggerReply);
|
||||
}
|
||||
/* ★★★★★★★★★★★★★★★★★★★★★★ 自动计算依赖物模型 - 结束 ★★★★★★★★★★★★★★★★★★★★★★*/
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -2102,4 +2120,158 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动计算依赖已更新物模型的其他物模型(纯计算型物模型)
|
||||
* 当设备只上报频率时,自动计算依赖频率的压力等物模型
|
||||
*
|
||||
* @param input 设备上报数据输入
|
||||
* @param updatedIdentifiers 已更新的物模型标识符集合(设备上报的)
|
||||
* @param key Redis缓存key
|
||||
* @param maps 物模型值映射(用于批量更新缓存)
|
||||
* @param deviceLogList 设备日志列表(用于存储历史数据)
|
||||
* @param type 物模型类型(1=属性,2=功能,3=事件)
|
||||
* @param isPowerOnTriggerReply 是否是设备上电触发回包
|
||||
*/
|
||||
private void calculateDependentThingsModels(ThingsModelValuesInput input,
|
||||
Set<String> updatedIdentifiers,
|
||||
String key,
|
||||
Map<String, String> maps,
|
||||
List<DeviceLog> deviceLogList,
|
||||
int type,
|
||||
boolean isPowerOnTriggerReply) {
|
||||
try {
|
||||
// 查询产品下所有物模型
|
||||
com.fastbee.iot.domain.ThingsModel queryModel = new com.fastbee.iot.domain.ThingsModel();
|
||||
queryModel.setProductId(input.getProductId());
|
||||
List<com.fastbee.iot.domain.ThingsModel> allThingsModels = thingsModelService.selectThingsModelList(queryModel);
|
||||
|
||||
if (CollectionUtils.isEmpty(allThingsModels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取设备信息(用于存储历史数据)
|
||||
Device device = this.selectDeviceBySerialNumber(input.getDeviceNumber());
|
||||
if (device == null) {
|
||||
log.warn("=>自动计算依赖物模型时,设备不存在[{}]", input.getDeviceNumber());
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历所有物模型,找出依赖已更新物模型的计算型物模型
|
||||
for (com.fastbee.iot.domain.ThingsModel thingsModel : allThingsModels) {
|
||||
String dependentIdentifier = thingsModel.getIdentifier();
|
||||
|
||||
// 跳过已更新的物模型(设备已上报的)
|
||||
if (updatedIdentifiers.contains(dependentIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 只处理有计算公式的物模型
|
||||
String formula = thingsModel.getFormula();
|
||||
if (StringUtils.isEmpty(formula)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查计算公式是否引用了已更新的物模型
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\{([^}]+)\\}");
|
||||
java.util.regex.Matcher matcher = pattern.matcher(formula);
|
||||
Set<String> referencedIdentifiers = new HashSet<>();
|
||||
while (matcher.find()) {
|
||||
String identifier = matcher.group(1);
|
||||
referencedIdentifiers.add(identifier);
|
||||
}
|
||||
|
||||
// 检查是否至少引用了一个已更新的物模型
|
||||
boolean hasDependency = false;
|
||||
for (String refIdentifier : referencedIdentifiers) {
|
||||
if (updatedIdentifiers.contains(refIdentifier)) {
|
||||
hasDependency = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有依赖已更新的物模型,跳过
|
||||
if (!hasDependency) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查所有引用的物模型是否都有值(从缓存中获取)
|
||||
Map<String, String> params = new HashMap<>();
|
||||
|
||||
for (String refIdentifier : referencedIdentifiers) {
|
||||
try {
|
||||
ValueItem refValueItem = itslValueCache.getCacheIdentifier(
|
||||
input.getProductId(),
|
||||
input.getDeviceNumber(),
|
||||
refIdentifier
|
||||
);
|
||||
if (refValueItem != null && StringUtils.isNotEmpty(refValueItem.getValue())) {
|
||||
params.put("{" + refIdentifier + "}", refValueItem.getValue());
|
||||
} else {
|
||||
// 如果引用的物模型值不存在,使用0作为默认值
|
||||
params.put("{" + refIdentifier + "}", "0");
|
||||
log.warn("=>自动计算依赖物模型时,引用的物模型值不存在[{}],标识符:[{}],使用默认值0",
|
||||
input.getProductId(), refIdentifier);
|
||||
// 如果依赖的物模型没有值,仍然尝试计算(使用默认值0)
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("=>自动计算依赖物模型时,获取引用的物模型值失败[{}],标识符:[{}],错误:{}",
|
||||
input.getProductId(), refIdentifier, e.getMessage());
|
||||
params.put("{" + refIdentifier + "}", "0");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果公式中有 %s,使用0作为默认值(因为这是纯计算型物模型,没有设备上报的原始值)
|
||||
if (formula.contains("%s")) {
|
||||
params.put("%s", "0");
|
||||
}
|
||||
|
||||
// 执行计算
|
||||
String calculatedValue;
|
||||
try {
|
||||
calculatedValue = String.valueOf(CaculateUtils.execute(formula, params));
|
||||
} catch (Exception e) {
|
||||
log.error("=>自动计算依赖物模型时,计算公式执行失败[{}],标识符:[{}],公式:[{}],错误:{}",
|
||||
input.getProductId(), dependentIdentifier, formula, e.getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 更新缓存
|
||||
ValueItem valueItem = new ValueItem();
|
||||
valueItem.setId(dependentIdentifier);
|
||||
valueItem.setValue(calculatedValue);
|
||||
valueItem.setShadow(calculatedValue);
|
||||
valueItem.setTs(DateUtils.getNowDate());
|
||||
maps.put(dependentIdentifier, JSONObject.toJSONString(valueItem));
|
||||
|
||||
// 获取物模型详细信息(用于存储历史数据)
|
||||
ThingsModelValueItem thingModelValue = thingsModelService.getSingleThingModels(
|
||||
input.getProductId(), dependentIdentifier);
|
||||
if (thingModelValue != null && thingModelValue.getType() == 1 && thingModelValue.getIsHistory() == 1) {
|
||||
// 存储历史数据(仅属性类型且启用了历史存储)
|
||||
DeviceLog deviceLog = new DeviceLog();
|
||||
deviceLog.setSerialNumber(input.getDeviceNumber());
|
||||
deviceLog.setLogType(type);
|
||||
deviceLog.setMode(2); // 在线模式
|
||||
deviceLog.setLogValue(calculatedValue);
|
||||
deviceLog.setRemark("自动计算"); // 标记为自动计算
|
||||
deviceLog.setIdentity(dependentIdentifier);
|
||||
deviceLog.setCreateTime(DateUtils.getNowDate());
|
||||
deviceLog.setUserId(device.getTenantId());
|
||||
deviceLog.setUserName(device.getTenantName());
|
||||
deviceLog.setTenantId(device.getTenantId());
|
||||
deviceLog.setTenantName(device.getTenantName());
|
||||
deviceLog.setModelName(thingModelValue.getName());
|
||||
deviceLog.setIsMonitor(thingModelValue.getIsMonitor());
|
||||
deviceLogList.add(deviceLog);
|
||||
}
|
||||
|
||||
log.debug("=>自动计算依赖物模型成功[{}],标识符:[{}],计算公式:[{}],计算结果:[{}]",
|
||||
input.getProductId(), dependentIdentifier, formula, calculatedValue);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("=>自动计算依赖物模型时发生异常[{}],设备编号:[{}],错误:{}",
|
||||
input.getProductId(), input.getDeviceNumber(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user