Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1211 migrate device models from st table to database #1215

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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 Microsoft.EntityFrameworkCore.Migrations;

public partial class AddDeviceModel : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.CreateTable(
name: "DeviceModels",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
IsBuiltin = table.Column<bool>(type: "boolean", nullable: false),
SupportLoRaFeatures = table.Column<bool>(type: "boolean", nullable: false),
UseOTAA = table.Column<bool>(type: "boolean", nullable: true),
PreferredWindow = table.Column<int>(type: "integer", nullable: true),
Deduplication = table.Column<int>(type: "integer", nullable: true),
ABPRelaxMode = table.Column<bool>(type: "boolean", nullable: true),
Downlink = table.Column<bool>(type: "boolean", nullable: true),
KeepAliveTimeout = table.Column<int>(type: "integer", nullable: true),
RXDelay = table.Column<int>(type: "integer", nullable: true),
SensorDecoder = table.Column<string>(type: "text", nullable: true),
AppEUI = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
_ = table.PrimaryKey("PK_DeviceModels", x => x.Id);
});
}

protected override void Down(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.DropTable(
name: "DeviceModels");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// <auto-generated />
using System;
using AzureIoTHub.Portal.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
Expand All @@ -21,6 +22,59 @@ protected override void BuildModel(ModelBuilder modelBuilder)

NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);

modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b =>
{
b.Property<string>("Id")
.HasColumnType("text");

b.Property<bool?>("ABPRelaxMode")
.HasColumnType("boolean");

b.Property<string>("AppEUI")
.IsRequired()
.HasColumnType("text");

b.Property<int?>("Deduplication")
.HasColumnType("integer");

b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");

b.Property<bool?>("Downlink")
.HasColumnType("boolean");

b.Property<bool>("IsBuiltin")
.HasColumnType("boolean");

b.Property<int?>("KeepAliveTimeout")
.HasColumnType("integer");

b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");

b.Property<int?>("PreferredWindow")
.HasColumnType("integer");

b.Property<int?>("RXDelay")
.HasColumnType("integer");

b.Property<string>("SensorDecoder")
.IsRequired()
.HasColumnType("text");

b.Property<bool>("SupportLoRaFeatures")
.HasColumnType("boolean");

b.Property<bool?>("UseOTAA")
.HasColumnType("boolean");

b.HasKey("Id");

b.ToTable("DeviceModels");
});

modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b =>
{
b.Property<string>("Id")
Expand Down
1 change: 1 addition & 0 deletions src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class PortalDbContext : DbContext
public DbSet<DeviceModelProperty> DeviceModelProperties { get; set; }
public DbSet<DeviceTag> DeviceTags { get; set; }
public DbSet<DeviceModelCommand> DeviceModelCommands { get; set; }
public DbSet<DeviceModel> DeviceModels { get; set; }

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public PortalDbContext(DbContextOptions<PortalDbContext> options)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) CGI France. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace AzureIoTHub.Portal.Infrastructure.Seeds
{
using Azure.Data.Tables;
using Domain;
using Domain.Entities;
using Factories;
using Microsoft.EntityFrameworkCore;
using Models.v10.LoRaWAN;

internal static class DeviceModelSeeder
{
public static async Task MigrateDeviceModels(this PortalDbContext ctx, ConfigHandler config)
{
var table = new TableClientFactory(config.StorageAccountConnectionString)
.GetDeviceTemplates();

var set = ctx.Set<DeviceModel>();

foreach (var item in table.Query<TableEntity>().ToArray())
{
if (await set.AnyAsync(c => c.Id == item.RowKey))
continue;

#pragma warning disable CS8629 // Nullable value type may be null.
_ = await set.AddAsync(new DeviceModel
{
Id = item.RowKey,
Name = item[nameof(DeviceModel.Name)]?.ToString(),
Description = item[nameof(DeviceModel.Description)]?.ToString(),
IsBuiltin = bool.Parse(item[nameof(DeviceModel.IsBuiltin)]?.ToString() ?? "false"),
SupportLoRaFeatures = bool.Parse(item[nameof(DeviceModel.SupportLoRaFeatures)]?.ToString() ?? "false"),
ABPRelaxMode = bool.TryParse(item[nameof(DeviceModel.ABPRelaxMode)]?.ToString(), out var abpRelaxMode) ? abpRelaxMode : null,
Deduplication = Enum.TryParse<DeduplicationMode>(item[nameof(DeviceModel.Deduplication)]?.ToString(), out var deduplication) ? deduplication : null,
Downlink = bool.TryParse(item[nameof(DeviceModel.Downlink)]?.ToString(), out var downLink) ? downLink : null,
KeepAliveTimeout = int.TryParse(item[nameof(DeviceModel.KeepAliveTimeout)]?.ToString(), out var keepAliveTimeout) ? keepAliveTimeout : null,
PreferredWindow = int.TryParse(item[nameof(DeviceModel.PreferredWindow)]?.ToString(), out var preferredWindow) ? preferredWindow : null,
RXDelay = int.TryParse(item[nameof(DeviceModel.PreferredWindow)]?.ToString(), out var rxDelay) ? rxDelay : null,
UseOTAA = bool.TryParse(item[nameof(DeviceModel.UseOTAA)]?.ToString(), out var useOTAA) ? useOTAA : null,
AppEUI = item[nameof(DeviceModel.AppEUI)]?.ToString(),
SensorDecoder = item[nameof(DeviceModel.SensorDecoder)]?.ToString()
});
#pragma warning restore CS8629 // Nullable value type may be null.

if (config is ProductionConfigHandler)
{
_ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey);
}
}
Comment on lines +22 to +51

Check notice

Code scanning / CodeQL

Missed opportunity to use Where

This foreach loop implicitly filters its target sequence [here](1) - consider filtering the sequence explicitly using '.Where(...)'.
}
}
}
3 changes: 3 additions & 0 deletions src/AzureIoTHub.Portal/Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@ await context
await context
.MigrateDeviceModelCommands(config);

await context
.MigrateDeviceModels(config);

_ = await context.SaveChangesAsync();
}
catch (InvalidOperationException e)
Expand Down
37 changes: 37 additions & 0 deletions src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) CGI France. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace AzureIoTHub.Portal.Domain.Entities
{
using AzureIoTHub.Portal.Models.v10.LoRaWAN;
using Base;

public class DeviceModel : EntityBase
{
public string Name { get; set; }

public string? Description { get; set; }

public bool IsBuiltin { get; set; }

public bool SupportLoRaFeatures { get; set; }

public bool? UseOTAA { get; set; }

public int? PreferredWindow { get; set; }

public DeduplicationMode? Deduplication { get; set; }

public bool? ABPRelaxMode { get; set; }

public bool? Downlink { get; set; }

public int? KeepAliveTimeout { get; set; }

public int? RXDelay { get; set; }

public string? SensorDecoder { get; set; }

public string? AppEUI { get; set; }
}
}