20251223:物模型支持计算(以另一个物模型上报数据计算得出)
This commit is contained in:
parent
898687ea09
commit
7e612e03eb
@ -701,6 +701,24 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
eventLogService.saveBatch(eventLogList);
|
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;
|
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