Compare commits

...

2 Commits

Author SHA1 Message Date
ChenYi
c1423d549f 优化注释 2025-12-09 17:24:27 +08:00
ChenYi
180b654f26 设备端物模型结构体属性设置请求体封装、平台产品物模型信息结构体拆解函数 2025-12-09 17:19:34 +08:00
3 changed files with 72 additions and 73 deletions

View File

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

View File

@ -6,6 +6,7 @@ using JiShe.ServicePro.DataChannelManages;
using JiShe.ServicePro.DeviceManagement.DeviceInfos; using JiShe.ServicePro.DeviceManagement.DeviceInfos;
using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto; using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto;
using JiShe.ServicePro.DeviceManagement.Permissions; using JiShe.ServicePro.DeviceManagement.Permissions;
using JiShe.ServicePro.DeviceManagement.ThingModels;
using JiShe.ServicePro.Dto; using JiShe.ServicePro.Dto;
using JiShe.ServicePro.Enums; using JiShe.ServicePro.Enums;
using JiShe.ServicePro.FreeRedisProvider; using JiShe.ServicePro.FreeRedisProvider;
@ -29,7 +30,9 @@ namespace JiShe.IoT.DeviceAggregation
/// <param name="redisPubSubService">Redis发布订阅服务</param> /// <param name="redisPubSubService">Redis发布订阅服务</param>
/// <param name="ioTDBDataChannelManageService">数据通道</param> /// <param name="ioTDBDataChannelManageService">数据通道</param>
/// <param name="_ioTDBOptions">IoTDBOptions</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; IoTDBOptions ioTDBOptions = _ioTDBOptions.Value;
@ -288,47 +291,45 @@ namespace JiShe.IoT.DeviceAggregation
{ {
try try
{ {
if (input.CommandContent == null || input.CommandContent.Keys.Count <=0)
{
throw new UserFriendlyException($"指令参数异常");
}
var deviceInfo = await deviceAppService.FindByIdAsync(input); var deviceInfo = await deviceAppService.FindByIdAsync(input);
if (deviceInfo == null) if (deviceInfo == null)
{ {
throw new UserFriendlyException($"设备不存在"); 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); //将指令存储
var receiveCommandInfoDto = new ReceiveCommandInfoDto()
{
DeviceAddress = deviceInfo.DeviceAddress,
Commands = input.CommandContent,
DeviceType = deviceInfo.DeviceType,
SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem,
IoTPlatform = deviceInfo.IoTPlatform,
};
//数据写入遥测任务数据存储通道 //数据写入遥测任务数据存储通道
if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET) if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET)
{ {
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo)); return await DeviceCommandInfoToOneNET(deviceInfo, receiveCommandInfoDto);
return await DeviceCommandInfoToOneNET(deviceInfo, packetTaskInfo);
} }
else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing) else if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.CTWing)
{ {
await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName,commandRequest); //await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.CTWingAepCommandIssuedEventName,commandRequest);
return true; //return true;
throw new UserFriendlyException($"发送设备指令信息失败CTWing暂未实现。");
} }
else else
{ {
throw new UserFriendlyException($"创建设备失败,未找到对应的产品配置信息。"); throw new UserFriendlyException($"发送设备指令信息失败,未找到对应的产品配置信息。");
} }
} }
catch (Exception) catch (Exception)
{ {
throw; throw;
} }
} }
@ -387,15 +388,17 @@ namespace JiShe.IoT.DeviceAggregation
try try
{ {
CreateDeviceInput createDeviceInput = input.Adapt<CreateDeviceInput>(); CreateDeviceInput createDeviceInput = input.Adapt<CreateDeviceInput>();
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>() var productInfo = await oneNETProductService.GetProductInfoAsync(new IdInput<string>() { Id = input.IoTPlatformProductId });
.Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)//此处不需要过滤产品状态,方便测试产品配置信息是否准确,避免跟车间生产搞混
.WhereIf(input.DeviceSourceTypeEnum == DeviceSourceTypeEnum.Workshop, e => e.IsEnabled == true)
.FirstAsync();
if (productInfo == null) 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; createDeviceInput.DeviceName = input.DeviceAddress;
@ -532,35 +535,26 @@ namespace JiShe.IoT.DeviceAggregation
public async Task<DeviceManagementInfoDto> RepushDeviceInfoToOneNET(DeviceManagementInfoDto input) public async Task<DeviceManagementInfoDto> RepushDeviceInfoToOneNET(DeviceManagementInfoDto input)
{ {
try try
{ {
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>()
.Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)
.FirstAsync();
if (productInfo == null)
{
throw new UserFriendlyException($"推送失败,未找到对应的产品配置信息。");
}
//检查OneNET平台设备是否已经存在 //检查OneNET平台设备是否已经存在
var oneNETDeviceInfoResult = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput() var oneNETDeviceInfoResult = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput()
{ {
DeviceName = input.IoTPlatformDeviceOpenInfo, DeviceName = input.IoTPlatformDeviceOpenInfo,
ProductId = productInfo.IoTPlatformProductId, ProductId = input.IoTPlatformProductId,
OneNETAccountId = productInfo.OneNETAccountId, OneNETAccountId = input.IoTPlatformAccountId,
}); });
if (oneNETDeviceInfoResult != null && oneNETDeviceInfoResult.Code == ServicePro.Enums.ResponeResultEnum.Success) 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平台 //推送至OneNET平台
var pushResult = await oneNETDeviceService.CreateDeviceInfoAsync(new CreateDeviceInfoInput() var pushResult = await oneNETDeviceService.CreateDeviceInfoAsync(new CreateDeviceInfoInput()
{ {
DeviceName = input.IoTPlatformDeviceOpenInfo, DeviceName = input.IoTPlatformDeviceOpenInfo,
ProductId = productInfo.IoTPlatformProductId, ProductId = input.IoTPlatformProductId,
OneNETAccountId = productInfo.OneNETAccountId, OneNETAccountId = input.IoTPlatformAccountId,
Description = input.DeviceAddress, Description = input.DeviceAddress,
}); });
@ -589,23 +583,13 @@ namespace JiShe.IoT.DeviceAggregation
public async Task<bool> DeleteDeviceInfoToOneNET(DeviceManagementInfoDto input) public async Task<bool> DeleteDeviceInfoToOneNET(DeviceManagementInfoDto input)
{ {
try try
{ {
var productInfo = await FreeSqlDbContext.Instance.Select<OneNETProductInfos>()
.Where(e => e.IoTPlatformProductId == input.IoTPlatformProductId)
.FirstAsync();
if (productInfo == null)
{
throw new UserFriendlyException($"删除失败,未找到对应的产品配置信息。");
}
//删除OneNET平台设备信息 //删除OneNET平台设备信息
var deleteResult = await oneNETDeviceService.DeleteDeviceInfoAsync(new DeleteDeviceInfoInput() var deleteResult = await oneNETDeviceService.DeleteDeviceInfoAsync(new DeleteDeviceInfoInput()
{ {
DeviceName = input.IoTPlatformDeviceOpenInfo, DeviceName = input.IoTPlatformDeviceOpenInfo,
ProductId = productInfo.IoTPlatformProductId, ProductId = input.IoTPlatformProductId,
OneNETAccountId = productInfo.OneNETAccountId, OneNETAccountId = input.IoTPlatformAccountId,
}); });
if (deleteResult == null || deleteResult.Code != ServicePro.Enums.ResponeResultEnum.Success) if (deleteResult == null || deleteResult.Code != ServicePro.Enums.ResponeResultEnum.Success)
@ -634,13 +618,39 @@ namespace JiShe.IoT.DeviceAggregation
/// 发送OneNET平台设备指令 /// 发送OneNET平台设备指令
/// </summary> /// </summary>
/// <param name="deviceInfo"></param> /// <param name="deviceInfo"></param>
/// <param name="packetTaskInfo"></param> /// <param name="input"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="UserFriendlyException"></exception> /// <exception cref="UserFriendlyException"></exception>
public async Task<bool> DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, DeviceTelemetryPacketTaskInfo packetTaskInfo) public async Task<bool> DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto input)
{ {
try try
{ {
//检查设备是否有配置设备端物模型信息
//如果有配置就检查指令字典中是否有SpecialCommand标识符
//如果有就需要构建 SpecialCommand 的特别指令
if (deviceInfo.IsNeedConfigDevicMdoel && deviceInfo.DeviceThingModelDataId.HasValue && input.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);
input.Commands[ThingModelFixedTypeConst.SpecialCommand] = tempSpecialCommand;
}
var commandRequest = new OpenApiRequest()
{
Message = input.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() var deviceOnlineStatus = await oneNETDeviceService.DeviceInfoDetailAsync(new DeviceInfoDetailInput()
{ {

View File

@ -53,7 +53,6 @@ namespace JiShe.IoT
DeviceAddress = commandIssueInfo.DeviceAddress, DeviceAddress = commandIssueInfo.DeviceAddress,
IssueRawMessage = input.Serialize(), IssueRawMessage = input.Serialize(),
IoTDataType = IoTDBDataTypeConst.Command, IoTDataType = IoTDBDataTypeConst.Command,
TelemetryType = (int)commandIssueInfo.TelemetryType,
TelemetrySource = (int)commandIssueInfo.SourceType, TelemetrySource = (int)commandIssueInfo.SourceType,
IoTPlatform = (int)commandIssueInfo.IoTPlatform, IoTPlatform = (int)commandIssueInfo.IoTPlatform,
IoTPlatformProductId = deviceInfo.IoTPlatformProductId, IoTPlatformProductId = deviceInfo.IoTPlatformProductId,