设备端物模型结构体属性设置请求体封装、平台产品物模型信息结构体拆解函数

This commit is contained in:
ChenYi 2025-12-09 17:19:34 +08:00
parent e63baad9da
commit 180b654f26
3 changed files with 73 additions and 74 deletions

View File

@ -11,19 +11,9 @@ namespace JiShe.IoT.DeviceAggregation
public class DeviceCommandForApiInput:IdInput
{
/// <summary>
/// 设备在物联网平台中发送的命令内容JSON格式
/// 设备在物联网平台中属性设置的参数键值对
/// </summary>
[Required(ErrorMessage = "命令内容不能为空")]
public string CommandContent { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public DeviceTypeEnum? DeviceType { get; set; }
/// <summary>
/// 设备指令类型
/// </summary>
public DeviceTelemetryCommandTypeEnum? TelemetryType { get; set; }
public Dictionary<string,object> CommandContent { get; set; }
}
}

View File

@ -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
/// <param name="redisPubSubService">Redis发布订阅服务</param>
/// <param name="ioTDBDataChannelManageService">数据通道</param>
/// <param name="_ioTDBOptions">IoTDBOptions</param>
public class DeviceAggregationService(ILogger<DeviceAggregationService> logger, IDeviceAppService deviceAppService, IOneNETDeviceService oneNETDeviceService, IReliableRedisPubSubService redisPubSubService, IIoTDBDataChannelManageService ioTDBDataChannelManageService,IOptions<IoTDBOptions> _ioTDBOptions) : IoTAppService, IDeviceAggregationService
/// <param name="oneNETProductService">OneNET产品服务</param>
/// <param name="deviceThingModelService">设备端物模型服务</param>
public class DeviceAggregationService(ILogger<DeviceAggregationService> logger, IDeviceAppService deviceAppService, IOneNETDeviceService oneNETDeviceService, IReliableRedisPubSubService redisPubSubService, IIoTDBDataChannelManageService ioTDBDataChannelManageService,IOptions<IoTDBOptions> _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<Dictionary<string,object>>(),
DeviceType = input.DeviceType ?? DeviceTypeEnum.GATEWAY,//todo 设备类型 需要跟设备统一什么情况下知道具体设备类型
SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem,
TelemetryType = input.TelemetryType ?? DeviceTelemetryCommandTypeEnum.,
IoTPlatform = deviceInfo.IoTPlatform,
}.Serialize(),
};
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt<DeviceCacheInfos>(), 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<CreateDeviceInput>();
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>()
.Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)//此处不需要过滤产品状态,方便测试产品配置信息是否准确,避免跟车间生产搞混
.WhereIf(input.DeviceSourceTypeEnum == DeviceSourceTypeEnum.Workshop, e => e.IsEnabled == true)
.FirstAsync();
var productInfo = await oneNETProductService.GetProductInfoAsync(new IdInput<string>() { 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<DeviceManagementInfoDto> RepushDeviceInfoToOneNET(DeviceManagementInfoDto input)
{
try
{
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>()
.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<bool> DeleteDeviceInfoToOneNET(DeviceManagementInfoDto input)
{
try
{
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>()
.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平台设备指令
/// </summary>
/// <param name="deviceInfo"></param>
/// <param name="packetTaskInfo"></param>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
public async Task<bool> DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, DeviceTelemetryPacketTaskInfo packetTaskInfo)
public async Task<bool> 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<string>() { Id = deviceInfo.IoTPlatformProductId });
if (propertyInfo == null)
{
throw new UserFriendlyException($"{nameof(DeviceCommandInfoToOneNET)} OneNET设备属性设置失败产品Id{deviceInfo.IoTPlatformProductId}未找到对应的属性信息。");
}
Dictionary<string, string> 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<DeviceCacheInfos>(), commandRequest.Message);
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
//检查下设备是否在线
var deviceOnlineStatus = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput()
{

View File

@ -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,