diff --git a/src/JiShe.IoT.Application.Contracts/DeviceAggregation/Dto/DeviceCommandForApiInput.cs b/src/JiShe.IoT.Application.Contracts/DeviceAggregation/Dto/DeviceCommandForApiInput.cs index a7f6e22..2a6bd8b 100644 --- a/src/JiShe.IoT.Application.Contracts/DeviceAggregation/Dto/DeviceCommandForApiInput.cs +++ b/src/JiShe.IoT.Application.Contracts/DeviceAggregation/Dto/DeviceCommandForApiInput.cs @@ -11,19 +11,9 @@ namespace JiShe.IoT.DeviceAggregation public class DeviceCommandForApiInput:IdInput { /// - /// 设备在物联网平台中发送的命令内容,JSON格式 + /// 设备在物联网平台中属性设置的参数键值对 /// [Required(ErrorMessage = "命令内容不能为空")] - public string CommandContent { get; set; } - - /// - /// 设备类型 - /// - public DeviceTypeEnum? DeviceType { get; set; } - - /// - /// 设备指令类型 - /// - public DeviceTelemetryCommandTypeEnum? TelemetryType { get; set; } + public Dictionary CommandContent { get; set; } } } \ No newline at end of file diff --git a/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs b/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs index 83a814b..a2ffda4 100644 --- a/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs +++ b/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs @@ -6,6 +6,7 @@ using JiShe.ServicePro.DataChannelManages; using JiShe.ServicePro.DeviceManagement.DeviceInfos; using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto; using JiShe.ServicePro.DeviceManagement.Permissions; +using JiShe.ServicePro.DeviceManagement.ThingModels; using JiShe.ServicePro.Dto; using JiShe.ServicePro.Enums; using JiShe.ServicePro.FreeRedisProvider; @@ -29,7 +30,9 @@ namespace JiShe.IoT.DeviceAggregation /// Redis发布订阅服务 /// 数据通道 /// IoTDBOptions - public class DeviceAggregationService(ILogger logger, IDeviceAppService deviceAppService, IOneNETDeviceService oneNETDeviceService, IReliableRedisPubSubService redisPubSubService, IIoTDBDataChannelManageService ioTDBDataChannelManageService,IOptions _ioTDBOptions) : IoTAppService, IDeviceAggregationService + /// OneNET产品服务 + /// 设备端物模型服务 + public class DeviceAggregationService(ILogger logger, IDeviceAppService deviceAppService, IOneNETDeviceService oneNETDeviceService, IReliableRedisPubSubService redisPubSubService, IIoTDBDataChannelManageService ioTDBDataChannelManageService,IOptions _ioTDBOptions, IOneNETProductService oneNETProductService, IDeviceThingModelManagementAppService deviceThingModelService) : IoTAppService, IDeviceAggregationService { IoTDBOptions ioTDBOptions = _ioTDBOptions.Value; @@ -288,47 +291,35 @@ namespace JiShe.IoT.DeviceAggregation { try { + if (input.CommandContent == null || input.CommandContent.Keys.Count <=0) + { + throw new UserFriendlyException($"指令参数异常"); + } + var deviceInfo = await deviceAppService.FindByIdAsync(input); if (deviceInfo == null) { throw new UserFriendlyException($"设备不存在"); } - //将指令存储 - var commandRequest = new OpenApiRequest() - { - Message = new ReceiveCommandInfoDto() - { - DeviceAddress = deviceInfo.DeviceAddress, - Commands = input.CommandContent.Deserialize>(), - DeviceType = input.DeviceType ?? DeviceTypeEnum.GATEWAY,//todo 设备类型 需要跟设备统一什么情况下知道具体设备类型 - SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem, - TelemetryType = input.TelemetryType ?? DeviceTelemetryCommandTypeEnum.抄读, - IoTPlatform = deviceInfo.IoTPlatform, - }.Serialize(), - }; - - var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt(), commandRequest.Message); - + //数据写入遥测任务数据存储通道 if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET) - { - await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo)); - - return await DeviceCommandInfoToOneNET(deviceInfo, packetTaskInfo); + { + return await DeviceCommandInfoToOneNET(deviceInfo, input); } else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing) { - await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName,commandRequest); - return true; + //await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName,commandRequest); + //return true; + throw new UserFriendlyException($"发送设备指令信息失败,CTWing暂未实现。"); } else { - throw new UserFriendlyException($"创建设备失败,未找到对应的产品配置信息。"); + throw new UserFriendlyException($"发送设备指令信息失败,未找到对应的产品配置信息。"); } } catch (Exception) { - throw; } } @@ -387,15 +378,17 @@ namespace JiShe.IoT.DeviceAggregation try { CreateDeviceInput createDeviceInput = input.Adapt(); - - var productInfo = await FreeSqlDbContext.Instance.Select() - .Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)//此处不需要过滤产品状态,方便测试产品配置信息是否准确,避免跟车间生产搞混 - .WhereIf(input.DeviceSourceTypeEnum == DeviceSourceTypeEnum.Workshop, e => e.IsEnabled == true) - .FirstAsync(); + + var productInfo = await oneNETProductService.GetProductInfoAsync(new IdInput() { Id = input.IoTPlatformProductId }); if (productInfo == null) { - throw new UserFriendlyException($"创建设备失败,未找到对应的产品配置信息。"); + throw new UserFriendlyException($"OneNET创建设备失败,未找到对应的产品配置信息。"); + } + + if (input.DeviceSourceTypeEnum == DeviceSourceTypeEnum.Workshop && !productInfo.IsEnabled) //车间生产推送,必须是已经启用的产品才可以 + { + throw new UserFriendlyException($"车间生产推送OneNET创建设备失败,产品未启用。"); } createDeviceInput.DeviceName = input.DeviceAddress; @@ -532,35 +525,26 @@ namespace JiShe.IoT.DeviceAggregation public async Task RepushDeviceInfoToOneNET(DeviceManagementInfoDto input) { try - { - var productInfo = await FreeSqlDbContext.Instance.Select() - .Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId) - .FirstAsync(); - - if (productInfo == null) - { - throw new UserFriendlyException($"推送失败,未找到对应的产品配置信息。"); - } - + { //检查OneNET平台设备是否已经存在 var oneNETDeviceInfoResult = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, - ProductId = productInfo.IoTPlatformProductId, - OneNETAccountId = productInfo.OneNETAccountId, + ProductId = input.IoTPlatformProductId, + OneNETAccountId = input.IoTPlatformAccountId, }); if (oneNETDeviceInfoResult != null && oneNETDeviceInfoResult.Code == ServicePro.Enums.ResponeResultEnum.Success) { - throw new UserFriendlyException($"推送失败,OneNET账号{productInfo.AccountPhoneNumber}的产品下{productInfo.ProductName}已经存在该设备{input.DeviceAddress}。"); + throw new UserFriendlyException($"OneNET推送失败,账号产品下{input.IoTPlatformProductId}已经存在该设备{input.DeviceAddress}。"); } //推送至OneNET平台 var pushResult = await oneNETDeviceService.CreateDeviceInfoAsync(new CreateDeviceInfoInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, - ProductId = productInfo.IoTPlatformProductId, - OneNETAccountId = productInfo.OneNETAccountId, + ProductId = input.IoTPlatformProductId, + OneNETAccountId = input.IoTPlatformAccountId, Description = input.DeviceAddress, }); @@ -589,23 +573,13 @@ namespace JiShe.IoT.DeviceAggregation public async Task DeleteDeviceInfoToOneNET(DeviceManagementInfoDto input) { try - { - var productInfo = await FreeSqlDbContext.Instance.Select() - .Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId) - .FirstAsync(); - - if (productInfo == null) - { - throw new UserFriendlyException($"删除失败,未找到对应的产品配置信息。"); - } - - + { //删除OneNET平台设备信息 var deleteResult = await oneNETDeviceService.DeleteDeviceInfoAsync(new DeleteDeviceInfoInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, - ProductId = productInfo.IoTPlatformProductId, - OneNETAccountId = productInfo.OneNETAccountId, + ProductId = input.IoTPlatformProductId, + OneNETAccountId = input.IoTPlatformAccountId, }); if (deleteResult == null || deleteResult.Code != ServicePro.Enums.ResponeResultEnum.Success) @@ -634,13 +608,49 @@ namespace JiShe.IoT.DeviceAggregation /// 发送OneNET平台设备指令 /// /// - /// + /// /// /// - public async Task DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, DeviceTelemetryPacketTaskInfo packetTaskInfo) + public async Task DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, DeviceCommandForApiInput input) { try { + //将指令存储 + var receiveCommandInfoDto = new ReceiveCommandInfoDto() + { + DeviceAddress = deviceInfo.DeviceAddress, + Commands = input.CommandContent, + DeviceType = deviceInfo.DeviceType, + SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem, + IoTPlatform = deviceInfo.IoTPlatform, + }; + + //检查设备是否有配置设备端物模型信息 + //如果有配置,就检查指令字典中是否有SpecialCommand标识符 + //如果有就需要构建 SpecialCommand 的特别指令 + + if (deviceInfo.IsNeedConfigDevicMdoel && deviceInfo.DeviceThingModelDataId.HasValue && receiveCommandInfoDto.Commands.ContainsKey(ThingModelFixedTypeConst.SpecialCommand)) + { + var propertyInfo = await oneNETProductService.GetProductThingModelSpecialCommandDataTypeListAsync(new IdInput() { Id = deviceInfo.IoTPlatformProductId }); + + if (propertyInfo == null) + { + throw new UserFriendlyException($"{nameof(DeviceCommandInfoToOneNET)} OneNET设备属性设置失败,产品Id{deviceInfo.IoTPlatformProductId}未找到对应的属性信息。"); + } + + Dictionary tempSpecialCommand = await deviceThingModelService.BuildThingModelSpecialCommandAsync(propertyInfo, deviceInfo.DeviceThingModelDataId.Value); + + receiveCommandInfoDto.Commands[ThingModelFixedTypeConst.SpecialCommand] = tempSpecialCommand; + } + + var commandRequest = new OpenApiRequest() + { + Message = receiveCommandInfoDto.Serialize(), + }; + var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt(), commandRequest.Message); + + await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo)); + //检查下设备是否在线 var deviceOnlineStatus = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput() { diff --git a/src/JiShe.IoT.Application/IoTAppService.cs b/src/JiShe.IoT.Application/IoTAppService.cs index 8c73968..ab444a7 100644 --- a/src/JiShe.IoT.Application/IoTAppService.cs +++ b/src/JiShe.IoT.Application/IoTAppService.cs @@ -53,7 +53,6 @@ namespace JiShe.IoT DeviceAddress = commandIssueInfo.DeviceAddress, IssueRawMessage = input.Serialize(), IoTDataType = IoTDBDataTypeConst.Command, - TelemetryType = (int)commandIssueInfo.TelemetryType, TelemetrySource = (int)commandIssueInfo.SourceType, IoTPlatform = (int)commandIssueInfo.IoTPlatform, IoTPlatformProductId = deviceInfo.IoTPlatformProductId,