Compare commits

..

2 Commits

16 changed files with 15180 additions and 125 deletions

View File

@ -3,6 +3,7 @@ using JiShe.IoT.DeviceAggregation.Dto;
using JiShe.ServicePro;
using JiShe.ServicePro.Core;
using JiShe.ServicePro.DeviceManagement.DeviceInfos;
using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto;
using JiShe.ServicePro.FileManagement.Files;
using Volo.Abp;
using Volo.Abp.Content;
@ -104,6 +105,14 @@ namespace JiShe.IoT.DeviceAggregation
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<bool> BatchCreateDeviceBusinessSystemAsync(BatchCreateDeviceBusinessSystemInput input);
Task<bool> BatchCreateDeviceBusinessSystemAsync(BatchCreateDeviceBusinessSystemInput input);
/// <summary>
/// 绑定设备端物模型
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<bool> BindingDeviceThingModel(BindingDeviceThingModelInput input);
}
}

View File

@ -14,17 +14,14 @@ using JiShe.ServicePro.Enums;
using JiShe.ServicePro.FileManagement.Files;
using JiShe.ServicePro.FreeRedisProvider;
using JiShe.ServicePro.IoTDBManagement.DataChannels;
using JiShe.ServicePro.IoTDBManagement.TableModels;
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 StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Content;
using static FreeSql.Internal.GlobalFilter;
namespace JiShe.IoT.DeviceAggregation
{
@ -699,6 +696,58 @@ namespace JiShe.IoT.DeviceAggregation
}
/// <summary>
/// 绑定设备端物模型
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<bool> BindingDeviceThingModel(BindingDeviceThingModelInput input)
{
try
{
List<DeviceManagementInfoDto> bindingDeviceList = await deviceAppService.BindingDeviceThingModel(input);
if (bindingDeviceList == null)
{
throw new UserFriendlyException($"绑定设备端物模型失败", "-101");
}
foreach (var item in bindingDeviceList)
{
if (item.IoTPlatform == ServicePro.Enums.IoTPlatformTypeEnum.CTWing)
{
logger.LogInformation($"{nameof(BindingDeviceThingModel)} CTWing设备{item.DeviceAddress}绑定设备物模型未实现");
continue;
}
else if (item.IoTPlatform == ServicePro.Enums.IoTPlatformTypeEnum.OneNET)
{
var platformThingModelInfos = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput<string>() { Id = item.IoTPlatformProductId });
return await DeviceCommandInfoToOneNET(item, new ReceiveCommandInfoDto()
{
DeviceType = item.DeviceType,
SourceType = DeviceTelemetrySourceTypeEnum.AdminSystem,
DeviceAddress = item.DeviceAddress,
IoTPlatform = item.IoTPlatform,
Commands = new Dictionary<string, object>() {
{ThingModelFixedTypeConst.SpecialCommand,
""}
},
}, platformThingModelInfos);
}
}
return true;
}
catch (Exception)
{
throw;
}
}
#region OneNET
/// <summary>
/// OneNET设备创建
@ -987,27 +1036,30 @@ namespace JiShe.IoT.DeviceAggregation
/// <summary>
/// 发送OneNET平台设备指令
/// </summary>
/// <param name="deviceInfo"></param>
/// <param name="input"></param>
/// <param name="deviceInfo">设备信息</param>
/// <param name="input">指令信息</param>
/// <param name="platformThingModelInfos">平台端物模型信息</param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
protected async Task<bool> DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto input)
protected async Task<bool> DeviceCommandInfoToOneNET(DeviceManagementInfoDto deviceInfo, ReceiveCommandInfoDto input, List<IoTPlatformThingModelInfoDto> platformThingModelInfos = null)
{
try
{
//获取设备对应的平台端物模型信息,校验前端传入的属性标识集合是否存在不合法的属性标识符
if (platformThingModelInfos == null || platformThingModelInfos.Count <= 0)
{
platformThingModelInfos = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput<string>() { Id = deviceInfo.IoTPlatformProductId });
}
var platformThingModelInfo = await platformThingModelInfoAppService.FindByPlatformProductIdAsync(new IdInput<string>() { Id = deviceInfo.IoTPlatformProductId });
if (platformThingModelInfo == null)
if (platformThingModelInfos == null || platformThingModelInfos.Count <= 0)
{
throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}的平台端物模型信息不存在。");
}
foreach (var item in input.Commands)
{
var tempPlatformThingModelInfo = platformThingModelInfo.Where(d => d.IoTPlatformRawFieldName == item.Key).FirstOrDefault();
var tempPlatformThingModelInfo = platformThingModelInfos.Where(d => d.IoTPlatformRawFieldName == item.Key).FirstOrDefault();
if (tempPlatformThingModelInfo == null)
{
throw new UserFriendlyException($"设备{deviceInfo.DeviceAddress}平台端物模型信息不存在属性标识符{item.Key}。");
@ -1022,8 +1074,7 @@ namespace JiShe.IoT.DeviceAggregation
//检查设备是否有配置设备端物模型信息
//如果有配置就检查指令字典中是否有SpecialCommand标识符
//如果有就需要构建 SpecialCommand 的特别指令
//如果有就需要构建 SpecialCommand 的特别指令
if (deviceInfo.IsNeedConfigDevicMdoel && deviceInfo.DeviceThingModelDataId.HasValue && input.Commands.ContainsKey(ThingModelFixedTypeConst.SpecialCommand))
{
var propertyInfo = await oneNETProductService.GetProductThingModelSpecialCommandDataTypeListAsync(new IdInput<string>() { Id = deviceInfo.IoTPlatformProductId });
@ -1037,6 +1088,11 @@ namespace JiShe.IoT.DeviceAggregation
input.Commands[ThingModelFixedTypeConst.SpecialCommand] = tempSpecialCommand;
}
else if (input.Commands.ContainsKey(ThingModelFixedTypeConst.SpecialCommand))
{
//非绑定物模型情况下SpecialCommand还原默认值设备也会恢复默认采集方式
input.Commands[ThingModelFixedTypeConst.SpecialCommand] = CommonConst.SpecialCommandDefaultValue;
}
var commandRequest = new OpenApiRequest()
{
@ -1044,25 +1100,7 @@ namespace JiShe.IoT.DeviceAggregation
};
var packetTaskInfo = GetDeviceTelemetryPacketTaskInfo(ioTDBOptions, commandRequest, deviceInfo.Adapt<DeviceCacheInfos>(), input.Commands.Serialize());
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
////检查下设备是否在线
//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("设备不在线");
//}
await ioTDBDataChannelManageService.DeviceTelemetryTaskWriterAsync(DataChannelManage.DeviceTelemetryTaskDataChannel.Writer, (DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo));
await redisPubSubService.PublishReliableAsync(DistributedMessageCenterConst.OneNETCommandIssuedEventName, packetTaskInfo);
return true;

View File

@ -1,6 +1,5 @@
using JiShe.ServicePro;
using JiShe.ServicePro.ApacheIoTDB.Provider.Options;
using JiShe.ServicePro.Consts;
using JiShe.ServicePro.Core;
using JiShe.ServicePro.Dto;
using JiShe.ServicePro.Encrypt;
@ -9,7 +8,6 @@ using JiShe.ServicePro.FreeRedisProvider;
using JiShe.ServicePro.FreeSqlProvider;
using JiShe.ServicePro.IoTDBManagement.TableModels;
using Microsoft.Extensions.Logging;
using System.Xml.Linq;
using Volo.Abp;
namespace JiShe.IoT

View File

@ -1,74 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JiShe.IoT.Migrations
{
/// <inheritdoc />
public partial class updatetable202601201031 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "BusinessSystemSubDeviceDataId",
table: "ServiceProSubDeviceManagementInfo");
migrationBuilder.DropColumn(
name: "BusinessSystemDeviceDataId",
table: "ServiceProDeviceInfo");
migrationBuilder.AlterTable(
name: "ServiceProSubDeviceManagementInfo",
comment: "子设备信息,需要下发配置的网关设备才用到",
oldComment: "子设备信息");
migrationBuilder.AddColumn<bool>(
name: "IsSynced",
table: "ServiceProSubDeviceManagementInfo",
type: "boolean",
nullable: false,
defaultValue: false,
comment: "是否同步");
migrationBuilder.AddColumn<int>(
name: "SubDeviceCapacity",
table: "ServiceProDeviceInfo",
type: "integer",
nullable: false,
defaultValue: 64,
comment: "子设备容量");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsSynced",
table: "ServiceProSubDeviceManagementInfo");
migrationBuilder.DropColumn(
name: "SubDeviceCapacity",
table: "ServiceProDeviceInfo");
migrationBuilder.AlterTable(
name: "ServiceProSubDeviceManagementInfo",
comment: "子设备信息",
oldComment: "子设备信息,需要下发配置的网关设备才用到");
migrationBuilder.AddColumn<long>(
name: "BusinessSystemSubDeviceDataId",
table: "ServiceProSubDeviceManagementInfo",
type: "bigint",
nullable: true,
comment: "业务系统子设备数据Id");
migrationBuilder.AddColumn<long>(
name: "BusinessSystemDeviceDataId",
table: "ServiceProDeviceInfo",
type: "bigint",
nullable: true,
comment: "业务系统设备数据Id");
}
}
}

View File

@ -13,8 +13,8 @@ using Volo.Abp.EntityFrameworkCore;
namespace JiShe.IoT.Migrations
{
[DbContext(typeof(IoTDbContext))]
[Migration("20260120023219_updatetable202601201031")]
partial class updatetable202601201031
[Migration("20260120070701_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)

View File

@ -739,7 +739,7 @@ namespace JiShe.IoT.Migrations
DeviceThingModelDataId = table.Column<Guid>(type: "uuid", nullable: true, comment: "设备物模型数据Id"),
FirmwareVersion = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true, comment: "固件版本"),
UpgradeDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true, comment: "升级日期"),
BusinessSystemDeviceDataId = table.Column<long>(type: "bigint", nullable: true, comment: "业务系统设备数据Id"),
SubDeviceCapacity = table.Column<int>(type: "integer", nullable: false, defaultValue: 64, comment: "子设备容量"),
ConcurrencyStamp = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
CreatorId = table.Column<Guid>(type: "uuid", nullable: true),
@ -1072,7 +1072,7 @@ namespace JiShe.IoT.Migrations
SubDeviceAddress = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false, comment: "子设备地址"),
SubDeviceIndex = table.Column<int>(type: "integer", nullable: false, comment: "子设备索引,抑或是主设备下唯一标识符、计量代码"),
SubDeviceBrandCode = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false, comment: "子设备品牌编码"),
BusinessSystemSubDeviceDataId = table.Column<long>(type: "bigint", nullable: true, comment: "业务系统子设备数据Id"),
IsSynced = table.Column<bool>(type: "boolean", nullable: false, comment: "是否同步"),
ConcurrencyStamp = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
CreatorId = table.Column<Guid>(type: "uuid", nullable: true),
@ -1092,7 +1092,7 @@ namespace JiShe.IoT.Migrations
{
table.PrimaryKey("PK_ServiceProSubDeviceManagementInfo", x => x.Id);
},
comment: "子设备信息");
comment: "子设备信息,需要下发配置的网关设备才用到");
migrationBuilder.CreateTable(
name: "ServiceProTextTemplates",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JiShe.IoT.Migrations
{
/// <inheritdoc />
public partial class updateIoTThingModels : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "IoTPlatformRawFieldExtension",
table: "ServiceProIoTPlatformThingModelInfo",
type: "text",
nullable: true,
comment: "物联网平台中对应产品物模型标识符扩展,结构体或者数组的时候,是参数的名称与长度的键值对,其他类型就是长度或者值范围",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true,
oldComment: "物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型");
migrationBuilder.AddColumn<bool>(
name: "IsOperableIdentifier",
table: "ServiceProIoTPlatformThingModelInfo",
type: "boolean",
nullable: false,
defaultValue: false,
comment: "是否可操作物模型标识符");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsOperableIdentifier",
table: "ServiceProIoTPlatformThingModelInfo");
migrationBuilder.AlterColumn<string>(
name: "IoTPlatformRawFieldExtension",
table: "ServiceProIoTPlatformThingModelInfo",
type: "text",
nullable: true,
comment: "物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true,
oldComment: "物联网平台中对应产品物模型标识符扩展,结构体或者数组的时候,是参数的名称与长度的键值对,其他类型就是长度或者值范围");
}
}
}

View File

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace JiShe.IoT.Migrations
{
[DbContext(typeof(IoTDbContext))]
[Migration("20260116085116_InitialCreate")]
[Migration("20260121015002_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@ -698,10 +698,6 @@ namespace JiShe.IoT.Migrations
.HasColumnType("character varying(50)")
.HasComment("账户手机号");
b.Property<long?>("BusinessSystemDeviceDataId")
.HasColumnType("bigint")
.HasComment("业务系统设备数据Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
@ -847,6 +843,12 @@ namespace JiShe.IoT.Migrations
.HasColumnType("text")
.HasComment("备注");
b.Property<int>("SubDeviceCapacity")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(64)
.HasComment("子设备容量");
b.Property<Guid?>("TenantId")
.HasColumnType("uuid")
.HasColumnName("TenantId")
@ -1024,10 +1026,6 @@ namespace JiShe.IoT.Migrations
b.Property<Guid>("Id")
.HasColumnType("uuid");
b.Property<long?>("BusinessSystemSubDeviceDataId")
.HasColumnType("bigint")
.HasComment("业务系统子设备数据Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
@ -1072,6 +1070,10 @@ namespace JiShe.IoT.Migrations
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsSynced")
.HasColumnType("boolean")
.HasComment("是否同步");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("timestamp with time zone")
.HasColumnName("LastModificationTime");
@ -1138,7 +1140,7 @@ namespace JiShe.IoT.Migrations
b.ToTable("ServiceProSubDeviceManagementInfo", null, t =>
{
t.HasComment("子设备信息");
t.HasComment("子设备信息,需要下发配置的网关设备才用到");
});
});
@ -1588,7 +1590,7 @@ namespace JiShe.IoT.Migrations
b.Property<string>("IoTPlatformRawFieldExtension")
.HasColumnType("text")
.HasComment("物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型");
.HasComment("物联网平台中对应产品物模型标识符扩展,结构体或者数组的时候,是参数的名称与长度的键值对,其他类型就是长度或者值范围");
b.Property<string>("IoTPlatformRawFieldName")
.IsRequired()
@ -1602,6 +1604,10 @@ namespace JiShe.IoT.Migrations
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsOperableIdentifier")
.HasColumnType("boolean")
.HasComment("是否可操作物模型标识符");
b.Property<bool>("IsSpecialIdentifier")
.HasColumnType("boolean")
.HasComment("是否是特殊物模型标识符");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JiShe.IoT.Migrations
{
/// <inheritdoc />
public partial class updatethingmodel : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "AccessMode",
table: "ServiceProIoTPlatformThingModelInfo",
type: "text",
nullable: false,
defaultValue: "r",
comment: "物模型标识符访问模式");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AccessMode",
table: "ServiceProIoTPlatformThingModelInfo");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JiShe.IoT.Migrations
{
/// <inheritdoc />
public partial class updatethingmodel2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "AccessMode",
table: "ServiceProIoTPlatformThingModelInfo",
type: "character varying(10)",
maxLength: 10,
nullable: false,
defaultValue: "r",
comment: "物模型标识符访问模式",
oldClrType: typeof(string),
oldType: "text",
oldDefaultValue: "r",
oldComment: "物模型标识符访问模式");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "AccessMode",
table: "ServiceProIoTPlatformThingModelInfo",
type: "text",
nullable: false,
defaultValue: "r",
comment: "物模型标识符访问模式",
oldClrType: typeof(string),
oldType: "character varying(10)",
oldMaxLength: 10,
oldDefaultValue: "r",
oldComment: "物模型标识符访问模式");
}
}
}

View File

@ -1536,6 +1536,14 @@ namespace JiShe.IoT.Migrations
b.Property<Guid>("Id")
.HasColumnType("uuid");
b.Property<string>("AccessMode")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(10)
.HasColumnType("character varying(10)")
.HasDefaultValue("r")
.HasComment("物模型标识符访问模式");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
@ -1587,7 +1595,7 @@ namespace JiShe.IoT.Migrations
b.Property<string>("IoTPlatformRawFieldExtension")
.HasColumnType("text")
.HasComment("物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型");
.HasComment("物联网平台中对应产品物模型标识符扩展,结构体或者数组的时候,是参数的名称与长度的键值对,其他类型就是长度或者值范围");
b.Property<string>("IoTPlatformRawFieldName")
.IsRequired()
@ -1601,6 +1609,10 @@ namespace JiShe.IoT.Migrations
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsOperableIdentifier")
.HasColumnType("boolean")
.HasComment("是否可操作物模型标识符");
b.Property<bool>("IsSpecialIdentifier")
.HasColumnType("boolean")
.HasComment("是否是特殊物模型标识符");

View File

@ -3,6 +3,7 @@ using JiShe.IoT.DeviceAggregation.Dto;
using JiShe.ServicePro;
using JiShe.ServicePro.Core;
using JiShe.ServicePro.DeviceManagement.DeviceInfos;
using JiShe.ServicePro.DeviceManagement.DeviceInfos.Dto;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Content;
@ -139,5 +140,17 @@ namespace JiShe.IoT.Controllers
return _deviceAggregationService.DownloadFirmwareInfoAsync(input);
}
/// <summary>
/// 绑定设备端物模型
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost(nameof(BindingDeviceThingModel))]
[SwaggerOperation(summary: "绑定设备端物模型", Tags = new[] { "DeviceInfo" })]
public async Task<bool> BindingDeviceThingModel(BindingDeviceThingModelInput input)
{
return await _deviceAggregationService.BindingDeviceThingModel(input);
}
}
}