diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab1Tests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab1Tests.cs index 7de7554d4..6a1532171 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab1Tests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab1Tests.cs @@ -22,7 +22,6 @@ public void ModuleDialogTab1ShouldBeRenderedProperly() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List(), @@ -43,7 +42,6 @@ public void ClickOnAddShouldAddRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List() { @@ -78,7 +76,6 @@ public void ClickOnRemoveShouldDeleteRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List() { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab2Tests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab2Tests.cs index 9d3fc7ea3..9c86a66db 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab2Tests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab2Tests.cs @@ -22,7 +22,6 @@ public void ModuleDialogTab2ShouldBeRenderedProperly() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List(), @@ -43,7 +42,6 @@ public void ClickOnAddShouldAddRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List() @@ -78,7 +76,6 @@ public void ClickOnRemoveShouldDeleteRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List() diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab3Tests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab3Tests.cs index 67c8dc285..fbf35dadc 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab3Tests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTab3Tests.cs @@ -22,7 +22,6 @@ public void ModuleDialogTab3ShouldBeRenderedProperly() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List(), @@ -43,7 +42,6 @@ public void ClickOnAddShouldAddRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List(), @@ -76,7 +74,6 @@ public void ClickOnRemoveShouldDeleteRow() var module = new IoTEdgeModule() { ModuleName = Guid.NewGuid().ToString(), - Version = Guid.NewGuid().ToString(), Status = "running", EnvironmentVariables = new List(), ModuleIdentityTwinSettings = new List(), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTests.cs index 5148ac692..a4851d49c 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Configurations/EdgeModule/ModuleDialogTests.cs @@ -29,7 +29,6 @@ public async Task ModuleDialogTestMustBeRenderedOnShow() var module = new IoTEdgeModule() { ModuleName = moduleName, - Version = "1.0", Status = "running", ImageURI = moduleImageUri, EnvironmentVariables = new List(), @@ -73,7 +72,6 @@ public async Task ClickOnSubmitShouldUpdateModuleValues() var module = new IoTEdgeModule() { ModuleName = moduleName, - Version = moduleVersion, Status = "running", ImageURI = moduleImageUri, EnvironmentVariables = new List(), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs index 424982cbb..056049c3d 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs @@ -210,7 +210,7 @@ public void ClickOnRebootShouldRebootModule() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); - _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module.ModuleName, StringComparison.Ordinal)), "RestartModule")) + _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ReturnsAsync(new C2Dresult() { Payload = "ABC", @@ -255,14 +255,14 @@ public void ClickOnRebootShouldDisplaySnackbarIfError() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); - _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module.ModuleName, StringComparison.Ordinal)), "RestartModule")) + _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ReturnsAsync(new C2Dresult() { Payload = "ABC", Status = 500 }); - _ = this.mockSnackbarService.Setup(c => c.Add(It.IsAny(), Severity.Error, It.IsAny>())).Returns((Snackbar)null); + _ = this.mockSnackbarService.Setup(c => c.Add(It.IsAny(), Severity.Error, It.IsAny>())).Returns(value: null); var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); @@ -301,7 +301,7 @@ public void EdgeDeviceDetailPageShouldProcessProblemDetailsExceptionWhenIssueOcc _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); - _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module.ModuleName, StringComparison.Ordinal)), "RestartModule")) + _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); @@ -357,6 +357,7 @@ public void ClickOnLogsShouldDisplayLogs() [Test] public void ClickOnConnectShouldDisplayDeviceCredentials() { + // Arrange _ = SetupOnInitialisation(); var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); @@ -376,6 +377,80 @@ public void ClickOnConnectShouldDisplayDeviceCredentials() cut.WaitForAssertion(() => MockRepository.VerifyAll()); } + [Test] + public void ClickOnCommandModuleShouldReturn200() + { + // Arrange + _ = SetupOnInitialisation(); + + var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); + cut.WaitForAssertion(() => cut.Find("#commandTest")); + + var commandButton = cut.Find("#commandTest"); + + _ = this.mockEdgeDeviceClientService + .Setup(x => x.ExecuteModuleMethod(It.Is(c => c.Equals(this.mockdeviceId, StringComparison.Ordinal)), It.IsAny(), It.IsAny())) + .ReturnsAsync(new C2Dresult() { Status = 200 }); + + _ = this.mockSnackbarService + .Setup(c => c.Add(It.IsAny(), Severity.Success, It.IsAny>())) + .Returns(value: null); + + // Act + commandButton.Click(); + + // Assert + cut.WaitForAssertion(() => MockRepository.VerifyAll()); + } + + [Test] + public void ClickOnCommandModuleShouldReturn400() + { + // Arrange + _ = SetupOnInitialisation(); + + var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); + cut.WaitForAssertion(() => cut.Find("#commandTest")); + + var commandButton = cut.Find("#commandTest"); + + _ = this.mockEdgeDeviceClientService + .Setup(x => x.ExecuteModuleMethod(It.Is(c => c.Equals(this.mockdeviceId, StringComparison.Ordinal)), It.IsAny(), It.IsAny())) + .ReturnsAsync(new C2Dresult() { Status = 400 }); + + _ = this.mockSnackbarService + .Setup(c => c.Add(It.IsAny(), Severity.Error, It.IsAny>())) + .Returns(value: null); + + // Act + commandButton.Click(); + + // Assert + cut.WaitForAssertion(() => MockRepository.VerifyAll()); + } + + [Test] + public void ClickOnCommandModuleShouldProcessProblemDetailsExceptionWhenIssueOccurs() + { + // Arrange + _ = SetupOnInitialisation(); + + var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId)); + cut.WaitForAssertion(() => cut.Find("#commandTest")); + + var commandButton = cut.Find("#commandTest"); + + _ = this.mockEdgeDeviceClientService + .Setup(x => x.ExecuteModuleMethod(It.Is(c => c.Equals(this.mockdeviceId, StringComparison.Ordinal)), It.IsAny(), It.IsAny())) + .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); + + // Act + commandButton.Click(); + + // Assert + cut.WaitForAssertion(() => MockRepository.VerifyAll()); + } + [Test] public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() { @@ -434,7 +509,15 @@ private IoTEdgeDevice SetupOnInitialisation() DeviceId = this.mockdeviceId, ConnectionState = "Connected", ModelId = Guid.NewGuid().ToString(), - Tags = tags + Tags = tags, + Modules = new List() + { + new IoTEdgeModule() + { + ModuleName = "moduleTest", + ImageURI = Guid.NewGuid().ToString() + } + } }; _ = this.mockEdgeDeviceClientService.Setup(service => service.GetDevice(this.mockdeviceId)) @@ -444,7 +527,19 @@ private IoTEdgeDevice SetupOnInitialisation() .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal)))) .ReturnsAsync(new IoTEdgeModel() { - ModelId = mockIoTEdgeDevice.ModelId + ModelId = mockIoTEdgeDevice.ModelId, + EdgeModules = new List() + { + new IoTEdgeModule() + { + ModuleName = "moduleTest", + ImageURI = Guid.NewGuid().ToString(), + Commands = new List() + { + new Portal.Shared.Models.v10.IoTEdgeModuleCommand(){ Name = "commandTest"} + } + } + } }); _ = this.mockDeviceTagSettingsClientService diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/ModuleLogsDialogTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/ModuleLogsDialogTests.cs index d017864c4..3d76b38e4 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/ModuleLogsDialogTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/ModuleLogsDialogTests.cs @@ -41,7 +41,6 @@ public async Task ModuleLogsDialogParametersMustBeCorrect() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -84,7 +83,6 @@ public async Task ModuleLogsShouldProcessProblemDetailsExceptionWhenIssueOccursO var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -120,7 +118,6 @@ public async Task ModuleLogsMustCloseOnCLickOnCloseButton() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeDeviceClientServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeDeviceClientServiceTests.cs index 02ef48348..f4182cb2b 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeDeviceClientServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeDeviceClientServiceTests.cs @@ -180,7 +180,6 @@ public async Task GetEdgeDeviceLogsMustReturnLogsWhenNoError() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -208,5 +207,53 @@ public async Task GetEdgeDeviceLogsMustReturnLogsWhenNoError() _ = result.Count.Should().Be(1); } + + [Test] + public async Task ExecuteModuleMethodShouldReturn200() + { + // Arrange + var deviceId = Fixture.Create(); + + var edgeModule = new IoTEdgeModule() + { + ModuleName = Guid.NewGuid().ToString() + }; + + var methodName = Fixture.Create(); + var c2Dresult = Fixture.Create(); + + _ = MockHttpClient.When(HttpMethod.Post, $"/api/edge/devices/{deviceId}/{edgeModule.ModuleName}/{methodName}") + .RespondJson(c2Dresult); + + // Act + var result = await this.edgeDeviceClientService.ExecuteModuleMethod(deviceId, edgeModule.ModuleName, methodName); + + // Assert + _ = result.Should().BeEquivalentTo(c2Dresult); + MockHttpClient.VerifyNoOutstandingRequest(); + MockHttpClient.VerifyNoOutstandingExpectation(); + } + + [Test] + public async Task ExecuteModuleCommandShouldReturn200() + { + // Arrange + var deviceId = Fixture.Create(); + var commandName = Fixture.Create(); + var moduleName = Fixture.Create(); + + var c2Dresult = Fixture.Create(); + + _ = MockHttpClient.When(HttpMethod.Post, $"/api/edge/devices/{deviceId}/{moduleName}/{commandName}") + .RespondJson(c2Dresult); + + // Act + var result = await this.edgeDeviceClientService.ExecuteModuleMethod(deviceId, moduleName, commandName); + + // Assert + _ = result.Should().BeEquivalentTo(c2Dresult); + MockHttpClient.VerifyNoOutstandingRequest(); + MockHttpClient.VerifyNoOutstandingExpectation(); + } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/EdgeDevicesControllerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/EdgeDevicesControllerTests.cs index bf3449017..09909638c 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/EdgeDevicesControllerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/EdgeDevicesControllerTests.cs @@ -1,7 +1,7 @@ // 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.Tests.Unit.Server.Controllers.v1._0 +namespace AzureIoTHub.Portal.Tests.Unit.Server.Controllers.v10 { using System; using System.Collections.Generic; @@ -271,7 +271,6 @@ public async Task GetEdgeDeviceLogsMustReturnLogsWhenNoErrorIsReturned() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -387,13 +386,38 @@ public async Task ExecuteMethodShouldExecuteC2DMethod(string methodName) var deviceId = Guid.NewGuid().ToString(); _ = this.mockEdgeDeviceService - .Setup(x => x.ExecuteModuleMethod(It.IsAny(), + .Setup(x => x.ExecuteModuleMethod(It.IsAny(), It.Is(c => c.Equals(deviceId, StringComparison.Ordinal)), It.Is(c => c.Equals(methodName, StringComparison.Ordinal)))) .ReturnsAsync(new C2Dresult()); // Act - var result = await edgeDeviceController.ExecuteModuleMethod(module, deviceId, methodName); + var result = await edgeDeviceController.ExecuteModuleMethod(module.ModuleName, deviceId, methodName); + + // Assert + Assert.IsNotNull(result); + + this.mockRepository.VerifyAll(); + } + + [TestCase("test")] + public async Task ExecuteCustomModuleMethodShouldExecuteC2DMethod(string commandName) + { + // Arrange + var edgeDeviceController = CreateEdgeDevicesController(); + + var deviceId = Guid.NewGuid().ToString(); + var moduleName = Guid.NewGuid().ToString(); + + _ = this.mockEdgeDeviceService + .Setup(x => x.ExecuteModuleMethod( + It.Is(c => c.Equals(deviceId, StringComparison.Ordinal)), + It.Is(c => c.Equals(moduleName, StringComparison.Ordinal)), + It.Is(c => c.Equals(commandName, StringComparison.Ordinal)))) + .ReturnsAsync(new C2Dresult()); + + // Act + var result = await edgeDeviceController.ExecuteModuleMethod(deviceId, moduleName, commandName); // Assert Assert.IsNotNull(result); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/ConfigHelperTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/ConfigHelperTest.cs index 3b4a0dca4..b1db5fd4b 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/ConfigHelperTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/ConfigHelperTest.cs @@ -115,7 +115,6 @@ public void CreateGatewayModuleShouldReturnValue() // Assert Assert.IsNotNull(result); Assert.AreEqual("running", result.Status); - Assert.AreEqual("1.0", result.Version); Assert.AreEqual("image_test", result.ImageURI); Assert.AreEqual(1, result.EnvironmentVariables.Count); } @@ -161,7 +160,6 @@ public void GenerateModulesContentShouldReturnValue() { ModuleName = "ModuleTest", Status = "running", - Version = "1.0", ImageURI = "image", EnvironmentVariables = new List() { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/DeviceHelperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/DeviceHelperTests.cs index 84c9e21b0..9957c0934 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/DeviceHelperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Helpers/DeviceHelperTests.cs @@ -308,12 +308,20 @@ public void RetrieveModuleListShouldReturnModuleList() LoRaWanNetworkSrvModule = new { version = "1.0", - status = "running" + status = "running", + settings = new + { + image = "image" + } }, LoRaBasicsStationModule = new { runtimeStatus = "running", - version = "1.0" + version = "1.0", + settings = new + { + image = "image" + } } } }); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/EdgeDeviceMapperTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/EdgeDeviceMapperTest.cs index 75826fb03..5dd46cf7f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/EdgeDeviceMapperTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/EdgeDeviceMapperTest.cs @@ -40,7 +40,14 @@ public void CreateEdgeDeviceListItemShouldReturnValue() var edgeDeviceMapper = CreateMapper(); var deviceTwin = new Twin(Guid.NewGuid().ToString()); + var modelId = Guid.NewGuid().ToString(); + deviceTwin.Properties.Reported["clients"] = new object[12]; + deviceTwin.Tags["modelId"] = modelId; + + _ = this.mockDeviceModelImageManager + .Setup(x => x.ComputeImageUri(It.Is(c => c.Equals(modelId, StringComparison.Ordinal)))) + .Returns(new Uri($"http://fake.local/{modelId}")); // Act var result = edgeDeviceMapper.CreateEdgeDeviceListItem(deviceTwin); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs index 433833ecf..b9f984aea 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs @@ -1049,6 +1049,60 @@ public async Task ExecuteC2DMethodShouldThrowInternalServerErrorExceptionWhenIss this.mockRepository.VerifyAll(); } + [Test] + public async Task ExecuteCustomCommandC2DMethodShouldReturn200() + { + // Arrange + var service = CreateService(); + var deviceId = Guid.NewGuid().ToString(); + var moduleName = Guid.NewGuid().ToString(); + + var method = new CloudToDeviceMethod(Guid.NewGuid().ToString()); + + _ = this.mockServiceClient.Setup(c => c.InvokeDeviceMethodAsync( + It.Is(x => x.Equals(deviceId, StringComparison.Ordinal)), + It.Is(x => x.Equals(moduleName, StringComparison.Ordinal)), + It.Is(x => x == method), + It.IsAny())) + .ReturnsAsync(new CloudToDeviceMethodResult + { + Status = 200 + }); + + // Act + var result = await service.ExecuteCustomCommandC2DMethod(deviceId, moduleName, method); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(200, result.Status); + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task ExecuteCustomCommandC2DMethodShouldThrowInternalServerErrorExceptionWhenIssueOccurs() + { + // Arrange + var service = CreateService(); + var deviceId = Guid.NewGuid().ToString(); + var moduleName = Guid.NewGuid().ToString(); + + var method = new CloudToDeviceMethod(Guid.NewGuid().ToString()); + + _ = this.mockServiceClient.Setup(c => c.InvokeDeviceMethodAsync( + It.Is(x => x.Equals(deviceId, StringComparison.Ordinal)), + It.Is(x => x.Equals(moduleName, StringComparison.Ordinal)), + It.Is(x => x == method), + It.IsAny())) + .ThrowsAsync(new Exception("")); + + // Act + var result = async () => await service.ExecuteCustomCommandC2DMethod(deviceId, moduleName, method); + + // Assert + _ = await result.Should().ThrowAsync(); + this.mockRepository.VerifyAll(); + } + [Test] public async Task GetEdgeDeviceLogsMustReturnLogsWhen200IsReturned() { @@ -1057,7 +1111,6 @@ public async Task GetEdgeDeviceLogsMustReturnLogsWhen200IsReturned() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -1065,7 +1118,7 @@ public async Task GetEdgeDeviceLogsMustReturnLogsWhen200IsReturned() var payload = JsonConvert.SerializeObject(new { - schemaVersion = edgeModule.Version, + schemaVersion = "1.0", items = new[] { new @@ -1117,7 +1170,6 @@ public async Task GetEdgeDeviceLogsMustReturnEmptyLogsWhenNot200IsReturned() var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -1125,7 +1177,7 @@ public async Task GetEdgeDeviceLogsMustReturnEmptyLogsWhenNot200IsReturned() var payload = JsonConvert.SerializeObject(new { - schemaVersion = edgeModule.Version, + schemaVersion = "1.0", items = new[] { new @@ -1177,7 +1229,6 @@ public async Task GetEdgeDeviceLogsShouldInternalServerErrorExceptionWhenIssueOc var edgeModule = new IoTEdgeModule { - Version = "1.0", ModuleName = Guid.NewGuid().ToString() }; @@ -1185,7 +1236,7 @@ public async Task GetEdgeDeviceLogsShouldInternalServerErrorExceptionWhenIssueOc var payload = JsonConvert.SerializeObject(new { - schemaVersion = edgeModule.Version, + schemaVersion = "1.0", items = new[] { new diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs index bb45e8259..f08f2de9f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs @@ -18,6 +18,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using System.Threading.Tasks; using System.Collections.Generic; using AzureIoTHub.Portal.Server.Exceptions; + using FluentAssertions; [TestFixture] public class EdgeDeviceServiceTest @@ -267,7 +268,7 @@ public void WhenEdgeDeviceIsNullUpdateEdgeDeviceShouldThrowArgumentNullException _ = Assert.ThrowsAsync(() => edgeDeviceService.UpdateEdgeDevice(null)); } - [TestCase("RestartModule", /*lang=json,strict*/ "{\"id\":\"aaa\",\"schemaVersion\":null}")] + [TestCase("RestartModule", /*lang=json,strict*/ "{\"id\":\"aaa\",\"schemaVersion\":\"1.0\"}")] public async Task ExecuteMethodShouldExecuteC2DMethod(string methodName, string expected) { // Arrange @@ -292,7 +293,7 @@ public async Task ExecuteMethodShouldExecuteC2DMethod(string methodName, string }); // Act - _ = await edgeDeviceService.ExecuteModuleMethod(edgeModule, deviceId, methodName); + _ = await edgeDeviceService.ExecuteModuleMethod(deviceId, edgeModule.ModuleName, methodName); // Assert this.mockRepository.VerifyAll(); @@ -307,7 +308,97 @@ public void WhenEdgeModuleIsNullExecuteMethodShouldThrowArgumentNullException(st var deviceId = Guid.NewGuid().ToString(); // Assert - _ = Assert.ThrowsAsync(() => edgeDeviceService.ExecuteModuleMethod(null, deviceId, methodName)); + _ = Assert.ThrowsAsync(() => edgeDeviceService.ExecuteModuleMethod(deviceId, null, methodName)); + } + + [TestCase("test")] + public async Task ExecuteModuleCommand(string commandName) + { + // Arrange + var edgeDeviceService = CreateEdgeDeviceService(); + + var edgeModule = new IoTEdgeModule + { + ModuleName = "aaa", + }; + + var deviceId = Guid.NewGuid().ToString(); + + _ = this.mockDeviceService.Setup(c => c.ExecuteCustomCommandC2DMethod( + It.Is(x => x == deviceId), + It.Is(x => x == edgeModule.ModuleName), + It.Is(x => + x.MethodName == commandName + ))) + .ReturnsAsync(new CloudToDeviceMethodResult + { + Status = 200 + }); + + // Act + var result = await edgeDeviceService.ExecuteModuleCommand(deviceId, edgeModule.ModuleName, commandName); + + // Assert + Assert.AreEqual(200, result.Status); + this.mockRepository.VerifyAll(); + } + + [TestCase("test")] + public void WhenDeviceIdIsNullExecuteModuleCommandShouldThrowArgumentNullException(string commandName) + { + // Arrange + var edgeDeviceService = CreateEdgeDeviceService(); + + var edgeModule = new IoTEdgeModule + { + ModuleName = "aaa", + }; + + var deviceId = string.Empty; + + // Act + var result = async () => await edgeDeviceService.ExecuteModuleCommand(deviceId, edgeModule.ModuleName, commandName); + + // Assert + _ = result.Should().ThrowAsync(); + this.mockRepository.VerifyAll(); + } + + [TestCase("test")] + public void WhenModuleIsNullExecuteModuleCommandShouldThrowArgumentNullException(string commandName) + { + // Arrange + var edgeDeviceService = CreateEdgeDeviceService(); + + var deviceId = Guid.NewGuid().ToString(); + + // Act + var result = async () => await edgeDeviceService.ExecuteModuleCommand(deviceId, null, commandName); + + // Assert + _ = result.Should().ThrowAsync(); + this.mockRepository.VerifyAll(); + } + + [Test] + public void WhenCommandNameIsNullExecuteModuleCommandShouldThrowArgumentNullException() + { + // Arrange + var edgeDeviceService = CreateEdgeDeviceService(); + + var deviceId = string.Empty; + + var edgeModule = new IoTEdgeModule + { + ModuleName = "aaa", + }; + + // Act + var result = async () => await edgeDeviceService.ExecuteModuleCommand(deviceId, edgeModule.ModuleName, null); + + // Assert + _ = result.Should().ThrowAsync(); + this.mockRepository.VerifyAll(); } [Test] diff --git a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor index ee7c18db8..33d99cc87 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor @@ -1,5 +1,7 @@ @page "/edge/devices/{deviceId}" + @using AzureIoTHub.Portal.Models.v10 +@using AzureIoTHub.Portal.Shared.Models.v10; @attribute [Authorize] @inject NavigationManager NavigationManager @@ -132,22 +134,23 @@ - Module Name - Version Status @context.ModuleName - @context.Version @context.Status - + logs - reboot + reboot + @foreach (var command in context.Commands) + { + @command.Name + } @@ -226,6 +229,17 @@ await LoadModel(edgeDevice.ModelId); + foreach (var edgeModelModule in edgeModel.EdgeModules) + { + foreach (var item in edgeDevice.Modules) + { + if (item.ModuleName.Equals(edgeModelModule.ModuleName, StringComparison.Ordinal)) + { + item.Commands = edgeModelModule.Commands; + } + } + } + TagList = await DeviceTagSettingsClientService.GetDeviceTags(); } catch (ProblemDetailsException exception) @@ -283,15 +297,13 @@ } } - public async Task OnMethod(IoTEdgeModule module, string methodName) + public async Task OnMethod(string moduleName, string methodName) { isProcessing = true; try { - //var result = await Http.PostAsJsonAsync($"api/edge/devices/{edgeDevice.DeviceId}/{module.ModuleName}/{methodName}", module); - - var c2dResult = await EdgeDeviceClientService.ExecuteModuleMethod(edgeDevice.DeviceId, module, methodName); + var c2dResult = await EdgeDeviceClientService.ExecuteModuleMethod(edgeDevice.DeviceId, moduleName, methodName); if (c2dResult.Status == 200) { diff --git a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceListPage.razor b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceListPage.razor index ba618a630..dc3f2ce9a 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceListPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceListPage.razor @@ -48,6 +48,7 @@ + @@ -65,13 +66,17 @@ - ID + + Device ID Allowed Nb devices See details Delete + + + @context.DeviceId diff --git a/src/AzureIoTHub.Portal/Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor b/src/AzureIoTHub.Portal/Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor index 723aca188..3c1675669 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor @@ -54,7 +54,6 @@ public IoTEdgeModule Module { get; set; } private string currentModuleName; - private string currentVersion; private string currentImageUri; private List currentEnvironmentVariables = new(); @@ -69,7 +68,6 @@ IsLoading = true; currentModuleName = Module.ModuleName; - currentVersion = Module.Version; currentImageUri = Module.ImageURI; currentEnvironmentVariables = new List(Module.EnvironmentVariables.ToArray()); currentModuleIdentityTwinSettings = new List(Module.ModuleIdentityTwinSettings.ToArray()); @@ -81,7 +79,6 @@ public void Submit() { Module.ModuleName = currentModuleName; - Module.Version = currentVersion; Module.ImageURI = currentImageUri; Module.EnvironmentVariables = new List(currentEnvironmentVariables.ToArray()); Module.ModuleIdentityTwinSettings = new List(currentModuleIdentityTwinSettings.ToArray()); diff --git a/src/AzureIoTHub.Portal/Client/Services/EdgeDeviceClientService.cs b/src/AzureIoTHub.Portal/Client/Services/EdgeDeviceClientService.cs index 0827c35a8..8ff7a3349 100644 --- a/src/AzureIoTHub.Portal/Client/Services/EdgeDeviceClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/EdgeDeviceClientService.cs @@ -55,9 +55,9 @@ public async Task> GetEdgeDeviceLogs(string deviceId, IoT return await response.Content.ReadFromJsonAsync>(); } - public async Task ExecuteModuleMethod(string deviceId, IoTEdgeModule edgeModule, string methodName) + public async Task ExecuteModuleMethod(string deviceId, string moduleName, string methodName) { - var response = await this.http.PostAsJsonAsync($"api/edge/devices/{deviceId}/{edgeModule.ModuleName}/{methodName}", edgeModule); + var response = await this.http.PostAsJsonAsync($"api/edge/devices/{deviceId}/{moduleName}/{methodName}", null); return await response.Content.ReadFromJsonAsync(); } diff --git a/src/AzureIoTHub.Portal/Client/Services/IEdgeDeviceClientService.cs b/src/AzureIoTHub.Portal/Client/Services/IEdgeDeviceClientService.cs index ca070d0ef..4fb17e009 100644 --- a/src/AzureIoTHub.Portal/Client/Services/IEdgeDeviceClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/IEdgeDeviceClientService.cs @@ -23,6 +23,7 @@ public interface IEdgeDeviceClientService Task> GetEdgeDeviceLogs(string deviceId, IoTEdgeModule edgeModule); - Task ExecuteModuleMethod(string deviceId, IoTEdgeModule edgeModule, string methodName); + Task ExecuteModuleMethod(string deviceId, string moduleName, string methodName); + } } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/EdgeDevicesController.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/EdgeDevicesController.cs index 4c6588c3c..682b4f486 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/EdgeDevicesController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/EdgeDevicesController.cs @@ -157,13 +157,13 @@ public async Task> GetCredentials(string dev /// /// Executes the module method on the IoT Edge device. /// - /// The edge module. + /// The edge module name. /// The device identifier. /// Name of the method. - [HttpPost("{deviceId}/{moduleId}/{methodName}", Name = "POST Execute module command")] - public async Task ExecuteModuleMethod(IoTEdgeModule edgeModule, string deviceId, string methodName) + [HttpPost("{deviceId}/{moduleName}/{methodName}", Name = "POST Execute module command")] + public async Task ExecuteModuleMethod(string deviceId, string moduleName, string methodName) { - return await this.edgeDevicesService.ExecuteModuleMethod(edgeModule, deviceId, methodName); + return await this.edgeDevicesService.ExecuteModuleMethod(deviceId, moduleName, methodName); } /// diff --git a/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs b/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs index 14225aa04..3e98f83b2 100644 --- a/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs +++ b/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs @@ -150,7 +150,6 @@ public static IoTEdgeModule CreateGatewayModule(Configuration config, JProperty ModuleName = module.Name, ImageURI = module.Value["settings"]["image"]?.Value(), Status = module.Value["status"]?.Value(), - Version = module.Value["version"]?.Value(), }; foreach (var item in GetEnvironmentVariables(module)) diff --git a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs index d76cf9b89..fe0634306 100644 --- a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs +++ b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs @@ -190,14 +190,15 @@ public static IReadOnlyCollection RetrieveModuleList(Twin twin) ModuleName = property.Key }; - if (propertyObject.TryGetValue("status", out var status)) + if (propertyObject.TryGetValue("settings", out var moduleSettings)) { - module.Status = status.Value(); + var setting = moduleSettings.ToObject>(); + module.ImageURI = setting["image"]; } - if (propertyObject.TryGetValue("version", out var version)) + if (propertyObject.TryGetValue("status", out var status)) { - module.Version = version.Value(); + module.Status = status.Value(); } list.Add(module); diff --git a/src/AzureIoTHub.Portal/Server/Mappers/EdgeDeviceMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/EdgeDeviceMapper.cs index 4e04324e5..33d33fad3 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/EdgeDeviceMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/EdgeDeviceMapper.cs @@ -24,7 +24,8 @@ public IoTEdgeListItem CreateEdgeDeviceListItem(Twin deviceTwin) { DeviceId = deviceTwin?.DeviceId, Status = deviceTwin?.Status.ToString(), - NbDevices = DeviceHelper.RetrieveConnectedDeviceCount(deviceTwin) + NbDevices = DeviceHelper.RetrieveConnectedDeviceCount(deviceTwin), + ImageUrl = this.deviceModelImageManager.ComputeImageUri(DeviceHelper.RetrieveTagValue(deviceTwin, nameof(IoTEdgeDevice.ModelId))) }; } diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs index b145d8d4b..f48bb7e7e 100644 --- a/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs @@ -403,6 +403,26 @@ public async Task ExecuteC2DMethod(string deviceId, C } } + /// + /// C2DMethod for custom command. + /// + /// the deviceId. + /// the module name. + /// the C2DMethod. + /// + /// + public async Task ExecuteCustomCommandC2DMethod(string deviceId, string moduleName, CloudToDeviceMethod method) + { + try + { + return await this.serviceClient.InvokeDeviceMethodAsync(deviceId, moduleName, method); + } + catch (Exception e) + { + throw new InternalServerErrorException($"Unable to execute the cloud to device method {method.MethodName} on the device with id {deviceId}", e); + } + } + /// /// Get edge device logs /// @@ -417,7 +437,7 @@ public async Task> GetEdgeDeviceLogs(string device var payload = JsonConvert.SerializeObject(new { - schemaVersion = edgeModule.Version, + schemaVersion = "1.0", items = new[] { new diff --git a/src/AzureIoTHub.Portal/Server/Services/EdgeDevicesService.cs b/src/AzureIoTHub.Portal/Server/Services/EdgeDevicesService.cs index c1bd98583..03754a792 100644 --- a/src/AzureIoTHub.Portal/Server/Services/EdgeDevicesService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/EdgeDevicesService.cs @@ -170,25 +170,26 @@ public async Task UpdateEdgeDevice(IoTEdgeDevice edgeDevice) /// /// Executes the module method on the IoT Edge device. /// - /// + /// /// /// /// - public async Task ExecuteModuleMethod(IoTEdgeModule edgeModule, string deviceId, string methodName) + public async Task ExecuteModuleMethod(string deviceId, string moduleName, string methodName) { - ArgumentNullException.ThrowIfNull(edgeModule, nameof(edgeModule)); + ArgumentNullException.ThrowIfNull(moduleName, nameof(moduleName)); + + if (!methodName.Equals("RestartModule", StringComparison.Ordinal)) + { + return await ExecuteModuleCommand(deviceId, moduleName, methodName); + } var method = new CloudToDeviceMethod(methodName); - var payload = string.Empty; - if (methodName == "RestartModule") + var payload = JsonConvert.SerializeObject(new { - payload = JsonConvert.SerializeObject(new - { - id = edgeModule.ModuleName, - schemaVersion = edgeModule.Version - }); - } + id = moduleName, + schemaVersion = "1.0" + }); _ = method.SetPayloadJson(payload); @@ -201,6 +202,33 @@ public async Task ExecuteModuleMethod(IoTEdgeModule edgeModule, strin }; } + /// + /// Execute the custom module command. + /// + /// the device identifier. + /// the module name. + /// the command name. + /// + public async Task ExecuteModuleCommand(string deviceId, string moduleName, string commandName) + { + ArgumentNullException.ThrowIfNull(deviceId, nameof(deviceId)); + ArgumentNullException.ThrowIfNull(moduleName, nameof(moduleName)); + ArgumentNullException.ThrowIfNull(commandName, nameof(commandName)); + + var method = new CloudToDeviceMethod(commandName); + var payload = "{}"; + + _ = method.SetPayloadJson(payload); + + var result = await this.devicesService.ExecuteCustomCommandC2DMethod(deviceId,moduleName, method); + + return new C2Dresult() + { + Payload = result.GetPayloadAsJson(), + Status = result.Status + }; + } + /// /// Gets the IoT Edge device enrollement credentials. /// diff --git a/src/AzureIoTHub.Portal/Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal/Server/Services/EdgeModelService.cs index 480e1e635..9f5904683 100644 --- a/src/AzureIoTHub.Portal/Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/EdgeModelService.cs @@ -89,10 +89,13 @@ public async Task GetEdgeModel(string modelId) var query = await this.tableClientFactory .GetEdgeDeviceTemplates() .GetEntityAsync(DefaultPartitionKey, modelId); + var modules = await this.configService.GetConfigModuleList(modelId); + var commands = this.tableClientFactory.GetEdgeModuleCommands() .Query(c => c.PartitionKey == modelId) .ToArray(); + return this.edgeDeviceModelMapper.CreateEdgeDeviceModel(query.Value, modules, commands); } catch (RequestFailedException e) diff --git a/src/AzureIoTHub.Portal/Server/Services/IDeviceService.cs b/src/AzureIoTHub.Portal/Server/Services/IDeviceService.cs index 2d748613a..45969d89e 100644 --- a/src/AzureIoTHub.Portal/Server/Services/IDeviceService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/IDeviceService.cs @@ -25,6 +25,8 @@ public interface IDeviceService Task ExecuteC2DMethod(string deviceId, CloudToDeviceMethod method); + Task ExecuteCustomCommandC2DMethod(string deviceId, string moduleName, CloudToDeviceMethod method); + Task DeleteDevice(string deviceId); Task> GetAllDevice( diff --git a/src/AzureIoTHub.Portal/Server/Services/IEdgeDevicesService.cs b/src/AzureIoTHub.Portal/Server/Services/IEdgeDevicesService.cs index 16222e921..1e8407bdd 100644 --- a/src/AzureIoTHub.Portal/Server/Services/IEdgeDevicesService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/IEdgeDevicesService.cs @@ -24,8 +24,10 @@ PaginationResult GetEdgeDevicesPage(PaginationResult edge Task UpdateEdgeDevice(IoTEdgeDevice edgeDevice); - Task ExecuteModuleMethod(IoTEdgeModule edgeModule, string deviceId, string methodName); + Task ExecuteModuleMethod(string deviceId, string moduleName, string methodName); Task GetEdgeDeviceCredentials(string edgeDeviceId); + + Task ExecuteModuleCommand(string deviceId, string moduleName, string commandName); } } diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeListItem.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeListItem.cs index b3fa97b46..e8e5561a8 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeListItem.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeListItem.cs @@ -3,6 +3,7 @@ namespace AzureIoTHub.Portal.Models.v10 { + using System; using System.ComponentModel.DataAnnotations; /// @@ -25,5 +26,10 @@ public class IoTEdgeListItem /// The number of devices connected on the IoT Edge. /// public int NbDevices { get; set; } + + /// + /// The device model image Url. + /// + public Uri ImageUrl { get; set; } } } diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeModule.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeModule.cs index 1c226709e..084779f93 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeModule.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/IoTEdgeModule.cs @@ -18,11 +18,6 @@ public class IoTEdgeModule [Required(ErrorMessage = "The device model name is required.")] public string ModuleName { get; set; } - /// - /// The module configuration version. - /// - public string Version { get; set; } - /// /// the device image URI. ///