using JiShe.IoT.DeviceAggregation; using JiShe.IoT.DeviceAggregation.Dto; using JiShe.ServicePro; using JiShe.ServicePro.ApacheIoTDB.Provider.Options; using JiShe.ServicePro.Core; using JiShe.ServicePro.DataChannelManages; using JiShe.ServicePro.DeviceManagement.DeviceInfos; using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto; using JiShe.ServicePro.DeviceManagement.ThingModels; using JiShe.ServicePro.Dto; using JiShe.ServicePro.Encrypt; using JiShe.ServicePro.Enums; using JiShe.ServicePro.FileManagement.Files; using JiShe.ServicePro.FreeRedisProvider; using JiShe.ServicePro.FreeSqlProvider; using JiShe.ServicePro.IoTDBManagement.DataChannels; using JiShe.ServicePro.IoTDBManagement.TableModels; using JiShe.ServicePro.IoTDBManagement.TreeModels; using JiShe.ServicePro.OneNET.Provider.OpenApiModels.Commands; using JiShe.ServicePro.OneNETManagement.OneNETDevices; using JiShe.ServicePro.OneNETManagement.OneNETProducts; using Mapster; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp; namespace JiShe.IoT { /// /// 设备基础服务 /// public abstract class IoTDeviceBasicAppService : IoTAppService { protected readonly ILogger logger; protected readonly IDeviceAppService deviceAppService; protected readonly IOneNETDeviceService oneNETDeviceService; protected readonly IReliableRedisPubSubService redisPubSubService; protected readonly IIoTDBDataChannelManageService ioTDBDataChannelManageService; protected readonly IoTDBOptions ioTDBOptions; protected readonly ServerApplicationOptions serverApplicationOptions; protected readonly IOneNETProductService oneNETProductService; protected readonly IDeviceThingModelManagementAppService deviceThingModelService; protected readonly IIoTPlatformThingModelInfoAppService platformThingModelInfoAppService; protected readonly IDeviceUpgradeRecordService deviceUpgradeRecordService; protected readonly ITreeModelService treeModelService; /// /// 设备服务 /// OneNET设备服务 /// Redis发布订阅服务 /// 数据通道 /// IoTDBOptions /// OneNET产品服务 /// 设备端物模型服务 /// 平台端端物模型服务 /// 设备升级记录服务 /// 应用服务配置 /// IoTDB树模型服务 protected IoTDeviceBasicAppService( ILogger logger, IDeviceAppService deviceAppService, IOneNETDeviceService oneNETDeviceService, IReliableRedisPubSubService redisPubSubService, IIoTDBDataChannelManageService ioTDBDataChannelManageService, IOptions _ioTDBOptions, IOptions _serverOptions, IOneNETProductService oneNETProductService, IDeviceThingModelManagementAppService deviceThingModelService, IIoTPlatformThingModelInfoAppService platformThingModelInfoAppService, IDeviceUpgradeRecordService deviceUpgradeRecordService, ITreeModelService treeModelService) { this.logger = logger; this.deviceAppService = deviceAppService; this.oneNETDeviceService = oneNETDeviceService; this.redisPubSubService = redisPubSubService; this.ioTDBDataChannelManageService = ioTDBDataChannelManageService; this.ioTDBOptions = _ioTDBOptions.Value; this.serverApplicationOptions = _serverOptions.Value; this.oneNETProductService = oneNETProductService; this.deviceThingModelService = deviceThingModelService; this.platformThingModelInfoAppService = platformThingModelInfoAppService; this.deviceUpgradeRecordService = deviceUpgradeRecordService; this.treeModelService = treeModelService; } #region OneNET 设备操作 /// /// OneNET设备创建 /// /// /// protected async Task OneNETDeviceCreateAsync(CreateDeviceAggregationInput input) { try { CreateDeviceInput createDeviceInput = input.Adapt(); var productInfo = await oneNETProductService.GetProductInfoAsync(new IdInput() { Id = input.IoTPlatformProductId }); if (productInfo == null) { throw new UserFriendlyException($"OneNET创建设备失败,未找到对应的产品配置信息。"); } if (input.DeviceSourceType == DeviceSourceTypeEnum.Workshop && !productInfo.IsEnabled) //车间生产推送,必须是已经启用的产品才可以 { throw new UserFriendlyException($"车间生产推送OneNET创建设备失败,产品未启用。"); } createDeviceInput.DeviceName = input.DeviceAddress; createDeviceInput.IoTPlatformAccountId = productInfo.OneNETAccountId; createDeviceInput.IoTPlatformDeviceOpenInfo = $"{input.IoTPlatformProductId}{input.DeviceAddress}"; createDeviceInput.PlatformPassword = productInfo.ProductAccesskey; createDeviceInput.IoTPlatformProductName = productInfo.ProductName; createDeviceInput.AccountPhoneNumber = productInfo.AccountPhoneNumber; if (input.DeviceType.HasValue) { createDeviceInput.DeviceType = input.DeviceType.Value; } var insertResult = await deviceAppService.CreateAsync(createDeviceInput); if (insertResult == null) { logger.LogError($"{nameof(OneNETDeviceCreateAsync)} 添加设备信息失败:{input.Serialize()}"); return false; } //推送至OneNET平台 var pushResult = await oneNETDeviceService.CreateDeviceInfoAsync(new CreateDeviceInfoInput() { DeviceName = createDeviceInput.IoTPlatformDeviceOpenInfo, ProductId = productInfo.IoTPlatformProductId, OneNETAccountId = productInfo.OneNETAccountId, Description = input.DeviceAddress, }); if (pushResult == null || pushResult.Code != ServicePro.Enums.ResponeResultEnum.Success || pushResult.Data == null) { logger.LogError($"{nameof(OneNETDeviceCreateAsync)} 推送设备信息失败:{pushResult.Serialize()}"); return false; } //更新OneNET平台推送结果 await DeviceUpdateHandler(insertResult, pushResult, pushResult.Data.SecurityKey); return true; } catch (Exception) { throw; } } /// /// OneNET设备批量创建 /// /// /// protected async Task OneNETDeviceBatchCreateAsync(BatchCreateDeviceAggregationInput input) { try { var productInfo = await FreeSqlDbContext.Instance.Select() .Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)//此处不需要过滤产品状态,方便测试产品配置信息是否准确,避免跟车间生产搞混 .WhereIf(input.DeviceSourceType == DeviceSourceTypeEnum.Workshop, e => e.IsEnabled == true) .FirstAsync(); if (productInfo == null) { throw new UserFriendlyException($"批量创建设备失败,未找到对应的产品配置信息。"); } BatchCreateDeviceInput batchCreateDeviceInput = new BatchCreateDeviceInput() { IoTPlatform = input.IoTPlatform, AddressList = input.AddressList, DeviceInputs = new List() }; //检查网关或者直连设备信息是否已经存在 var checkDevicesInfos = await deviceAppService.FindByDeviceAddressAsync(new FindByDeviceAddressInput() { AddressList = input.AddressList, IoTPlatform = input.IoTPlatform, IoTPlatformProductId = input.IoTPlatformProductId, }); foreach (var item in input.DeviceInfos) { if (checkDevicesInfos != null) { var checkDevices = checkDevicesInfos.Where(e => e.DeviceAddress == item.DeviceAddress).FirstOrDefault(); if (checkDevices != null && checkDevices.IsPlatformPushSuccess) { logger.LogError($"{nameof(OneNETDeviceBatchCreateAsync)} 平台{input.IoTPlatform} 产品 {input.IoTPlatformProductId} 下设备信息已存在:{item.DeviceAddress}"); continue; } } CreateDeviceInput createDeviceInput = input.Adapt(); createDeviceInput.DeviceName = item.DeviceAddress; createDeviceInput.DeviceAddress = item.DeviceAddress; createDeviceInput.IoTPlatformAccountId = productInfo.OneNETAccountId; createDeviceInput.IoTPlatformDeviceOpenInfo = $"{input.IoTPlatformProductId}{item.DeviceAddress}"; createDeviceInput.PlatformPassword = productInfo.ProductAccesskey; createDeviceInput.IoTPlatformProductName = productInfo.ProductName; createDeviceInput.AccountPhoneNumber = productInfo.AccountPhoneNumber; if (input.DeviceSourceType.HasValue) { createDeviceInput.DeviceSourceType = input.DeviceSourceType.Value; } if (input.DeviceType.HasValue) { createDeviceInput.DeviceType = input.DeviceType.Value; } if (item.BusinessSystemDeviceDataId.HasValue) { createDeviceInput.BusinessSystemDeviceDataId = item.BusinessSystemDeviceDataId.Value; } batchCreateDeviceInput.DeviceInputs.Add(createDeviceInput); } if (batchCreateDeviceInput.DeviceInputs != null || batchCreateDeviceInput.DeviceInputs.Count > 0) { var insertResult = await deviceAppService.BatchCreateAsync(batchCreateDeviceInput); if (insertResult == null) { logger.LogError($"{nameof(OneNETDeviceBatchCreateAsync)} OneNET设备批量创建添加设备信息失败:{input.Serialize()}"); return false; } //网关或者直连设备 推送至OneNET平台 var oneNETBatchCreateDeviceInfoInput = new BatchCreateDeviceInfoInput() { ProductId = productInfo.IoTPlatformProductId, OneNETAccountId = productInfo.OneNETAccountId, DeviceList = new List() }; oneNETBatchCreateDeviceInfoInput.DeviceList = batchCreateDeviceInput.DeviceInputs.Select(d => d.IoTPlatformDeviceOpenInfo).ToList(); var pushResult = await oneNETDeviceService.BatchCreateDeviceInfoAsync(oneNETBatchCreateDeviceInfoInput); if (pushResult == null || pushResult.Code != ServicePro.Enums.ResponeResultEnum.Success) { logger.LogError($"{nameof(OneNETDeviceBatchCreateAsync)} 推送设备信息失败:{pushResult.Serialize()}"); return false; } //更新OneNET平台推送结果 foreach (var item in insertResult) { var successEntity = pushResult.Data.Successlist.Where(d => d.DeviceName == item.IoTPlatformDeviceOpenInfo).FirstOrDefault(); if (successEntity != null) { await DeviceUpdateHandler(item, HttpDataResultExtensions.Success(successEntity), successEntity.SecurityKey); } } } //暂不考虑子设备地址信息,由网关设备主动上报 return true; } catch (Exception) { throw; } } /// /// 重新推送设备信息到OneNET物联网平台 /// /// /// /// public async Task RepushDeviceInfoToOneNET(DeviceManagementInfoDto input) { try { //检查OneNET平台设备是否已经存在 var oneNETDeviceInfoResult = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, ProductId = input.IoTPlatformProductId, OneNETAccountId = input.IoTPlatformAccountId, }); if (oneNETDeviceInfoResult != null && oneNETDeviceInfoResult.Code == ServicePro.Enums.ResponeResultEnum.Success) { throw new UserFriendlyException($"OneNET推送失败,账号产品下{input.IoTPlatformProductId}已经存在该设备{input.DeviceAddress}。"); } //推送至OneNET平台 var pushResult = await oneNETDeviceService.CreateDeviceInfoAsync(new CreateDeviceInfoInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, ProductId = input.IoTPlatformProductId, OneNETAccountId = input.IoTPlatformAccountId, Description = input.DeviceAddress, }); if (pushResult == null || pushResult.Code != ServicePro.Enums.ResponeResultEnum.Success || pushResult.Data == null) { logger.LogError($"{nameof(RepushDeviceInfoToOneNET)} 推送设备信息失败:{pushResult.Serialize()}"); throw new UserFriendlyException($"平台请求失败。"); } return await DeviceUpdateHandler(input, pushResult, pushResult.Data.SecurityKey); } catch (Exception) { throw; } } /// /// 删除OneNET平台设备 /// /// /// /// public async Task DeleteDeviceInfoToOneNET(DeviceManagementInfoDto input) { try { //删除OneNET平台设备信息 var deleteResult = await oneNETDeviceService.DeleteDeviceInfoAsync(new DeleteDeviceInfoInput() { DeviceName = input.IoTPlatformDeviceOpenInfo, ProductId = input.IoTPlatformProductId, OneNETAccountId = input.IoTPlatformAccountId, }); if (deleteResult == null || deleteResult.Code != ServicePro.Enums.ResponeResultEnum.Success) { logger.LogError($"{nameof(DeleteDeviceInfoToOneNET)} 删除设备信息失败:{deleteResult.Serialize()}"); throw new UserFriendlyException($"删除设备平台请求失败。"); } var localDeleteReult = await deviceAppService.DeleteAsync(new IdInput() { Id = input.Id }); if (localDeleteReult == false) { throw new UserFriendlyException($"平台设备信息删除成功,系统删除设备失败。"); } return localDeleteReult; } catch (Exception) { throw; } } /// /// 发送OneNET平台设备指令 /// /// 设备信息 /// 指令信息 /// 平台端物模型信息 /// /// protected async Task DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto input, List platformThingModelInfos = null) { try { //获取设备对应的平台端物模型信息,校验前端传入的属性标识集合是否存在不合法的属性标识符 if (platformThingModelInfos == null || platformThingModelInfos.Count <= 0) { platformThingModelInfos = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput() { Id = deviceInfo.IoTPlatformProductId }); } if (platformThingModelInfos == null || platformThingModelInfos.Count <= 0) { throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。"); } foreach (var item in input.Commands) { var tempPlatformThingModelInfo = platformThingModelInfos.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}是升级指令,此处不允许下发。"); } } //检查设备是否有配置设备端物模型信息 //如果有配置,就检查指令字典中是否有SpecialCommand标识符 //如果有就需要构建 SpecialCommand 的特别指令 if (deviceInfo.IsNeedConfigDeviceModel && deviceInfo.DeviceThingModelDataId.HasValue && input.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); input.Commands[ThingModelFixedTypeConst.SpecialCommand] = tempSpecialCommand; } else if (input.Commands.ContainsKey(ThingModelFixedTypeConst.SpecialCommand)) { //设备端物模型解除绑定情况下,SpecialCommand 还原默认值,设备也会恢复默认采集方式 //给SpecialCommand第一个参数设置默认值 var propertyInfo = await oneNETProductService.GetProductThingModelSpecialCommandDataTypeListAsync(new IdInput() { Id = deviceInfo.IoTPlatformProductId }); if (propertyInfo == null) { throw new UserFriendlyException($"{nameof(DeviceCommandInfoToOneNET)} OneNET设备属性设置失败,产品Id{deviceInfo.IoTPlatformProductId}未找到对应的属性信息。"); } string paName = propertyInfo.FirstOrDefault()?.Identifier; input.Commands[ThingModelFixedTypeConst.SpecialCommand] = new Dictionary() { { paName, CommonConst.SpecialCommandDefaultValue } }; logger.LogWarning($"{nameof(DeviceCommandInfoToOneNET)} OneNET平台设备{deviceInfo.DeviceAddress}特殊抄读指令还原为{CommonConst.SpecialCommandDefaultValue}"); } var commandRequest = new OpenApiRequest() { Message = input.Serialize(), }; var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt(), input.Commands.Serialize()); await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo)); await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo); return true; } catch (Exception ex) { logger.LogError($"{nameof(DeviceCommandInfoToOneNET)} 发送OneNET设备指令信息发生异常,设备地址:{deviceInfo.DeviceAddress},异常信息:{ex.Message}"); throw; } } /// /// 发送OneNET平台设备升级指令 /// /// /// 设置属性请求内容相关 /// 固件数据Id /// 固件文件信息 /// 入参 /// 产品信息(如果已获取则传入以避免重复调用) /// 平台端物模型信息(如果已获取则传入以避免重复调用) /// /// protected async Task DeviceUpgradeCommandToOneNET(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto taskInput, DeviceFirmwareInfoDto deviceFirmwareInfo, FileObjectDto fileObject, DeviceUpgradeForApiInput input, dynamic productInfo = null, dynamic platformThingModelInfo = null) { try { if (deviceInfo == null || deviceFirmwareInfo == null || fileObject == null) { throw new UserFriendlyException($"{nameof(DeviceUpgradeCommandToOneNET)}设备或固件信息不能为空"); } if ((deviceInfo.IoTPlatformProductId != deviceFirmwareInfo.IoTPlatformProductId) || (deviceInfo.IoTPlatform != deviceFirmwareInfo.IoTPlatform)) { throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}平台产品信息固件中不一致"); } //如果未传入产品信息和物模型信息,则获取 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.FIRMWARE_UPGRADE).FirstOrDefault(); if (upgradeProperty == null) { throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}平台端物模型信息不存在升级属性标识符{ThingModelFixedTypeConst.FIRMWARE_UPGRADE}。"); } //构建升级指令,《文件MD5值+OneNET产品KEY+升级标识符+文件大小》=>MD5计算获得签名值 var upgradeRecordInput = new CreateDeviceUpgradeRecordInput() { DeviceDataId = deviceInfo.Id, DeviceName = deviceInfo.DeviceName, DeviceAddress = deviceInfo.DeviceAddress, OldFirmwareVersion = deviceInfo.FirmwareVersion, NowFirmwareVersion = deviceFirmwareInfo.FirmwareVersion, UpgradeSource = DeviceUpgradeSourceTypeEnum.AdminSystem, UpgradeIdentifier = Yitter.IdGenerator.YitIdHelper.NextId(), UpgradeDescription = input.UpgradeDescription, UpgradeStatus = DeviceUpgradeStatusTypeEnum.NotUpgrade, Id = GuidGenerator.Create() }; var md5HashRaw = $"{fileObject.Md5Hash}{productInfo.ProductAccesskey}{upgradeRecordInput.UpgradeIdentifier}{fileObject.FileSize}"; var upgradeRequest = new DeviceUpgradeCommandRequest() { Length = fileObject.FileSize, UpgradeIdentifier = upgradeRecordInput.UpgradeIdentifier, SignatureValue = md5HashRaw.Md5Fun(), FirmwareUrl = $"{serverApplicationOptions.DownloadDeviceFirmwareBasicUrl}{upgradeRecordInput.Id}", TimeOut = serverApplicationOptions.DownloadDeviceFirmwareTimeOut, }; upgradeRecordInput.UpgradeMessage = upgradeRequest.Serialize(); upgradeRecordInput.FirmwareSignature = upgradeRequest.SignatureValue; string upgradeMessageHexString = upgradeRecordInput.UpgradeMessage.ToHexString(); //检查长度是否超过了OneNET平台升级属性标识符的长度限制 var thingModelInfoStr = ((OneNETProductInfoDto)productInfo).ThingModelInfos; if (string.IsNullOrWhiteSpace(thingModelInfoStr)) { logger.LogError($"{nameof(DeviceUpgradeCommandToOneNET)} 通过OneNET产品ID和属性标识符获取属性配置信息失败,属性信息为空"); return false; } var thingModelInfo = thingModelInfoStr.Deserialize(); if (thingModelInfo.Properties == null) { logger.LogError($"{nameof(DeviceUpgradeCommandToOneNET)} 通过OneNET产品ID和属性标识符获取属性配置信息失败,属性信息为空"); return false; } var property = thingModelInfo.Properties.Where(d => d.Identifier == upgradeProperty.IoTPlatformRawFieldName).FirstOrDefault(); //精准匹配 if (property == null) { logger.LogError($"{nameof(DeviceUpgradeCommandToOneNET)} 通过OneNET产品ID和属性标识符获取属性配置信息失败,没有找到属性标识升级对应的属性平台信息"); return false; } var length = ((OneNETModelStringSpecs)property.DataType.Specs).Length; if (upgradeMessageHexString.Length > length) { throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}平台端物模型信息属性标识符{upgradeProperty.IoTPlatformRawFieldName}长度超过OneNET平台限制,请检查物模型属性标识符长度是否超过了{length}"); } var insertResult = await deviceUpgradeRecordService.CreateAsync(upgradeRecordInput); if (insertResult == null) { throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}升级记录失败"); } //发送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)); //将升级记录数据Id作为key,文件数据ID作为值,存入Redis缓存中。 string cacheKey = string.Format($"{RedisConst.CacheDeviceUpgradeRecordDataKey}", upgradeRecordInput.Id); await FreeRedisProvider.Instance.SetAsync(cacheKey, fileObject.Id); await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo); //更新状态为升级中 await deviceUpgradeRecordService.UpdateStatusAsync(new UpdateStatusInput() { Id = upgradeRecordInput.Id.Value, UpgradeStatus = DeviceUpgradeStatusTypeEnum.Upgrading, }); return true; } catch (Exception) { throw; } } /// /// 抄读OneNET平台设备属性数据 /// /// /// /// /// protected async Task> DevicePropertyValueToOneNET(DeviceManagementInfoDto deviceInfo, DevicePropertyValueForApiInput input) { try { //检查下设备是否在线 var deviceOnlineStatus = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput() { DeviceName = deviceInfo.IoTPlatformDeviceOpenInfo, OneNETAccountId = deviceInfo.IoTPlatformAccountId, ProductId = deviceInfo.IoTPlatformProductId, }); if (deviceOnlineStatus == null || deviceOnlineStatus.Code != ResponeResultEnum.Success) { throw new UserFriendlyException("获取平台设备信息失败"); } if (deviceOnlineStatus.Data.Status != 1) { throw new UserFriendlyException("设备不在线"); } var deviceDataResult = await oneNETDeviceService.QueryDevicePropertyDetail(new QueryDevicePropertyDetailInput() { DeviceName = deviceInfo.IoTPlatformDeviceOpenInfo, OneNETAccountId = deviceInfo.IoTPlatformAccountId, ProductId = deviceInfo.IoTPlatformProductId, PropertyInfos = input.PropertyList }); if (deviceDataResult == null || deviceDataResult.Success == false || deviceDataResult.Data == null) { throw new UserFriendlyException($"设备{deviceInfo.DeviceName}获取数据失败"); } //获取设备产品平台端物模型信息 var platformThingModelInfo = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput() { Id = deviceInfo.IoTPlatformProductId }); if (platformThingModelInfo == null || platformThingModelInfo.Count <= 0) { return deviceDataResult.Data; } List updateKeys = new List() { ThingModelFixedTypeConst.FIRMWARE_VERSION.ToLowerInvariant(), ThingModelFixedTypeConst.ReadingMode.ToLowerInvariant() }; var platformUpdatePropertyInfos = platformThingModelInfo.Where(d => updateKeys.Contains(d.StandardFieldName.ToLowerInvariant())).ToList(); if (platformUpdatePropertyInfos == null || platformUpdatePropertyInfos.Count <= 0) { return deviceDataResult.Data; } //根据抄读结果(单个或多个属性)更新设备信息,统一收集后只调用一次 UpdateDeviceInfos bool needUpdate = false; //抄读结果如果有固件版本号,则更新固件版本号到设备信息中 var firmwareVersionKey = platformUpdatePropertyInfos.FirstOrDefault(d => d.StandardFieldName?.ToLowerInvariant() == ThingModelFixedTypeConst.FIRMWARE_VERSION.ToLowerInvariant())?.IoTPlatformRawFieldName; if (!string.IsNullOrWhiteSpace(firmwareVersionKey) && deviceDataResult.Data.ContainsKey(firmwareVersionKey)) { deviceInfo.FirmwareVersion = deviceDataResult.Data[firmwareVersionKey].ToString(); needUpdate = true; } //抄读结果如果有抄读模式,则更新抄读模式到设备信息中 var readModeKey = platformUpdatePropertyInfos.FirstOrDefault(d => d.StandardFieldName?.ToLowerInvariant() == ThingModelFixedTypeConst.ReadingMode.ToLowerInvariant())?.IoTPlatformRawFieldName; if (!string.IsNullOrWhiteSpace(readModeKey) && deviceDataResult.Data.ContainsKey(readModeKey)) { var readModeValue = deviceDataResult.Data[readModeKey]; // 兼容 JsonElement / 字符串 / 数值 三种情况 int readModeInt; if (readModeValue is System.Text.Json.JsonElement jsonElement) { if (jsonElement.ValueKind == System.Text.Json.JsonValueKind.Number && jsonElement.TryGetInt32(out var num)) { readModeInt = num; } else { readModeInt = Convert.ToInt32(jsonElement.ToString()); } } else { readModeInt = Convert.ToInt32(readModeValue); } deviceInfo.ReadingMode = (DeviceReadingModeEnum)readModeInt; needUpdate = true; } if (needUpdate) { await deviceAppService.UpdateDeviceInfos(deviceInfo); } return deviceDataResult.Data; } catch (Exception ex) { if (input.PropertyList.Contains(ThingModelFixedTypeConst.SpecialCommand)) { ex = new UserFriendlyException("请检查设备是否已经采集数据"); throw ex; } else { throw; } } } #endregion #region CTWing 设备操作 /// /// CTWing 批量设备创建 /// /// /// protected async Task CTWingDeviceBatchCreateAsync(BatchCreateDeviceAggregationInput input) { try { throw new UserFriendlyException($"CTWing 批量设备创建失败,CTWing暂未实现。"); } catch (Exception) { throw; } } #endregion /// /// 更新设备信息并处理缓存 /// /// /// 推送结果原始信息 /// 设备接入鉴权key /// /// private async Task DeviceUpdateHandler(DeviceManagementInfoDto input, HttpDataResult pushResult, string platformPassword = null) { UpdateDeviceInput updateDeviceInput = input.Adapt(); updateDeviceInput.IoTPlatformResponse = pushResult.Serialize(); updateDeviceInput.IsPlatformPushSuccess = true; if (!string.IsNullOrWhiteSpace(updateDeviceInput.PlatformPassword)) { updateDeviceInput.PlatformPassword = platformPassword; } var updateResult = await deviceAppService.UpdateAsync(updateDeviceInput); if (updateResult == null) { logger.LogError($"{nameof(DeviceUpdateHandler)} 更新设备信息失败:{input.Serialize()}"); throw new UserFriendlyException($"推送结果更新失败。"); } //设备数据缓存到Redis DeviceCacheInfos deviceCacheInfos = input.Adapt(); deviceCacheInfos.PlatformPassword = null; FreeRedisProvider.Instance.HSet(RedisConst.CacheAllDeviceInfoHashKey, input.DeviceAddress, deviceCacheInfos); return input.Adapt(); } /// /// 获取OneNET产品信息和平台端物模型信息 /// /// 物联网平台产品Id /// 设备地址(用于错误信息) /// 返回产品信息和平台端物模型信息的元组 protected async Task<(dynamic ProductInfo, dynamic PlatformThingModelInfo)> GetOneNETProductAndThingModelInfoAsync(string iotPlatformProductId, string deviceAddress) { //获取设备对应的产品信息 var productInfo = await oneNETProductService.GetProductInfoAsync(new IdInput() { Id = iotPlatformProductId }); if (productInfo == null) { throw new UserFriendlyException($"{nameof(DeviceUpgradeCommandToOneNET)} OneNET设备升级属性设置失败,产品Id{iotPlatformProductId}未找到对应的产品信息。"); } //获取设备对应的平台端物模型信息,校验前端传入的属性标识集合是否存在不合法的属性标识符 var platformThingModelInfo = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput() { Id = iotPlatformProductId }); if (platformThingModelInfo == null) { throw new UserFriendlyException($"设备{deviceAddress}的平台端物模型信息不存在。"); } return (productInfo, platformThingModelInfo); } /// /// 根据平台处理设备升级指令 /// /// 设备信息 /// 接收指令信息Dto /// 固件版本信息 /// 文件信息 /// 升级输入参数 /// OneNET产品信息(可选,如果已获取则传入以避免重复调用) /// OneNET平台端物模型信息(可选,如果已获取则传入以避免重复调用) /// 处理结果 protected async Task ProcessDeviceUpgradeByPlatformAsync(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto receiveCommandInfoDto, DeviceFirmwareInfoDto deviceFirmwareVersionInfo, FileObjectDto fileInfo, DeviceUpgradeForApiInput input, dynamic oneNETProductInfo = null, dynamic oneNETPlatformThingModelInfo = null) { if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET) { //如果未传入产品信息和物模型信息,则获取 if (oneNETProductInfo == null || oneNETPlatformThingModelInfo == null) { var (productInfo, platformThingModelInfo) = await GetOneNETProductAndThingModelInfoAsync(deviceInfo.IoTPlatformProductId, deviceInfo.DeviceAddress); oneNETProductInfo = productInfo; oneNETPlatformThingModelInfo = platformThingModelInfo; } return await DeviceUpgradeCommandToOneNET(deviceInfo, receiveCommandInfoDto, deviceFirmwareVersionInfo, fileInfo, input, oneNETProductInfo, oneNETPlatformThingModelInfo); } else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing) { //await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName,commandRequest); //return true; throw new UserFriendlyException($"发送设备升级指令信息失败,CTWing暂未实现。"); } else { throw new UserFriendlyException($"发送设备升级指令信息失败,未找到对应的产品配置信息。"); } } } }