Compare commits

..

2 Commits

Author SHA1 Message Date
ChenYi
3229ac917f 完善设备操作日志记录 2026-02-04 17:12:26 +08:00
ChenYi
0424b6ae38 操作日志处理记录 2026-02-03 17:23:46 +08:00
5 changed files with 138 additions and 29 deletions

@ -1 +1 @@
Subproject commit ddfe5fb0eabb58f3b0d2014d911947d5d6dd71fb
Subproject commit cbf9b87d348e3af5dcbe55fc70e03dad91dc69d2

View File

@ -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<DeviceTelemetryCommandTypeEnum> actionTypes = new List<DeviceTelemetryCommandTypeEnum>() {
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<Dictionary<string, object>>("获取数据失败来源类型错误业务系统传固定值2", -104, ResponeResultEnum.Fail);
}
//限定操作类型必须为设置类型
if (messageBody.TelemetryCommandType != DeviceTelemetryCommandTypeEnum.GetAttributeData)
{
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("设备指令操作类型错误", -105, ResponeResultEnum.Fail);
}
var deviceInfo = await deviceAppService.FindByDeviceAddressAsync(messageBody.DeviceAddress);
if (deviceInfo == null)
{
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("设备不存在", -105, ResponeResultEnum.Fail);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("设备不存在", -106, ResponeResultEnum.Fail);
}
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, input, deviceInfo.Adapt<DeviceCacheInfos>(), messageBody.Commands.Serialize());
@ -209,7 +233,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
if (platformThingModelInfo == null)
{
return HttpDataResultExtensions.Failed<Dictionary<string, object>>($"业务系统推送指令时设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。", -106, ResponeResultEnum.Fail);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>($"业务系统推送指令时设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。", -107, ResponeResultEnum.Fail);
}
foreach (var item in messageBody.Commands)
@ -222,17 +246,17 @@ namespace JiShe.IoT.BusinessSystemAggregation
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,14 +268,14 @@ namespace JiShe.IoT.BusinessSystemAggregation
if (messageBody.Commands == null || messageBody.Commands.Count <= 0)
{
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("获取数据失败OneNET平台未返回数据", -106);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("获取数据失败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<Dictionary<string, object>>("获取数据失败OneNET平台未返回数据", -106);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("获取数据失败OneNET平台未返回数据", -109);
}
return HttpDataResultExtensions.Success<Dictionary<string, object>>(queryResult);
@ -263,7 +287,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
}
else
{
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("指令处理失败,当前设备平台类型异常", -105);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("指令处理失败,当前设备平台类型异常", -110);
}
return HttpDataResultExtensions.Success<Dictionary<string, object>>("指令下发成功");
@ -275,7 +299,7 @@ namespace JiShe.IoT.BusinessSystemAggregation
catch (Exception ex)
{
_logger.LogError(ex, "接收业务系统指令信息时发生异常");
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("指令处理失败,发送异常", -106);
return HttpDataResultExtensions.Failed<Dictionary<string, object>>("指令处理失败,发送异常", -111);
}
}

View File

@ -312,6 +312,7 @@ namespace JiShe.IoT.DeviceAggregation
DeviceType = deviceInfo.DeviceType,
SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem,
IoTPlatform = deviceInfo.IoTPlatform,
TelemetryCommandType = DeviceTelemetryCommandTypeEnum.RoutineOperationSet,
};
//数据写入遥测任务数据存储通道
@ -558,6 +559,8 @@ namespace JiShe.IoT.DeviceAggregation
Message = input.Serialize(),
};
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt<DeviceCacheInfos>(), input.PropertyList.Serialize());
packetTaskInfo.TelemetryType = (int)DeviceTelemetryCommandTypeEnum.GetAttributeData;
if (deviceInfo.IoTPlatform == IoTPlatformTypeEnum.OneNET)
{
@ -619,6 +622,7 @@ namespace JiShe.IoT.DeviceAggregation
{ThingModelFixedTypeConst.SpecialCommand,
""}
},
TelemetryCommandType = DeviceTelemetryCommandTypeEnum.ThingModelSwitch,
}, platformThingModelInfos);
}
}

View File

@ -47,13 +47,13 @@ namespace JiShe.IoT
var oneNETIssueMessageEntity = new DeviceTelemetryPacketTaskInfo()
{
DataBaseName = iotDBOptions.DataBaseName,
DeviceType = $"{commandIssueInfo.DeviceType}",
DeviceAddress = commandIssueInfo.DeviceAddress,
DeviceType = $"{deviceInfo.DeviceType}",
DeviceAddress = deviceInfo.DeviceAddress,
IssueRawMessage = input.Serialize(),
IssuePayload = messageBody,
IoTDataType = IoTDBDataTypeConst.Command,
TelemetrySource = (int)commandIssueInfo.SourceType,
IoTPlatform = (int)commandIssueInfo.IoTPlatform,
IoTPlatform = (int)deviceInfo.IoTPlatform,
IoTPlatformProductId = deviceInfo.IoTPlatformProductId,
IoTPlatformDeviceOpenInfo = deviceInfo.IoTPlatformDeviceOpenInfo,
IoTPlatformAccountId = deviceInfo.IoTPlatformAccountId,
@ -61,7 +61,8 @@ namespace JiShe.IoT
IoTPlatformProductName = deviceInfo.IoTPlatformProductName,
RetryCount = 0,
IssueStatus = (int)DeviceCommandIssueStatusEnum.Unprocessed,
LastIssueTime = DateTime.Now
LastIssueTime = DateTime.Now,
TelemetryType = (int)commandIssueInfo.TelemetryCommandType,
};
return oneNETIssueMessageEntity;

View File

@ -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<string> exitCommands = new List<string>()
{
ThingModelFixedTypeConst.FIRMWARE_UPGRADE.ToLowerInvariant(),
ThingModelFixedTypeConst.SpecialCommand.ToLowerInvariant(),
ThingModelFixedTypeConst.DEVICE_TO_MASTER_SWITCH.ToLowerInvariant(),
};
/// <param name="logger"></param>
/// <param name="deviceAppService">设备服务</param>
/// <param name="oneNETDeviceService">OneNET设备服务</param>
@ -449,6 +458,7 @@ namespace JiShe.IoT
};
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt<DeviceCacheInfos>(), input.Commands.Serialize());
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo);
@ -466,7 +476,7 @@ namespace JiShe.IoT
/// </summary>
/// <param name="deviceInfo"></param>
/// <param name="taskInput">设置属性请求内容相关</param>
/// <param name="deviceFirmwareInfo">固件数据Id</param>
/// <param name="deviceFirmwareInfo">固件数据</param>
/// <param name="fileObject">固件文件信息</param>
/// <param name="input">入参</param>
/// <param name="productInfo">产品信息(如果已获取则传入以避免重复调用)</param>
@ -573,6 +583,7 @@ namespace JiShe.IoT
{
{ upgradeProperty.IoTPlatformRawFieldName, upgradeMessageHexString }
};
taskInput.TelemetryCommandType = DeviceTelemetryCommandTypeEnum.FirmwareUpgrade;
var commandRequest = new OpenApiRequest()
{
@ -724,6 +735,75 @@ namespace JiShe.IoT
}
}
}
/// <summary>
/// 发送设备切换主站指令
/// </summary>
/// <param name="deviceInfo"></param>
/// <param name="taskInput">设置属性请求内容相关</param>
/// <param name="input">入参</param>
/// <param name="productInfo">产品信息(如果已获取则传入以避免重复调用)</param>
/// <param name="platformThingModelInfo">平台端物模型信息(如果已获取则传入以避免重复调用)</param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
protected async Task<bool> 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<IoTPlatformThingModelInfoDto>)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<string, object>()
{
{ upgradeProperty.IoTPlatformRawFieldName, upgradeMessageHexString }
};
var commandRequest = new OpenApiRequest()
{
Message = taskInput.Serialize(),
};
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt<DeviceCacheInfos>(), 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