diff --git a/JiShe.ServicePro b/JiShe.ServicePro index ddfe5fb..cbf9b87 160000 --- a/JiShe.ServicePro +++ b/JiShe.ServicePro @@ -1 +1 @@ -Subproject commit ddfe5fb0eabb58f3b0d2014d911947d5d6dd71fb +Subproject commit cbf9b87d348e3af5dcbe55fc70e03dad91dc69d2 diff --git a/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs b/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs index 06aaf2d..dfd21b4 100644 --- a/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs +++ b/src/JiShe.IoT.Application/BusinessSystemAggregation/BusinessSystemAggregationService.cs @@ -17,6 +17,7 @@ using JiShe.ServicePro.OneNETManagement.OneNETProducts; using Mapster; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Linq; using Volo.Abp; using Volo.Abp.Auditing; using static Volo.Abp.Ui.LayoutHooks.LayoutHooks; @@ -91,12 +92,23 @@ namespace JiShe.IoT.BusinessSystemAggregation return HttpDataResultExtensions.Failed("设备指令不能为空", -103, ResponeResultEnum.Fail); } + List actionTypes = new List() { + DeviceTelemetryCommandTypeEnum.OperateBreaker, + DeviceTelemetryCommandTypeEnum.RoutineOperationSet, + }; + //限定来源类型必须为业务系统 if (messageBody.SourceType != DeviceTelemetrySourceTypeEnum.BusinessSystem) { return HttpDataResultExtensions.Failed("设备指令来源类型错误,业务系统传固定值2", -104, ResponeResultEnum.Fail); } + //限定操作类型必须为设置类型 + if (!actionTypes.Contains(messageBody.TelemetryCommandType)) + { + return HttpDataResultExtensions.Failed("设备指令操作类型错误", -105, ResponeResultEnum.Fail); + } + var deviceInfo = await deviceAppService.FindByDeviceAddressAsync(messageBody.DeviceAddress); if (deviceInfo == null) @@ -123,18 +135,24 @@ namespace JiShe.IoT.BusinessSystemAggregation var tempPlatformThingModelInfo = platformThingModelInfo.Where(d => d.IoTPlatformRawFieldName == item.Key).FirstOrDefault(); if (tempPlatformThingModelInfo == null) { - throw new UserFriendlyException($"业务系统推送指令时设备设备{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。"); - } - - //排除升级指令 - if (tempPlatformThingModelInfo.StandardFieldName.ToLowerInvariant() == ThingModelFixedTypeConst.FIRMWARE_UPGRADE.ToLowerInvariant()) - { - throw new UserFriendlyException($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是升级指令操作,被禁止。"); + _logger.LogError($"业务系统推送指令时设备设备{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。"); + messageBody.Commands.RemoveAll(d => d.Key == item.Key); + continue; } if (deviceInfo.IsNeedConfigDeviceModel && deviceInfo.DeviceThingModelDataId.HasValue && item.Key.ToLowerInvariant() == ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant()) { - throw new UserFriendlyException($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是特殊指令操作,被禁止。"); + _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; } } @@ -191,11 +209,17 @@ namespace JiShe.IoT.BusinessSystemAggregation return HttpDataResultExtensions.Failed>("获取数据失败,来源类型错误,业务系统传固定值2", -104, ResponeResultEnum.Fail); } + //限定操作类型必须为设置类型 + if (messageBody.TelemetryCommandType != DeviceTelemetryCommandTypeEnum.GetAttributeData) + { + return HttpDataResultExtensions.Failed>("设备指令操作类型错误", -105, ResponeResultEnum.Fail); + } + var deviceInfo = await deviceAppService.FindByDeviceAddressAsync(messageBody.DeviceAddress); if (deviceInfo == null) { - return HttpDataResultExtensions.Failed>("设备不存在", -105, ResponeResultEnum.Fail); + return HttpDataResultExtensions.Failed>("设备不存在", -106, ResponeResultEnum.Fail); } var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, input, deviceInfo.Adapt(), messageBody.Commands.Serialize()); @@ -209,9 +233,9 @@ namespace JiShe.IoT.BusinessSystemAggregation if (platformThingModelInfo == null) { - return HttpDataResultExtensions.Failed>($"业务系统推送指令时设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。", -106, ResponeResultEnum.Fail); + return HttpDataResultExtensions.Failed>($"业务系统推送指令时设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。", -107, ResponeResultEnum.Fail); } - + foreach (var item in messageBody.Commands) { var tempPlatformThingModelInfo = platformThingModelInfo.Where(d => d.IoTPlatformRawFieldName == item.Key).FirstOrDefault(); @@ -221,18 +245,18 @@ namespace JiShe.IoT.BusinessSystemAggregation messageBody.Commands.RemoveAll(d => d.Key == item.Key); continue; } - - //排除升级指令 - if (tempPlatformThingModelInfo.StandardFieldName.ToLowerInvariant() == ThingModelFixedTypeConst.FIRMWARE_UPGRADE.ToLowerInvariant()) + + if (deviceInfo.IsNeedConfigDeviceModel && deviceInfo.DeviceThingModelDataId.HasValue && item.Key.ToLowerInvariant() == ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant()) { - _logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是升级指令操作,被禁止。"); + _logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是特殊指令操作,被禁止。"); messageBody.Commands.RemoveAll(d => d.Key == item.Key); continue; } - if (deviceInfo.IsNeedConfigDeviceModel && deviceInfo.DeviceThingModelDataId.HasValue && item.Key.ToLowerInvariant() == ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant()) + //排除指令 + if (exitCommands.Contains(tempPlatformThingModelInfo.StandardFieldName.ToLowerInvariant())) { - _logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是特殊指令操作,被禁止。"); + _logger.LogError($"业务系统推送指令时设备{deviceInfo.DeviceAddress}平台端物模型属性标识符{item.Key}是升级指令操作,被禁止。"); messageBody.Commands.RemoveAll(d => d.Key == item.Key); continue; } @@ -244,18 +268,18 @@ namespace JiShe.IoT.BusinessSystemAggregation if (messageBody.Commands == null || messageBody.Commands.Count <= 0) { - return HttpDataResultExtensions.Failed>("获取数据失败,OneNET平台未返回数据", -106); + return HttpDataResultExtensions.Failed>("获取数据失败,OneNET平台未返回数据", -108); } var queryResult = await DevicePropertyValueToOneNET(deviceInfo, new DevicePropertyValueForApiInput() { PropertyList = messageBody.Commands.Select(d => d.Key).ToList() }); if (queryResult == null || queryResult.Count <= 0) { - return HttpDataResultExtensions.Failed>("获取数据失败,OneNET平台未返回数据", -106); + return HttpDataResultExtensions.Failed>("获取数据失败,OneNET平台未返回数据", -109); } return HttpDataResultExtensions.Success>(queryResult); - + } else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing) { @@ -263,7 +287,7 @@ namespace JiShe.IoT.BusinessSystemAggregation } else { - return HttpDataResultExtensions.Failed>("指令处理失败,当前设备平台类型异常", -105); + return HttpDataResultExtensions.Failed>("指令处理失败,当前设备平台类型异常", -110); } return HttpDataResultExtensions.Success>("指令下发成功"); @@ -275,7 +299,7 @@ namespace JiShe.IoT.BusinessSystemAggregation catch (Exception ex) { _logger.LogError(ex, "接收业务系统指令信息时发生异常"); - return HttpDataResultExtensions.Failed>("指令处理失败,发送异常", -106); + return HttpDataResultExtensions.Failed>("指令处理失败,发送异常", -111); } } diff --git a/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs b/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs index 71489b1..83d7cab 100644 --- a/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs +++ b/src/JiShe.IoT.Application/DeviceAggregation/DeviceAggregationService.cs @@ -312,6 +312,7 @@ namespace JiShe.IoT.DeviceAggregation DeviceType = deviceInfo.DeviceType, SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem, IoTPlatform = deviceInfo.IoTPlatform, + TelemetryCommandType = DeviceTelemetryCommandTypeEnum.RoutineOperationSet, }; //数据写入遥测任务数据存储通道 @@ -558,7 +559,8 @@ namespace JiShe.IoT.DeviceAggregation Message = input.Serialize(), }; var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt(), input.PropertyList.Serialize()); - + packetTaskInfo.TelemetryType = (int)DeviceTelemetryCommandTypeEnum.GetAttributeData; + if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET) { @@ -620,6 +622,7 @@ namespace JiShe.IoT.DeviceAggregation {ThingModelFixedTypeConst.SpecialCommand, ""} }, + TelemetryCommandType = DeviceTelemetryCommandTypeEnum.ThingModelSwitch, }, platformThingModelInfos); } } diff --git a/src/JiShe.IoT.Application/IoTAppService.cs b/src/JiShe.IoT.Application/IoTAppService.cs index 0d777e9..4343a6f 100644 --- a/src/JiShe.IoT.Application/IoTAppService.cs +++ b/src/JiShe.IoT.Application/IoTAppService.cs @@ -62,6 +62,7 @@ namespace JiShe.IoT RetryCount = 0, IssueStatus = (int)DeviceCommandIssueStatusEnum.Unprocessed, LastIssueTime = DateTime.Now, + TelemetryType = (int)commandIssueInfo.TelemetryCommandType, }; return oneNETIssueMessageEntity; diff --git a/src/JiShe.IoT.Application/IoTDeviceBasicAppService.cs b/src/JiShe.IoT.Application/IoTDeviceBasicAppService.cs index b4b3aad..7d9fb14 100644 --- a/src/JiShe.IoT.Application/IoTDeviceBasicAppService.cs +++ b/src/JiShe.IoT.Application/IoTDeviceBasicAppService.cs @@ -22,6 +22,7 @@ using JiShe.ServicePro.OneNETManagement.OneNETProducts; using Mapster; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Collections.Generic; using Volo.Abp; namespace JiShe.IoT @@ -44,6 +45,14 @@ namespace JiShe.IoT protected readonly IDeviceUpgradeRecordService deviceUpgradeRecordService; protected readonly ITreeModelService treeModelService; + //需要过滤的命令 + protected readonly List exitCommands = new List() + { + ThingModelFixedTypeConst.FIRMWARE_UPGRADE.ToLowerInvariant(), + ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant(), + ThingModelFixedTypeConst.DEVICE_TO_MASTER_SWITCH.ToLowerInvariant(), + }; + /// /// 设备服务 /// OneNET设备服务 @@ -467,7 +476,7 @@ namespace JiShe.IoT /// /// /// 设置属性请求内容相关 - /// 固件数据Id + /// 固件数据 /// 固件文件信息 /// 入参 /// 产品信息(如果已获取则传入以避免重复调用) @@ -574,6 +583,7 @@ namespace JiShe.IoT { { upgradeProperty.IoTPlatformRawFieldName, upgradeMessageHexString } }; + taskInput.TelemetryCommandType = DeviceTelemetryCommandTypeEnum.FirmwareUpgrade; var commandRequest = new OpenApiRequest() { @@ -725,6 +735,75 @@ namespace JiShe.IoT } } } + + /// + /// 发送设备切换主站指令 + /// + /// + /// 设置属性请求内容相关 + /// 入参 + /// 产品信息(如果已获取则传入以避免重复调用) + /// 平台端物模型信息(如果已获取则传入以避免重复调用) + /// + /// + protected async Task DeviceMasterSwitchCommand(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto taskInput, DeviceUpgradeForApiInput input, dynamic productInfo = null, dynamic platformThingModelInfo = null) + { + try + { + if (deviceInfo == null) + { + throw new UserFriendlyException($"{nameof(DeviceUpgradeCommandToOneNET)}设备或固件信息不能为空"); + } + + + //如果未传入产品信息和物模型信息,则获取 + if (productInfo == null || platformThingModelInfo == null) + { + var (productInfoResult, platformThingModelInfoResult) = await GetOneNETProductAndThingModelInfoAsync(deviceInfo.IoTPlatformProductId, deviceInfo.DeviceAddress); + productInfo = productInfoResult; + platformThingModelInfo = platformThingModelInfoResult; + } + + var upgradeProperty = ((List)platformThingModelInfo).Where(d => d.StandardFieldName == ThingModelFixedTypeConst.DEVICE_TO_MASTER_SWITCH).FirstOrDefault(); + if (upgradeProperty == null) + { + throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}平台端物模型信息不存在转主站属性标识符{ThingModelFixedTypeConst.DEVICE_TO_MASTER_SWITCH}。"); + } + + //构建转主站指令 + + + + var upgradeMessageHexString = "md5HashRaw".Md5Fun().ToHexString(); + + //发送OneNET平台设备升级指令,HEX格式字符串 + taskInput.Commands = new Dictionary() + { + { upgradeProperty.IoTPlatformRawFieldName, upgradeMessageHexString } + }; + + var commandRequest = new OpenApiRequest() + { + Message = taskInput.Serialize(), + }; + var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt(), taskInput.Commands.Serialize()); + + await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETUpgradeCommandIssuedEventName, packetTaskInfo)); + + + + + await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo); + + + return true; + } + catch (Exception) + { + + throw; + } + } #endregion #region CTWing 设备操作