From 188ffb112bd727ac6705af6002193e2266eb2e40 Mon Sep 17 00:00:00 2001 From: Kevin BEAUGRAND <9513635+kbeaugrand@users.noreply.github.com> Date: Tue, 27 Sep 2022 12:54:33 +0200 Subject: [PATCH] Fix #1289 - Add ClassType to device twin configuration for loraWAN (#1290) --- ... for ClassType in device model.Designer.cs | 351 ++++++++++++++++++ ...d support for ClassType in device model.cs | 30 ++ .../PortalDbContextModelSnapshot.cs | 3 + .../Mappers/LoRaDeviceModelMapperTests.cs | 2 +- .../Server/Mappers/LoRaDeviceModelMapper.cs | 2 + .../Entities/DeviceModel.cs | 2 + 6 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.Designer.cs create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.cs diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.Designer.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.Designer.cs new file mode 100644 index 000000000..209f723dc --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.Designer.cs @@ -0,0 +1,351 @@ +// +using System; +using AzureIoTHub.Portal.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AzureIoTHub.Portal.Infrastructure.Migrations +{ + [DbContext(typeof(PortalDbContext))] + [Migration("20220927114351_Add support for ClassType in device model")] + partial class AddsupportforClassTypeindevicemodel + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsConnected") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StatusUpdatedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Devices"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); + + b.Property("AppEUI") + .HasColumnType("text"); + + b.Property("ClassType") + .HasColumnType("integer"); + + b.Property("Deduplication") + .HasColumnType("integer"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Downlink") + .HasColumnType("boolean"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("PreferredWindow") + .HasColumnType("integer"); + + b.Property("RXDelay") + .HasColumnType("integer"); + + b.Property("SensorDecoder") + .HasColumnType("text"); + + b.Property("SupportLoRaFeatures") + .HasColumnType("boolean"); + + b.Property("UseOTAA") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DeviceModels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Confirmed") + .HasColumnType("boolean"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Frame") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelCommands"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsWritable") + .HasColumnType("boolean"); + + b.Property("ModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PropertyType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelProperties"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTag", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("Searchable") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DeviceTags"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EdgeDeviceModels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("EdgeDeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModuleName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EdgeDeviceModelCommands"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); + + b.Property("AlreadyLoggedInOnce") + .HasColumnType("boolean"); + + b.Property("AppEUI") + .HasColumnType("text"); + + b.Property("AppKey") + .HasColumnType("text"); + + b.Property("AppSKey") + .HasColumnType("text"); + + b.Property("ClassType") + .HasColumnType("integer"); + + b.Property("DataRate") + .HasColumnType("text"); + + b.Property("Deduplication") + .HasColumnType("integer"); + + b.Property("DevAddr") + .HasColumnType("text"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Downlink") + .HasColumnType("boolean"); + + b.Property("FCntDownStart") + .HasColumnType("integer"); + + b.Property("FCntResetCounter") + .HasColumnType("integer"); + + b.Property("FCntUpStart") + .HasColumnType("integer"); + + b.Property("GatewayID") + .HasColumnType("text"); + + b.Property("IsConnected") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NbRep") + .HasColumnType("text"); + + b.Property("NwkSKey") + .HasColumnType("text"); + + b.Property("PreferredWindow") + .HasColumnType("integer"); + + b.Property("RX1DROffset") + .HasColumnType("integer"); + + b.Property("RX2DataRate") + .HasColumnType("integer"); + + b.Property("RXDelay") + .HasColumnType("integer"); + + b.Property("ReportedRX1DROffset") + .HasColumnType("text"); + + b.Property("ReportedRX2DataRate") + .HasColumnType("text"); + + b.Property("ReportedRXDelay") + .HasColumnType("text"); + + b.Property("SensorDecoder") + .HasColumnType("text"); + + b.Property("StatusUpdatedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Supports32BitFCnt") + .HasColumnType("boolean"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text"); + + b.Property("TxPower") + .HasColumnType("text"); + + b.Property("UseOTAA") + .HasColumnType("boolean"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LorawanDevices"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.cs new file mode 100644 index 000000000..b0606425a --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220927114351_Add support for ClassType in device model.cs @@ -0,0 +1,30 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable disable + +namespace AzureIoTHub.Portal.Infrastructure.Migrations +{ + using AzureIoTHub.Portal.Models.v10.LoRaWAN; + using Microsoft.EntityFrameworkCore.Migrations; + + public partial class AddsupportforClassTypeindevicemodel : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + _ = migrationBuilder.AddColumn( + name: "ClassType", + table: "DeviceModels", + type: "integer", + nullable: false, + defaultValue: ClassType.A); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + _ = migrationBuilder.DropColumn( + name: "ClassType", + table: "DeviceModels"); + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs index b80b1060f..ca2eac845 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs @@ -67,6 +67,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("AppEUI") .HasColumnType("text"); + b.Property("ClassType") + .HasColumnType("integer"); + b.Property("Deduplication") .HasColumnType("integer"); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs index f993fad54..c33ce626d 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs @@ -123,7 +123,7 @@ public void UpdateTableEntityStateUnderTestExpectedBehavior(bool isBuiltin) var result = loRaDeviceModelMapper.BuildDeviceModelDesiredProperties(model); // Assert - _ = result.Keys.Count.Should().Be(13); + _ = result.Keys.Count.Should().Be(14); this.mockRepository.VerifyAll(); } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs index 664611916..8e3201b24 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs @@ -47,6 +47,7 @@ public LoRaDeviceModelDto CreateDeviceModel(TableEntity entity) Description = entity[nameof(LoRaDeviceModelDto.Description)]?.ToString(), SensorDecoder = entity[nameof(LoRaDeviceModelDto.SensorDecoder)]?.ToString(), UseOTAA = bool.Parse(entity[nameof(LoRaDeviceModelDto.UseOTAA)]?.ToString() ?? "true"), + ClassType = Enum.TryParse(entity[nameof(LoRaDeviceModelDto.ClassType)]?.ToString(), out var classType) ? classType : ClassType.A, PreferredWindow = int.TryParse(entity[nameof(LoRaDeviceModelDto.PreferredWindow)]?.ToString(), out var intResult) ? intResult : 1, Supports32BitFCnt = bool.TryParse(entity[nameof(LoRaDeviceModelDto.Supports32BitFCnt)]?.ToString(), out var boolResult) ? boolResult : null, ABPRelaxMode = bool.TryParse(entity[nameof(LoRaDeviceModelDto.ABPRelaxMode)]?.ToString(), out boolResult) ? boolResult : null, @@ -79,6 +80,7 @@ public Dictionary BuildDeviceModelDesiredProperties(LoRaDeviceMo AddOptionalProperties(nameof(LoRaDeviceModelDto.RX1DROffset), modelDto.RX1DROffset, desiredProperties); AddOptionalProperties(nameof(LoRaDeviceModelDto.RX2DataRate), modelDto.RX2DataRate, desiredProperties); AddOptionalProperties(nameof(LoRaDeviceModelDto.RXDelay), modelDto.RXDelay, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.ClassType), modelDto.ClassType.ToString(), desiredProperties); return desiredProperties; } diff --git a/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs b/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs index add66fa1a..8a14cbcef 100644 --- a/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs +++ b/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs @@ -22,6 +22,8 @@ public class DeviceModel : EntityBase public DeduplicationMode? Deduplication { get; set; } + public ClassType ClassType { get; set; } + public bool? ABPRelaxMode { get; set; } public bool? Downlink { get; set; }