From ddd6d2e9e936457706582a300ed786020028bb3c Mon Sep 17 00:00:00 2001
From: ChenYi <296215406@outlook.com>
Date: Wed, 18 Mar 2026 17:26:06 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E6=94=B6=E4=B8=9A=E5=8A=A1=E7=B3=BB?=
=?UTF-8?q?=E7=BB=9F=E8=B0=83=E7=94=A8=E8=AE=BE=E5=A4=87=E6=9C=8D=E5=8A=A1?=
=?UTF-8?q?=E4=BF=A1=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Dto/CallDeviceServiceRequestInfoDto.cs | 15 ++
.../IBusinessSystemAggregationService.cs | 9 +-
.../BusinessSystemAggregationService.cs | 156 ++++++++++++++++--
3 files changed, 169 insertions(+), 11 deletions(-)
create mode 100644 src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/Dto/CallDeviceServiceRequestInfoDto.cs
diff --git a/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/Dto/CallDeviceServiceRequestInfoDto.cs b/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/Dto/CallDeviceServiceRequestInfoDto.cs
new file mode 100644
index 0000000..ad3cf46
--- /dev/null
+++ b/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/Dto/CallDeviceServiceRequestInfoDto.cs
@@ -0,0 +1,15 @@
+using JiShe.ServicePro.Dto;
+
+namespace JiShe.IoT.BusinessSystemAggregation
+{
+ ///
+ /// 业务系统调用设备服务请求参数
+ ///
+ public class CallDeviceServiceRequestInfoDto: ReceiveCommandInfoDto
+ {
+ ///
+ /// 服务名称
+ ///
+ public string ServiceName { get; set; }
+ }
+}
diff --git a/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/IBusinessSystemAggregationService.cs b/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/IBusinessSystemAggregationService.cs
index 4b9cc54..8518177 100644
--- a/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/IBusinessSystemAggregationService.cs
+++ b/src/JiShe.IoT.Application.Contracts/BusinessSystemAggregation/IBusinessSystemAggregationService.cs
@@ -1,5 +1,6 @@
using JiShe.ServicePro;
using JiShe.ServicePro.ApacheIoTDB.Provider.Model;
+using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -46,6 +47,12 @@ namespace JiShe.IoT.BusinessSystemAggregation
///
///
///
- Task BatchCreateDeviceInfoAsync(OpenApiRequest input);
+ Task BatchCreateDeviceInfoAsync(OpenApiRequest input);
+
+
+ ///
+ /// 接收业务系统调用设备服务信息,Msg 字段为 CallDeviceServiceRequestInfoDto 实体
+ ///
+ Task>> CallDeviceServiceToOneNETForApiAsync(OpenApiRequest input);
}
}
diff --git a/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs b/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs
index fd5d392..adf618d 100644
--- a/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs
+++ b/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs
@@ -96,7 +96,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
}
List actionTypes = new List() {
- DeviceTelemetryCommandTypeEnum.OperateBreaker,
+ DeviceTelemetryCommandTypeEnum.OperateService,
DeviceTelemetryCommandTypeEnum.RoutineOperationSet,
};
@@ -118,7 +118,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
{
return HttpDataResultExtensions.Failed("设备不存在", -1041, ResponeResultEnum.Fail);
}
-
+
//将指令存储IoTDB数据库和Redis发布通道
if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET)
{
@@ -136,7 +136,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
var tempPlatformThingModelInfo = platformThingModelInfo.Where(d => d.IoTPlatformRawFieldName == item.Key).FirstOrDefault();
if (tempPlatformThingModelInfo == null)
{
- _logger.LogError($"业务系统推送指令时设备设备{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。");
+ _logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。");
messageBody.Commands.RemoveAll(d => d.Key == item.Key);
continue;
}
@@ -213,14 +213,14 @@ namespace JiShe.IoT.BusinessSystemAggregation
return HttpDataResultExtensions.Failed>("获取数据失败,设备属性值不能为空", -102, ResponeResultEnum.Fail);
}
- var restrictionKey = string.Format(RedisConst.CacheDeviceOpenApiRestrictionKey,nameof(ReceiveGetCommandInfoAsync), messageBody.DeviceAddress);
- var openApiDeviceRequest = FreeRedisProvider.Instance.Get(restrictionKey);
+ var restrictionKey = string.Format(RedisConst.CacheDeviceOpenApiRestrictionKey, nameof(ReceiveGetCommandInfoAsync), messageBody.DeviceAddress);
+ var openApiDeviceRequest = FreeRedisProvider.Instance.Get(restrictionKey);
if (openApiDeviceRequest != null)
{
return HttpDataResultExtensions.Failed>("获取数据失败,设备请求被限制", -103, ResponeResultEnum.Fail);
}
- FreeRedisProvider.Instance.Set(restrictionKey,"1",TimeSpan.FromSeconds(5));
+ FreeRedisProvider.Instance.Set(restrictionKey, "1", TimeSpan.FromSeconds(5));
//限定来源类型必须为业务系统
if (messageBody.SourceType != DeviceTelemetrySourceTypeEnum.BusinessSystem)
@@ -240,7 +240,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
{
return HttpDataResultExtensions.Failed>("设备不存在", -106, ResponeResultEnum.Fail);
}
-
+
//将指令存储IoTDB数据库和Redis发布通道
if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET)
{
@@ -263,7 +263,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
messageBody.Commands.RemoveAll(d => d.Key == item.Key);
continue;
}
-
+
if (deviceInfo.IsNeedConfigDeviceModel && deviceInfo.DeviceThingModelDataId.HasValue && item.Key.ToLowerInvariant() == ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant())
{
_logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是特殊指令操作,被禁止。");
@@ -278,7 +278,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
messageBody.Commands.RemoveAll(d => d.Key == item.Key);
continue;
}
- commands.Add(tempPlatformThingModelInfo.IoTPlatformRawFieldName,item.Key);
+ commands.Add(tempPlatformThingModelInfo.IoTPlatformRawFieldName, item.Key);
}
if (commands == null || commands.Count <= 0)
@@ -292,7 +292,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
//数据写入遥测任务数据存储通道
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
-
+
var queryResult = await DevicePropertyValueToOneNET(deviceInfo, new DevicePropertyValueForApiInput() { PropertyList = commands.Select(d => d.Key).ToList() });
if (queryResult == null || queryResult.Count <= 0)
@@ -616,5 +616,141 @@ namespace JiShe.IoT.BusinessSystemAggregation
!deviceAddress.Contains("*") &&
!deviceAddress.Contains("~");
}
+
+ ///
+ /// 接收业务系统调用设备服务信息,Msg 字段为 CallDeviceServiceRequestInfoDto 实体
+ ///
+ [AllowAnonymous]
+ public async Task>> CallDeviceServiceToOneNETForApiAsync(OpenApiRequest input)
+ {
+ try
+ {
+ var handleResult = HandleOpenApiRequest(input, serverApplicationOptions);
+ if (handleResult.Success == false)
+ {
+ return HttpDataResultExtensions.Failed>("获取数据失败,签名校验异常", -101);
+ }
+ var messageBody = handleResult.Data;
+ if (messageBody == null || messageBody.Commands == null || messageBody.Commands.Count <= 0 || string.IsNullOrWhiteSpace(messageBody.DeviceAddress) || string.IsNullOrWhiteSpace(messageBody.ServiceName))
+ {
+ return HttpDataResultExtensions.Failed>("服务调用失败,服务调用参数不能为空", -102, ResponeResultEnum.Fail);
+ }
+
+ var restrictionKey = string.Format(RedisConst.CacheDeviceOpenApiRestrictionKey, nameof(ReceiveGetCommandInfoAsync), messageBody.DeviceAddress);
+ var openApiDeviceRequest = FreeRedisProvider.Instance.Get(restrictionKey);
+ if (openApiDeviceRequest != null)
+ {
+ return HttpDataResultExtensions.Failed>("服务调用失败,设备请求被限制", -103, ResponeResultEnum.Fail);
+ }
+
+ FreeRedisProvider.Instance.Set(restrictionKey, "1", TimeSpan.FromSeconds(5));
+
+ //限定来源类型必须为业务系统
+ if (messageBody.SourceType != DeviceTelemetrySourceTypeEnum.BusinessSystem)
+ {
+ return HttpDataResultExtensions.Failed>("服务调用失败,来源类型错误,业务系统传固定值2", -104, ResponeResultEnum.Fail);
+ }
+
+ //限定操作类型必须为设备服务调用类型
+ if (messageBody.TelemetryCommandType != DeviceTelemetryCommandTypeEnum.OperateService)
+ {
+ return HttpDataResultExtensions.Failed>("服务调用失败,指令操作类型错误", -105, ResponeResultEnum.Fail);
+ }
+
+ var deviceInfo = await deviceAppService.FindByDeviceAddressAsync(messageBody.DeviceAddress);
+
+ if (deviceInfo == null)
+ {
+ return HttpDataResultExtensions.Failed>("设备不存在", -106, ResponeResultEnum.Fail);
+ }
+
+ //将指令存储IoTDB数据库和Redis发布通道
+ if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET)
+ {
+ //获取设备对应的平台端物模型信息,校验前端传入的属性标识集合是否存在不合法的属性标识符
+
+ var platformThingModelInfo = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput() { Id = deviceInfo.IoTPlatformProductId });
+
+ if (platformThingModelInfo == null)
+ {
+ return HttpDataResultExtensions.Failed>($"业务系统设备服务调时,{deviceInfo.DeviceAddress}的平台端物模型信息不存在。", -107, ResponeResultEnum.Fail);
+ }
+
+ Dictionary commands = new Dictionary();
+ foreach (var item in messageBody.Commands)
+ {
+ var tempPlatformThingModelInfo = platformThingModelInfo.Where(d => d.StandardFieldName == item.Key).FirstOrDefault();
+ if (tempPlatformThingModelInfo == null)
+ {
+ _logger.LogError($"业务系统设备服务调时{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。");
+ messageBody.Commands.RemoveAll(d => d.Key == item.Key);
+ continue;
+ }
+
+
+ //排除指令
+ if (exitCommands.Contains(tempPlatformThingModelInfo.StandardFieldName.ToLowerInvariant()))
+ {
+ _logger.LogError($"业务系统设备服务调时{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是升级指令操作,被禁止。");
+ messageBody.Commands.RemoveAll(d => d.Key == item.Key);
+ continue;
+ }
+ commands.Add(tempPlatformThingModelInfo.IoTPlatformRawFieldName, item.Key);
+ }
+
+ if (commands == null || commands.Count <= 0)
+ {
+ _logger.LogError($"业务系统设备服务调时{deviceInfo.DeviceAddress}未匹配到具体数据模型,被禁止。");
+ return HttpDataResultExtensions.Failed>("业务系统设备服务调失败,未匹配到具体数据模型", -108);
+ }
+
+
+ var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, input, deviceInfo.Adapt(), commands.Serialize());
+
+ //数据写入遥测任务数据存储通道
+ await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
+
+ var queryResult = await CallDeviceServiceToOneNET(deviceInfo, new CallDeviceServiceForApiInput()
+ {
+ ServiceParams = messageBody.Commands,
+ ServiceName = messageBody.ServiceName,
+ });
+
+ if (queryResult == null || queryResult.Count <= 0)
+ {
+ return HttpDataResultExtensions.Failed>("业务系统设备服务调失败,OneNET平台未返回数据", -109);
+ }
+
+ Dictionary result = new Dictionary();
+ foreach (var item in commands)
+ {
+ result.Add(item.Value, queryResult[item.Key]);
+ }
+
+ return HttpDataResultExtensions.Success>(result);
+
+ }
+ else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing)
+ {
+ //await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName, input);
+ }
+ else
+ {
+ return HttpDataResultExtensions.Failed>("指令处理失败,当前设备平台类型异常", -110);
+ }
+
+ return HttpDataResultExtensions.Success>("指令下发成功");
+ }
+ catch (UserFriendlyException ex)
+ {
+ _logger.LogError(ex, "接收业务系统指令信息时发生异常");
+ return HttpDataResultExtensions.Failed>("设备属性数据获取失败,发送异常", -111);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "接收业务系统指令信息时发生异常");
+ return HttpDataResultExtensions.Failed>("设备属性数据获取失败,发送异常", -112);
+ }
+ }
}
}
\ No newline at end of file