diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index aba1b62..79887d6 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -56,7 +56,7 @@ jobs: - name: Build run: dotnet build --no-restore --configuration release - name: Test - run: dotnet test --no-build --verbosity normal --configuration release --logger "trx;LogFileName=${{ matrix.platform }}-test-results.trx" + run: dotnet test Kepware.Api.Test/Kepware.Api.Test.csproj --no-build --verbosity normal --configuration Release --logger "trx;LogFileName=${{ matrix.platform }}-test-results.trx" - name: Publish Test Report (${{ matrix.platform }}) if: ${{ github.event_name == 'pull_request' }} uses: dorny/test-reporter@v1 diff --git a/Kepware-ConfigAPI-SDK-dotnet.sln b/Kepware-ConfigAPI-SDK-dotnet.sln index fde41f8..4f6dcf0 100644 --- a/Kepware-ConfigAPI-SDK-dotnet.sln +++ b/Kepware-ConfigAPI-SDK-dotnet.sln @@ -50,6 +50,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docfx", "docfx", "{EF3D2F75 docs\docfx\toc.yml = docs\docfx\toc.yml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kepware.Api.TestIntg", "Kepware.Api.TestIntg\Kepware.Api.TestIntg.csproj", "{5FF0BFA8-5429-4823-9B18-05EB2E6779AE}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{457CB96C-D60B-4994-B87C-BCDBF4035D58}" ProjectSection(SolutionItems) = preProject docs\docfx\docs\toc.yml = docs\docfx\docs\toc.yml @@ -77,6 +79,10 @@ Global {E5F9DE9E-F9F2-4683-A7A9-ACE8501F7566}.Debug|Any CPU.Build.0 = Debug|Any CPU {E5F9DE9E-F9F2-4683-A7A9-ACE8501F7566}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5F9DE9E-F9F2-4683-A7A9-ACE8501F7566}.Release|Any CPU.Build.0 = Release|Any CPU + {5FF0BFA8-5429-4823-9B18-05EB2E6779AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FF0BFA8-5429-4823-9B18-05EB2E6779AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FF0BFA8-5429-4823-9B18-05EB2E6779AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FF0BFA8-5429-4823-9B18-05EB2E6779AE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Kepware.Api.Test/ApiClient/GetProductInfo.cs b/Kepware.Api.Test/ApiClient/GetProductInfo.cs index 7959f3e..653d954 100644 --- a/Kepware.Api.Test/ApiClient/GetProductInfo.cs +++ b/Kepware.Api.Test/ApiClient/GetProductInfo.cs @@ -36,6 +36,7 @@ public async Task GetProductInfoAsync_ShouldReturnProductInfo_WhenApiRespondsSuc #region GetProductInfoAsync - SupportsJsonProjectLoadService + //TODO: Add more test cases for TKS versions as well. Different product name [Theory] [InlineData("KEPServerEX", "12", 6, 17, true)] // Supports JSON Project Load Service (6.17+) [InlineData("KEPServerEX", "12", 6, 16, false)] // Does not support it (6.16) diff --git a/Kepware.Api.Test/ApiClient/LoadEntity.cs b/Kepware.Api.Test/ApiClient/LoadEntity.cs index a0bf132..08bf73c 100644 --- a/Kepware.Api.Test/ApiClient/LoadEntity.cs +++ b/Kepware.Api.Test/ApiClient/LoadEntity.cs @@ -196,7 +196,7 @@ public async Task LoadEntityAsync_ShouldReturnNull_OnHttpRequestException() #endregion #region LoadEntityAsync - Device with DynamicProperties - + // TODO: Add these types of test for other entities (Device, TagGroup, Tag, etc.) [Fact] public async Task LoadEntityAsync_ShouldReturnDevice_WithCorrectDynamicProperties() { diff --git a/Kepware.Api.TestIntg/ApiClient/AdminModelTests.cs b/Kepware.Api.TestIntg/ApiClient/AdminModelTests.cs new file mode 100644 index 0000000..b1f0b40 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/AdminModelTests.cs @@ -0,0 +1,108 @@ +using Kepware.Api.Model; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; +using System.Net.Http.Json; +using Kepware.Api.Model.Admin; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class AdminModelTests : TestApiClientBase + { + + #region GetAdminSettingsAsync Tests + + [Fact] + public async Task GetAdminSettingsAsync_ShouldReturnAdminSettings_WhenApiRespondsSuccessfully() + { + + // Act + var result = await _kepwareApiClient.Admin.GetAdminSettingsAsync(); + + // Assert + result.ShouldNotBeNull(); + result.EventLogConnectionPort.ShouldNotBe(default(int)); + result.EventLogMaxRecords.ShouldNotBe(default(int)); + if (_productInfo.ProductId == "013") + { + result.LicenseServer.ShouldNotBeNull(); + result.LicenseServer.RecheckIntervalMinutes.ShouldNotBe(default(int)); + result.LicenseServer.Enable.ShouldNotBeNull(); + } + + } + + [Fact] + public async Task GetAdminSettingsAsync_ShouldReturnNull_WhenApiReturnsUnauthorized() + { + + // Act + var result = await _badCredKepwareApiClient.Admin.GetAdminSettingsAsync(); + + // Assert + result.ShouldBeNull(); + + } + + #endregion + + #region SetAdminSettingsAsync Tests + + [Fact] + public async Task SetAdminSettingsAsync_ShouldReturnTrue_WhenUpdateSuccessful() + { + // Arrange + var newSettings = new AdminSettings(); + newSettings.EventLogMaxRecords = new Random().Next(10000, 30001); + if (_productInfo.ProductId != "013") + { + newSettings.LicenseServer.Port = new Random().Next(10000, 30001); + } + + // Act + var result = await _kepwareApiClient.Admin.SetAdminSettingsAsync(newSettings); + + // Assert + result.ShouldBeTrue(); + + } + + [Fact] + public async Task SetAdminSettingsAsync_ShouldReturnFalse_WhenUpdateFails() + { + // Arrange + var newSettings = new AdminSettings(); + newSettings.EventLogConnectionPort = 1000; + + + // Act + var result = await _kepwareApiClient.Admin.SetAdminSettingsAsync(newSettings); + + // Assert + result.ShouldBeFalse(); + } + + [Fact] + public async Task SetAdminSettingsAsync_ShouldThrowException_WhenApiReturnsUnauthorized() + { + // Arrange + var newSettings = new AdminSettings(); + newSettings.EventLogMaxRecords = new Random().Next(10000, 30001); + + // Act and Assert + await Should.ThrowAsync(async () => + { + await _badCredKepwareApiClient.Admin.SetAdminSettingsAsync(newSettings); + }); + + } + + #endregion + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/AutomaticTagGenerationAsyncTests.cs b/Kepware.Api.TestIntg/ApiClient/AutomaticTagGenerationAsyncTests.cs new file mode 100644 index 0000000..dabfadd --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/AutomaticTagGenerationAsyncTests.cs @@ -0,0 +1,147 @@ +using Kepware.Api.Model; +using Kepware.Api.Model.Services; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System; +using System.Net; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using Xunit.Extensions.Ordering; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class AutomaticTagGenerationAsyncTests : TestApiClientBase + { + private const string UNIT_TEST_CHANNEL = "unitTestChannel"; + private const string UNIT_TEST_DEVICE = "unitTestDevice"; + private const string ENDPOINT_TAG_GENERATION = $"/config/v1/project/channels/{UNIT_TEST_CHANNEL}/devices/{UNIT_TEST_DEVICE}/services/TagGeneration"; + private const string JOB_ENDPOINT = $"/config/v1/project/channels/{UNIT_TEST_CHANNEL}/devices/{UNIT_TEST_DEVICE}/services/TagGeneration/jobs/job123"; + + [Fact] + public async Task AutomaticTagGenerationAsync_ShouldReturnKepServerJobPromise_WhenApiResponseIsInvalid() + { + // Arrange + // Create channel that doesn't support ATG + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + + // Act + var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(channel.Name, device.Name, TimeSpan.FromSeconds(30)); + // Assert + result.ShouldNotBeNull(); + //result.Endpoint.ShouldBe(ENDPOINT_TAG_GENERATION); + result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30)); + + // Clean up + await DeleteAllChannelsAsync(); + } + + // [Fact] + // public async Task AutomaticTagGenerationAsync_ShouldThrowException_WhenHttpClientThrowsException() + // { + // // Arrange + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Put, $"{TEST_ENDPOINT}{ENDPOINT_TAG_GENERATION}") + // .Throws(new HttpRequestException("Network error")); + + // // Act & Assert + // await Should.ThrowAsync(async () => + // { + // await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(UNIT_TEST_CHANNEL, UNIT_TEST_DEVICE, TimeSpan.FromSeconds(30)); + // }); + // } + + // [Fact] + // public async Task AutomaticTagGenerationAsync_ShouldReturnSuccess_WhenJobCompletesSuccessfullyAfterFirstGet() + // { + // // Arrange + // var jobResponse = new JobResponseMessage { ResponseStatusCode = (int)ApiResponseCode.Accepted, JobId = JOB_ENDPOINT }; + // var jobStatus = new JobStatusMessage { Completed = true }; + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Put, $"{TEST_ENDPOINT}{ENDPOINT_TAG_GENERATION}") + // .ReturnsResponse(HttpStatusCode.Accepted, JsonSerializer.Serialize(jobResponse), "application/json"); + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}{JOB_ENDPOINT}") + // .ReturnsResponse(HttpStatusCode.OK, JsonSerializer.Serialize(jobStatus), "application/json"); + + // // Act + // var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(UNIT_TEST_CHANNEL, UNIT_TEST_DEVICE, TimeSpan.FromSeconds(30)); + // var completionResult = await result.AwaitCompletionAsync(); + + // // Assert + // completionResult.Value.ShouldBeTrue(); + // completionResult.IsSuccess.ShouldBeTrue(); + // } + + [Fact] + public async Task AutomaticTagGenerationAsync_ShouldReturnSuccess_WhenJobCompletesSuccessfully() + { + // Arrange + var channel = await AddTestChannel(driver: "Allen-Bradley ControlLogix Ethernet"); + var device = await AddAtgTestDevice(channel); + + // Act + var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(channel.Name, device.Name, TimeSpan.FromSeconds(30)); + + // Assert + result.ShouldNotBeNull(); + result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30)); + + // Wait for job completion + var completionResult = await result.AwaitCompletionAsync(); + + // Assert + completionResult.Value.ShouldBeTrue(); + completionResult.IsSuccess.ShouldBeTrue(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + // [Fact] + // public async Task AutomaticTagGenerationAsync_ShouldReturnFailure_WhenJobFailsAfterFirstGet() + // { + // // Arrange + // var jobResponse = new JobResponseMessage { ResponseStatusCode = (int)ApiResponseCode.Accepted, JobId = JOB_ENDPOINT }; + // var jobStatus = new JobStatusMessage { Completed = false }; + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Put, $"{TEST_ENDPOINT}{ENDPOINT_TAG_GENERATION}") + // .ReturnsResponse(HttpStatusCode.Accepted, JsonSerializer.Serialize(jobResponse), "application/json"); + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}{JOB_ENDPOINT}") + // .ReturnsResponse(HttpStatusCode.OK, JsonSerializer.Serialize(jobStatus), "application/json"); + + // // Act + // var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(UNIT_TEST_CHANNEL, UNIT_TEST_DEVICE, TimeSpan.FromSeconds(1)); + // var completionResult = await result.AwaitCompletionAsync(TimeSpan.FromMilliseconds(100)); + + // // Assert + // completionResult.Value.ShouldBeFalse(); + // completionResult.IsSuccess.ShouldBeFalse(); + // } + + // [Fact] + // public async Task AutomaticTagGenerationAsync_ShouldReturnFailure_WhenJobFailsAfterMultipleGets() + // { + // // Arrange + // var jobResponse = new JobResponseMessage { ResponseStatusCode = (int)ApiResponseCode.Accepted, JobId = JOB_ENDPOINT }; + // var jobStatusIncomplete = new JobStatusMessage { Completed = false }; + + // var jobStatusFailed = new JobStatusMessage { Completed = true, Message = "Job failed" }; + + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Put, $"{TEST_ENDPOINT}{ENDPOINT_TAG_GENERATION}") + // .ReturnsResponse(HttpStatusCode.Accepted, JsonSerializer.Serialize(jobResponse), "application/json"); + // _httpMessageHandlerMock.SetupSequenceRequest(HttpMethod.Get, $"{TEST_ENDPOINT}{JOB_ENDPOINT}") + // .ReturnsResponse(HttpStatusCode.OK, JsonSerializer.Serialize(jobStatusIncomplete), "application/json") + // .ReturnsResponse(HttpStatusCode.OK, JsonSerializer.Serialize(jobStatusIncomplete), "application/json") + // .ReturnsResponse(HttpStatusCode.ServiceUnavailable, JsonSerializer.Serialize(jobStatusFailed), "application/json"); + + // // Act + // var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(UNIT_TEST_CHANNEL, UNIT_TEST_DEVICE, TimeSpan.FromSeconds(5)); + // var completionResult = await result.AwaitCompletionAsync(TimeSpan.FromMilliseconds(100)); + + // // Assert + // completionResult.Value.ShouldBeFalse(); + // completionResult.IsSuccess.ShouldBeFalse(); + // } + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/GetProductInfo.cs b/Kepware.Api.TestIntg/ApiClient/GetProductInfo.cs new file mode 100644 index 0000000..1fc284c --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/GetProductInfo.cs @@ -0,0 +1,36 @@ +using Kepware.Api.Model; +using Moq; +using Moq.Contrib.HttpClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class GetProductInfo : TestApiClientBase + { + + [Fact] + public async Task GetProductInfoAsync_ShouldReturnProductInfo_WhenApiRespondsSuccessfully() + { + + // Act + var result = await _kepwareApiClient.GetProductInfoAsync(); + + // Assert + Assert.NotNull(result); + Assert.Equal(_productInfo.ProductId, result.ProductId); + Assert.Equal(_productInfo.ProductName, result.ProductName); + Assert.Equal(_productInfo.ProductVersion, result.ProductVersion); + Assert.Equal(_productInfo.ProductVersionMajor, result.ProductVersionMajor); + Assert.Equal(_productInfo.ProductVersionMinor, result.ProductVersionMinor); + Assert.Equal(_productInfo.ProductVersionBuild, result.ProductVersionBuild); + Assert.Equal(_productInfo.ProductVersionPatch, result.ProductVersionPatch); + + } + + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/InsertTests.cs b/Kepware.Api.TestIntg/ApiClient/InsertTests.cs new file mode 100644 index 0000000..53e7c64 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/InsertTests.cs @@ -0,0 +1,106 @@ +using Kepware.Api.Model; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; + +namespace Kepware.Api.TestIntg.ApiClient; + +public class InsertTests : TestApiClientBase +{ + [Fact] + public async Task Insert_Item_WhenSuccessful_ShouldReturnTrue() + { + // Arrange + var channel = CreateTestChannel(); + + // Act + var result = await _kepwareApiClient.GenericConfig.InsertItemAsync(channel); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Insert_Item_WithHttpError_ShouldReturnFalse() + { + // Arrange + var channel = CreateTestChannel(); + channel.SetDynamicProperty("InvalidProperty","InvalidValue"); + + // Act + var result = await _kepwareApiClient.GenericConfig.InsertItemAsync(channel); + + // Assert + result.ShouldBeFalse(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Insert_MultipleItems_WhenSuccessful_ShouldReturnAllTrue() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tags = CreateSimulatorTestTags(); + + // Act + var results = await _kepwareApiClient.GenericConfig.InsertItemsAsync(tags, owner: device); + + // Assert + results.ShouldAllBe(r => r == true); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Insert_MultipleItems_WithPartialSuccess_ShouldReturnMixedResults() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tags = CreateSimulatorTestTags(); + tags[1].TagAddress = "InvalidAddress"; + + // Act + var results = await _kepwareApiClient.GenericConfig.InsertItemsAsync(tags, owner: device); + + // Assert + results.Length.ShouldBe(2); + results[0].ShouldBeTrue(); + results[1].ShouldBeFalse(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Insert_MultipleItems_WithUnsupportedDriver_ShouldSkipItems() + { + // Arrange + await ConfigureToServeDrivers(); + var channel1 = CreateTestChannel("Channel1", "UnsupportedDriver"); + var channel2 = CreateTestChannel("Channel2", "Simulator"); + var channels = new List { channel1, channel2 }; + + // Act + var results = await _kepwareApiClient.GenericConfig.InsertItemsAsync(channels); + + // Assert + results.Length.ShouldBe(1); // Only the Simulator channel should be inserted + results[0].ShouldBeTrue(); + + // Clean up + await DeleteAllChannelsAsync(); + + } +} \ No newline at end of file diff --git a/Kepware.Api.TestIntg/ApiClient/LoadEntity.cs b/Kepware.Api.TestIntg/ApiClient/LoadEntity.cs new file mode 100644 index 0000000..aea049c --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/LoadEntity.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Kepware.Api.Model; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using Xunit; + +namespace Kepware.Api.TestIntg.ApiClient +{ + [TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")] + public class LoadEntityTests : TestApiClientBase + { + #region LoadEntityAsync - Channel (Collection) + + [Fact] + public async Task LoadEntityAsync_ShouldReturnChannelCollection_WhenApiRespondsSuccessfully() + { + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(); + + // Assert + Assert.NotNull(result); + result.ShouldBeOfType(); + + } + + #endregion + + #region LoadEntityAsync - Single Channel + + [Fact] + public async Task LoadEntityAsync_ShouldReturnChannel_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + + // Act + + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync(channel.Name); + + // Assert + Assert.NotNull(result); + Assert.Equal(channel.Name, result.Name); + Assert.Equal(channel.Description, result.Description); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - Device (Collection) + + [Fact] + public async Task LoadEntityAsync_ShouldReturnDeviceCollection_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + + var devicesList = new List(); + devicesList.Add(CreateTestDevice(channel, "TestDevice1")); + devicesList.Add(CreateTestDevice(channel, "TestDevice2")); + foreach (var device in devicesList) + { + await _kepwareApiClient.Project.Devices.GetOrCreateDeviceAsync(channel, device.Name); + } + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync([channel.Name]); + + // Assert + Assert.NotNull(result); + Assert.Equal(2, result.Count); + Assert.Contains(result, d => d.Name == "TestDevice1"); + Assert.Contains(result, d => d.Name == "TestDevice2"); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - Single Device + + [Fact] + public async Task LoadEntityAsync_ShouldReturnDevice_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync(device.Name, channel); + + // Assert + Assert.NotNull(result); + result.Name.ShouldNotBeNull(); + Assert.Equal(channel.Name, result.Owner?.Name); + + // Cleanup + await DeleteAllChannelsAsync(); + + } + + #endregion + + #region LoadEntityAsync - Error Handling + + [Fact] + public async Task LoadEntityAsync_ShouldReturnNull_WhenApiReturns404() + { + // Act + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync("InvalidChannel"); + + // Assert + Assert.Null(result); + } + + #endregion + + // TODO: Add these types of test for other entities (Device, TagGroup, Tag, etc.) + #region LoadEntityAsync - Device with DynamicProperties + + [Fact] + public async Task LoadEntityAsync_ShouldReturnDevice_WithCorrectDynamicProperties() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync(device.Name, channel); + + // Assert + Assert.NotNull(result); + Assert.Equal(device.Name, result.Name); + Assert.Equal(device.Description, result.Description); + Assert.Equal(device.Owner!.Name, result.Owner?.Name); + + // Check if DynamicProperties are set correctly + // Expected defaults based on device creation + Assert.Equal(1, result.GetDynamicProperty("servermain.DEVICE_ID_FORMAT")); + Assert.Equal("1", result.GetDynamicProperty("servermain.DEVICE_ID_STRING")); + Assert.Equal(1, result.GetDynamicProperty("servermain.DEVICE_ID_HEXADECIMAL")); + Assert.Equal(1, result.GetDynamicProperty("servermain.DEVICE_ID_DECIMAL")); + Assert.Equal(1, result.GetDynamicProperty("servermain.DEVICE_ID_OCTAL")); + Assert.True(result.GetDynamicProperty("servermain.DEVICE_DATA_COLLECTION")); + Assert.Equal(0, result.GetDynamicProperty("servermain.DEVICE_SCAN_MODE")); + Assert.Equal(1000, result.GetDynamicProperty("servermain.DEVICE_SCAN_MODE_RATE_MS")); + Assert.False(result.GetDynamicProperty("servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE")); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - TagGroup (Collection) + + [Fact] + public async Task LoadEntityAsync_ShouldReturnTagGroupCollection_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagGroup = await AddTestTagGroup(device); + var tagGroup2 = await AddTestTagGroup(device, "TagGroup2"); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(device); + + // Assert + Assert.NotNull(result); + Assert.Equal(2, result.Count); + Assert.Contains(result, g => g.Name == tagGroup.Name); + Assert.Contains(result, g => g.Name == tagGroup2.Name); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - Single TagGroup + + [Fact] + public async Task LoadEntityAsync_ShouldReturnTagGroup_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagGroup = await AddTestTagGroup(device); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync(tagGroup.Name, device); + + // Assert + Assert.NotNull(result); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - Single Tag with DynamicProperties + + [Fact] + public async Task LoadEntityAsync_ShouldReturnTag_WithCorrectDynamicProperties() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tag = await AddSimulatorTestTag(device); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadEntityAsync(tag.Name, device); + + // Assert + // Expected defaults based on tag creation + Assert.NotNull(result); + Assert.Equal(tag.Name, result.Name); + Assert.Equal(tag.Description, result.Description); + Assert.Equal(tag.TagAddress, result.GetDynamicProperty("servermain.TAG_ADDRESS")); + Assert.Equal(5, result.GetDynamicProperty("servermain.TAG_DATA_TYPE")); + Assert.Equal(1, result.GetDynamicProperty("servermain.TAG_READ_WRITE_ACCESS")); + Assert.Equal(100, result.GetDynamicProperty("servermain.TAG_SCAN_RATE_MILLISECONDS")); + Assert.False(result.GetDynamicProperty("servermain.TAG_AUTOGENERATED")); + Assert.Equal(0, result.GetDynamicProperty("servermain.TAG_SCALING_TYPE")); + Assert.Equal(0, result.GetDynamicProperty("servermain.TAG_SCALING_RAW_LOW")); + Assert.Equal(1000, result.GetDynamicProperty("servermain.TAG_SCALING_RAW_HIGH")); + Assert.Equal(9, result.GetDynamicProperty("servermain.TAG_SCALING_SCALED_DATA_TYPE")); + Assert.Equal(0, result.GetDynamicProperty("servermain.TAG_SCALING_SCALED_LOW")); + Assert.Equal(1000, result.GetDynamicProperty("servermain.TAG_SCALING_SCALED_HIGH")); + Assert.False(result.GetDynamicProperty("servermain.TAG_SCALING_CLAMP_LOW")); + Assert.False(result.GetDynamicProperty("servermain.TAG_SCALING_CLAMP_HIGH")); + Assert.False(result.GetDynamicProperty("servermain.TAG_SCALING_NEGATE_VALUE")); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - Tag (Collection) + + [Fact] + public async Task LoadEntityAsync_ShouldReturnTagCollection_WhenApiRespondsSuccessfully() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagList = await AddSimulatorTestTags(device); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(device); + + // Assert + Assert.NotNull(result); + Assert.Equal(2, result.Count); + Assert.Contains(result, t => t.Name == tagList[0].Name); + Assert.Contains(result, t => t.Name == tagList[1].Name); + + // Cleanup + await DeleteAllChannelsAsync(); + } + + #endregion + + #region LoadEntityAsync - TagGroup Nested + [Fact] + public async Task LoadEntityAsync_ShouldReturnTagGroupCollectionInTagGroup_WhenApiRespondsSuccessfully() + { + // TODO: Currently this test fails due to issue in EndpointResolver. + // Arrange + try + { + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagGroup = await AddTestTagGroup(device); + var tagGroup2 = await AddTestTagGroup(tagGroup, "TagGroup2"); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(tagGroup); + + // Assert + Assert.NotNull(result); + Assert.Single(result); + Assert.Contains(result, g => g.Name == tagGroup2.Name); + + } + catch (Exception ex) + { + Assert.Fail($"Currently this test fails due to issue in EndpointResolver. Test failed with exception: \n {ex}"); + } + + // Cleanup + await DeleteAllChannelsAsync(); + } + #endregion + + #region LoadEntityAsync - TagGroup Tag Collection + [Fact] + public async Task LoadEntityAsync_ShouldReturnTagCollectionFromTagGroup_WhenApiRespondsSuccessfully() + { + // TODO: Currently this test fails due to issue in EndpointResolver. + try + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagGroup = await AddTestTagGroup(device); + var tagList = await AddSimulatorTestTags(tagGroup); + + // Act + var result = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(tagGroup); + + // Assert + Assert.NotNull(result); + Assert.Equal(2, result.Count); + Assert.Contains(result, t => t.Name == tagList[0].Name); + Assert.Contains(result, t => t.Name == tagList[1].Name); + } + catch (Exception ex) + { + Assert.Fail($"Currently this test fails due to issue in EndpointResolver. Test failed with exception: \n {ex}"); + } + + // Cleanup + await DeleteAllChannelsAsync(); + } + #endregion + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/ProjectApiHandlerTests.cs b/Kepware.Api.TestIntg/ApiClient/ProjectApiHandlerTests.cs new file mode 100644 index 0000000..191f3bc --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ProjectApiHandlerTests.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Kepware.Api.Model; +using Kepware.Api.ClientHandler; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Xunit; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ProjectApiHandlerTests : TestApiClientBase + { + private readonly ProjectApiHandler _projectApiHandler; + + public ProjectApiHandlerTests() + { + _projectApiHandler = _kepwareApiClient.Project; + } + + #region Channel Tests + + [Fact] + public async Task GetOrCreateChannelAsync_ShouldReturnChannel_WhenChannelExists() + { + // Arrange + var channel = await AddTestChannel(); + + // Act + var result = await _projectApiHandler.Channels.GetOrCreateChannelAsync(channel.Name, channel.DeviceDriver!); + + // Assert + Assert.NotNull(result); + Assert.Equal(channel.Name, result.Name); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task GetOrCreateChannelAsync_ShouldCreateChannel_WhenChannelDoesNotExist() + { + // Arrange + var channel = CreateTestChannel(); + + // Act + var result = await _projectApiHandler.Channels.GetOrCreateChannelAsync(channel.Name, channel.DeviceDriver); + + // Assert + Assert.NotNull(result); + Assert.Equal(channel.Name, result.Name); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task UpdateChannelAsync_ShouldReturnTrue_WhenUpdateIsSuccessful() + { + // Arrange + var channel = await AddTestChannel(); + channel.Description = "Updated Description"; + + // Act + var result = await _projectApiHandler.Channels.UpdateChannelAsync(channel); + + // Assert + Assert.True(result); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task DeleteChannelAsync_ShouldReturnTrue_WhenDeletionIsSuccessful() + { + // Arrange + var channel = await AddTestChannel(); + + // Act + var result = await _projectApiHandler.Channels.DeleteChannelAsync(channel); + + // Assert + Assert.True(result); + + // Clean up + await DeleteAllChannelsAsync(); + } + + #endregion + + #region Device Tests + + [Fact] + public async Task GetOrCreateDeviceAsync_ShouldReturnDevice_WhenDeviceExists() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + + // Act + var result = await _projectApiHandler.Devices.GetOrCreateDeviceAsync(channel, device.Name); + + // Assert + Assert.NotNull(result); + Assert.Equal(device.Name, result.Name); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task GetOrCreateDeviceAsync_ShouldCreateDevice_WhenDeviceDoesNotExist() + { + // Arrange + var channel = await AddTestChannel(); + var device = CreateTestDevice(channel); + + // Act + var result = await _projectApiHandler.Devices.GetOrCreateDeviceAsync(channel, device.Name); + + // Assert + Assert.NotNull(result); + Assert.Equal(device.Name, result.Name); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task UpdateDeviceAsync_ShouldReturnTrue_WhenUpdateIsSuccessful() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + device.Description = "Updated Device Description"; + + // Act + var result = await _projectApiHandler.Devices.UpdateDeviceAsync(device); + + // Assert + Assert.True(result); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task DeleteDeviceAsync_ShouldReturnTrue_WhenDeletionIsSuccessful() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + + // Act + var result = await _projectApiHandler.Devices.DeleteDeviceAsync(device); + + // Assert + Assert.True(result); + + // Clean up + await DeleteAllChannelsAsync(); + } + + #endregion + + #region Device Tag & Tag Group Tests + + [Fact] + public async Task LoadTagGroupsRecursiveAsync_ShouldLoadTagGroupsCorrectly() + { + // TODO: Currently this test fails due to isse in EndpointResolver. + try + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagGroup = await AddTestTagGroup(device); + var tagGroup2 = await AddTestTagGroup(device, "TagGroup2"); + var tagGroup3 = await AddTestTagGroup(tagGroup); + + var tagGroups = new List { tagGroup, tagGroup2, tagGroup3 }; + + // Act + await ProjectApiHandler.LoadTagGroupsRecursiveAsync(_kepwareApiClient, tagGroups); + + // Assert + Assert.NotNull(tagGroup.TagGroups); + Assert.Single(tagGroup.TagGroups); + Assert.Equal("TagGroup1", tagGroup.TagGroups.First().Name); + Assert.NotNull(tagGroup2.TagGroups); + Assert.Empty(tagGroup2.TagGroups); + } + catch (Exception ex) + { + Assert.Fail($"Currently this test fails due to issue in EndpointResolver. Test failed with exception: \n {ex}"); + } + + // Clean up + await DeleteAllChannelsAsync(); + } + + #endregion + } +} + diff --git a/Kepware.Api.TestIntg/ApiClient/ProjectLoadTests.cs b/Kepware.Api.TestIntg/ApiClient/ProjectLoadTests.cs new file mode 100644 index 0000000..56e8059 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ProjectLoadTests.cs @@ -0,0 +1,214 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using Moq; +using Moq.Contrib.HttpClient; +using Microsoft.Extensions.Logging; +using Kepware.Api.Model; +using System.Linq; +using System.Collections.Generic; +using Kepware.Api.Serializer; +using Kepware.Api.Util; +using Shouldly; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ProjectLoadTests : TestApiClientBase + { + private const string ENDPONT_FULL_PROJECT = "/config/v1/project?content=serialize"; + + private async Task ConfigureToServeFullProject() + { + var jsonData = await File.ReadAllTextAsync("_data/simdemo_en-us.json"); + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + ENDPONT_FULL_PROJECT) + .ReturnsResponse(jsonData, "application/json"); + } + + private async Task ConfigureToServeEndpoints() + { + var projectData = await LoadJsonTestDataAsync(); + + var channels = projectData.Project?.Channels?.Select(c => new Channel { Name = c.Name, Description = c.Description, DynamicProperties = c.DynamicProperties }).ToList() ?? []; + + // Serve project details + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + "/config/v1/project") + .ReturnsResponse(JsonSerializer.Serialize(new Project { Description = projectData?.Project?.Description, DynamicProperties = projectData?.Project?.DynamicProperties ?? [] }), "application/json"); + + // Serve channels without nested devices + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + "/config/v1/project/channels") + .ReturnsResponse(JsonSerializer.Serialize(channels), "application/json"); + + foreach (var channel in projectData?.Project?.Channels ?? []) + { + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}") + .ReturnsResponse(JsonSerializer.Serialize(new Channel { Name = channel.Name, Description = channel.Description, DynamicProperties = channel.DynamicProperties }), "application/json"); + + if (channel.Devices != null) + { + var devices = channel.Devices.Select(d => new Device { Name = d.Name, Description = d.Description, DynamicProperties = d.DynamicProperties }).ToList(); + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices") + .ReturnsResponse(JsonSerializer.Serialize(devices), "application/json"); + + foreach (var device in channel.Devices) + { + var deviceEndpoint = TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices/{device.Name}"; + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, deviceEndpoint) + .ReturnsResponse(JsonSerializer.Serialize(new Device { Name = device.Name, Description = device.Description, DynamicProperties = device.DynamicProperties }), "application/json"); + + + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, deviceEndpoint + "/tags") + .ReturnsResponse(JsonSerializer.Serialize(device.Tags), "application/json"); + + ConfigureToServeEndpointsTagGroupsRecursive(deviceEndpoint, device.TagGroups ?? []); + } + } + } + } + + private void ConfigureToServeEndpointsTagGroupsRecursive(string endpoint, IEnumerable tagGroups) + { + var tagGroupEndpoint = endpoint + "/tag_groups"; + + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, tagGroupEndpoint) + .ReturnsResponse(JsonSerializer.Serialize(tagGroups), "application/json"); + + foreach (var tagGroup in tagGroups) + { + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, string.Concat(tagGroupEndpoint, "/", tagGroup.Name, "/tags")) + .ReturnsResponse(JsonSerializer.Serialize(tagGroup.Tags), "application/json"); + + ConfigureToServeEndpointsTagGroupsRecursive(string.Concat(tagGroupEndpoint, "/", tagGroup.Name), tagGroup.TagGroups ?? []); + } + } + + //[Theory] + //[InlineData("KEPServerEX", "12", 6, 17, true)] + //[InlineData("KEPServerEX", "12", 6, 16, false)] + //[InlineData("ThingWorxKepwareEdge", "13", 1, 10, true)] + //[InlineData("ThingWorxKepwareEdge", "13", 1, 9, false)] + //[InlineData("UnknownProduct", "99", 10, 0, false)] + //public async Task LoadProject_ShouldLoadCorrectly_BasedOnProductSupport( + // string productName, string productId, int majorVersion, int minorVersion, bool supportsJsonLoad) + //{ + // // TODO: Implement a way to serilize the project data to JSON and compare against it being added to Kepware. + // + // // Arrange + // var channel = await AddTestChannel(); + // var device = await AddTestDevice(channel); + // var tags = await AddSimulatorTestTags(device); + + // var project = await _kepwareApiClient.Project.LoadProject(true); + + // project.IsLoadedByProjectLoadService.ShouldBe(supportsJsonLoad); + + // project.ShouldNotBeNull(); + // project.Channels.ShouldNotBeEmpty("Channels list should not be empty."); + + // var testProject = await LoadJsonTestDataAsync(); + // var compareResult = EntityCompare.Compare(testProject?.Project?.Channels, project?.Channels); + + // compareResult.ShouldNotBeNull(); + // compareResult.UnchangedItems.ShouldNotBeEmpty("All channels should be unchanged."); + // compareResult.ChangedItems.ShouldBeEmpty("No channels should be changed."); + // compareResult.ItemsOnlyInLeft.ShouldBeEmpty("No channels should exist only in the test data."); + // compareResult.ItemsOnlyInRight.ShouldBeEmpty("No channels should exist only in the loaded project."); + + // foreach (var (ExpectedChannel, LoadedChannel) in testProject?.Project?.Channels?.Zip(project?.Channels ?? []) ?? []) + // { + // var deviceCompareResult = EntityCompare.Compare(ExpectedChannel.Devices, LoadedChannel.Devices); + // deviceCompareResult.ShouldNotBeNull(); + // deviceCompareResult.UnchangedItems.ShouldNotBeEmpty($"All devices in channel {ExpectedChannel.Name} should be unchanged."); + // deviceCompareResult.ChangedItems.ShouldBeEmpty($"No devices in channel {ExpectedChannel.Name} should be changed."); + // deviceCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No devices should exist only in the test data for channel {ExpectedChannel.Name}."); + // deviceCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No devices should exist only in the loaded project for channel {ExpectedChannel.Name}."); + + // foreach (var (ExpectedDevice, LoadedDevice) in ExpectedChannel.Devices?.Zip(LoadedChannel.Devices ?? []) ?? []) + // { + // if (ExpectedDevice.Tags?.Count > 0 || LoadedDevice.Tags?.Count > 0) + // { + // var tagCompareResult = EntityCompare.Compare(ExpectedDevice.Tags, LoadedDevice.Tags); + // tagCompareResult.ShouldNotBeNull(); + // tagCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tags in device {ExpectedDevice.Name} should be unchanged."); + // tagCompareResult.ChangedItems.ShouldBeEmpty($"No tags in device {ExpectedDevice.Name} should be changed."); + // tagCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No tags should exist only in the test data for device {ExpectedDevice.Name}."); + // tagCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No tags should exist only in the loaded project for device {ExpectedDevice.Name}."); + // } + + // CompareTagGroupsRecursive(ExpectedDevice.TagGroups, LoadedDevice.TagGroups, ExpectedDevice.Name); + // } + // } + + // // Clean up + // await DeleteAllChannelsAsync(); + //} + + private static void CompareTagGroupsRecursive(DeviceTagGroupCollection? expected, DeviceTagGroupCollection? actual, string parentName) + { + if ((expected?.Count ?? 0) == 0 && (actual?.Count ?? 0) == 0) + return; + var tagGroupCompareResult = EntityCompare.Compare(expected, actual); + + tagGroupCompareResult.ShouldNotBeNull(); + tagGroupCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tag groups in {parentName} should be unchanged."); + tagGroupCompareResult.ChangedItems.ShouldBeEmpty($"No tag groups in {parentName} should be changed."); + tagGroupCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No tag groups should exist only in the test data for {parentName}."); + tagGroupCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No tag groups should exist only in the loaded project for {parentName}."); + + foreach (var (ExpectedTagGroup, ActualTagGroup) in expected?.Zip(actual ?? []) ?? []) + { + var thisName = parentName + "/" + ExpectedTagGroup.Name; + if (ExpectedTagGroup.Tags?.Count > 0 || ActualTagGroup.Tags?.Count > 0) + { + var tagCompareResult = EntityCompare.Compare(ExpectedTagGroup.Tags, ExpectedTagGroup.Tags); + tagCompareResult.ShouldNotBeNull(); + tagCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tags in device {thisName} should be unchanged."); + tagCompareResult.ChangedItems.ShouldBeEmpty($"No tags in device {thisName} should be changed."); + tagCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No tags should exist only in the test data for device {thisName}."); + tagCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No tags should exist only in the loaded project for device {thisName}."); + } + + CompareTagGroupsRecursive(ExpectedTagGroup.TagGroups, ActualTagGroup.TagGroups, thisName); + } + } + + [Fact] + public async Task LoadProject_NotFull_ShouldLoadCorrectly_BasedOnProductSupport() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tags = await AddSimulatorTestTags(device); + + // Act + var project = await _kepwareApiClient.Project.LoadProject(blnLoadFullProject: false); + + // Assert + project.ShouldNotBeNull(); + project.Channels.ShouldBeNull("Channels list should be null."); + + foreach (var ch in project.Channels ?? []) + { + ch.Devices.ShouldBeNull("Devices should not be loaded when not requested."); + } + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task LoadProject_ShouldReturnEmptyProject_WhenHttpRequestFails() + { + + // Act + var project = await _badCredKepwareApiClient.Project.LoadProject(true); + + // Assert + project.ShouldNotBeNull(); + project.Channels.ShouldBeNull(); + } + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/ProjectPermissionTests.cs b/Kepware.Api.TestIntg/ApiClient/ProjectPermissionTests.cs new file mode 100644 index 0000000..2b8a94b --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ProjectPermissionTests.cs @@ -0,0 +1,128 @@ +using Kepware.Api.Model.Admin; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ProjectPermissionTests : TestApiClientBase + { + + [Fact] + public async Task GetProjectPermissionAsync_ShouldReturnProjectPermission_WhenApiRespondsSuccessfully() + { + // Arrange + var serverUserGroup = new ServerUserGroup { Name = "Administrators" }; + var projectPermissionName = ProjectPermissionName.ServermainAlias; + var projectPermission = new ProjectPermission + { + Name = projectPermissionName, + AddObject = true, + EditObject = true, + DeleteObject = false + }; + + // Act + var result = await _kepwareApiClient.Admin.GetProjectPermissionAsync(serverUserGroup, projectPermissionName); + + // Assert + result.ShouldNotBeNull(); + result.Name.ShouldBe(projectPermissionName); + result.AddObject.ShouldBeTrue(); + result.EditObject.ShouldBeTrue(); + result.DeleteObject.ShouldBeTrue(); + } + + //[Fact] + //public async Task GetProjectPermissionAsync_ShouldReturnNull_WhenApiReturnsNotFound() + //{ + // // Arrange + // var serverUserGroup = new ServerUserGroup { Name = "Anonymous Clients" }; + // var projectPermissionName = ProjectPermissionName.ServermainProject; + + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}{ENDPOINT_PROJECT_PERMISSION.Replace("{groupName}", serverUserGroup.Name).Replace("{permissionName}", projectPermissionName.ToString())}") + // .ReturnsResponse(HttpStatusCode.NotFound, "Not Found"); + + // // Act + // var result = await _kepwareApiClient.Admin.GetProjectPermissionAsync(serverUserGroup, projectPermissionName); + + // // Assert + // result.ShouldBeNull(); + //} + + [Fact] + public async Task UpdateProjectPermissionAsync_ShouldReturnTrue_WhenUpdateSuccessful() + { + // Arrange + var serverUserGroup = new ServerUserGroup { Name = "TestGroup" }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(serverUserGroup); + + var projectPermission = new ProjectPermission + { + Name = ProjectPermissionName.ServermainAlias, + AddObject = true, + EditObject = true, + DeleteObject = false + }; + + // Act + var result = await _kepwareApiClient.Admin.UpdateProjectPermissionAsync(serverUserGroup, projectPermission); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(serverUserGroup.Name); + } + + //[Fact] + //public async Task UpdateProjectPermissionAsync_ShouldThrowInvalidOperationException_WhenProjectPermissionNotFound() + //{ + // // Arrange + // var serverUserGroup = new ServerUserGroup { Name = "TestGroup" }; + // var projectPermission = new ProjectPermission + // { + // Name = ProjectPermissionName.ServermainAlias, + // AddObject = true, + // EditObject = true, + // DeleteObject = false + // }; + + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}{ENDPOINT_PROJECT_PERMISSION.Replace("{groupName}", serverUserGroup.Name).Replace("{permissionName}", projectPermission.Name.ToString())}") + // .ReturnsResponse(HttpStatusCode.NotFound, "Not Found"); + + // // Act & Assert + // await Should.ThrowAsync(async () => + // await _kepwareApiClient.Admin.UpdateProjectPermissionAsync(serverUserGroup, projectPermission)); + //} + + [Fact] + public async Task UpdateProjectPermissionAsync_ShouldReturnFalse_WhenUpdateFails() + { + // TODO: Currently fails. Unsure of expected behavior from Kepware when an update fails. As of v6.18 + // Kepware returns a 200 OK with content that indicates a "not applied" key in the payload , + // which is not consistent with other endpoints. + + // Arrange + var serverUserGroup = new ServerUserGroup { Name = "Administrators" }; + var projectPermission = new ProjectPermission + { + Name = ProjectPermissionName.ServermainAlias, + AddObject = true, + EditObject = true, + DeleteObject = false + }; + + // Act + var result = await _kepwareApiClient.Admin.UpdateProjectPermissionAsync(serverUserGroup, projectPermission); + + // Assert + result.ShouldBeFalse("Currently fails. Unsure of expected behavior from Kepware when an update fails. See comments in test."); + } + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/ProjectPropertiesTests.cs b/Kepware.Api.TestIntg/ApiClient/ProjectPropertiesTests.cs new file mode 100644 index 0000000..ef54cc7 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ProjectPropertiesTests.cs @@ -0,0 +1,100 @@ +using Kepware.Api.Model; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; +using System.Net.Http.Json; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ProjectPropertiesTests : TestApiClientBase + { + + #region GetProjectPropertiesAsync Tests + + [Fact] + public async Task GetProjectPropertiesAsync_ShouldReturnProjectProperties_WhenApiRespondsSuccessfully() + { + + // Act + var result = await _kepwareApiClient.Project.GetProjectPropertiesAsync(); + + // Assert + result.ShouldNotBeNull(); + result.ProjectProperties.OpcUaEnableDiagnostics.ShouldNotBeNull(); + result.ProjectProperties.OpcUaEnableDiagnostics.Value.ShouldBeOfType(); + result.ProjectProperties.ThingWorxMaxDatastoreSize.ShouldBeOfType(); + result.ProjectProperties.EnableOpcDa1.ShouldNotBeNull(); + result.ProjectProperties.EnableOpcDa1.Value.ShouldBeOfType(); + } + + [Fact] + public async Task GetProjectPropertiesAsync_ShouldReturnNull_WhenApiReturnsUnauthorized() + { + + // Act + var result = await _badCredKepwareApiClient.Project.GetProjectPropertiesAsync(); + + // Assert + result.ShouldBeNull(); + } + + #endregion + + #region SetProjectPropertiesAsync Tests + + [Fact] + public async Task SetProjectPropertiesAsync_ShouldReturnTrue_WhenUpdateSuccessful() + { + // Arrange + var newSettings = new Project(); + if (_productInfo.ProductId != "013") + { + newSettings.ProjectProperties.OpcDaMaxConnections = new Random().Next(1, 4001); + } + newSettings.ProjectProperties.OpcUaMaxConnections = new Random().Next(1, 257); + + // Act + var result = await _kepwareApiClient.Project.SetProjectPropertiesAsync(newSettings); + + // Assert + result.ShouldBeTrue(); + } + + [Fact] + public async Task SetProjectPropertiesAsync_ShouldReturnFalse_WhenUpdateFails() + { + // Arrange + var newSettings = new Project(); + newSettings.ProjectProperties.OpcDaMaxConnections = 5000; // Invalid value, should be between 1 and 4000 + + // Act + var result = await _kepwareApiClient.Project.SetProjectPropertiesAsync(newSettings); + + // Assert + result.ShouldBeFalse(); + } + + [Fact] + public async Task SetProjectPropertiesAsync_ShouldReturnFalse_WhenApiReturnsUnauthorized() + { + // Arrange + var newSettings = new Project(); + newSettings.ProjectProperties.OpcDaMaxConnections = new Random().Next(1, 4001); + newSettings.ProjectProperties.OpcUaMaxConnections = new Random().Next(1, 257); + + // Act and Assert + await Should.ThrowAsync(async () => + { + await _badCredKepwareApiClient.Project.SetProjectPropertiesAsync(newSettings); + }); + } + + #endregion + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/ReinitializeRuntimeAsyncTests.cs b/Kepware.Api.TestIntg/ApiClient/ReinitializeRuntimeAsyncTests.cs new file mode 100644 index 0000000..cc27c26 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ReinitializeRuntimeAsyncTests.cs @@ -0,0 +1,52 @@ +using Kepware.Api.Model; +using Kepware.Api.Model.Services; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System; +using System.Net; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ReinitializeRuntimeAsyncTests : TestApiClientBase + { + + [Fact] + public async Task ReinitializeRuntimeAsync_ShouldReturnKepServerJobPromise_WhenApiResponseIsInvalid() + { + + // Act + var result = await _badCredKepwareApiClient.ApiServices.ReinitializeRuntimeAsync(TimeSpan.FromSeconds(30)); + + // Assert + result.ShouldNotBeNull(); + result.Endpoint.ShouldBe("/config/v1/project/services/ReinitializeRuntime"); + result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30)); + } + + + [Fact] + public async Task ReinitializeRuntimeAsync_ShouldReturnSuccess_WhenJobCompletesSuccessfully() + { + + // Act + var result = await _kepwareApiClient.ApiServices.ReinitializeRuntimeAsync(TimeSpan.FromSeconds(30)); + // Assert + result.ShouldNotBeNull(); + result.Endpoint.ShouldBe("/config/v1/project/services/ReinitializeRuntime"); + result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30)); + + // Wait for the job to complete + var completionResult = await result.AwaitCompletionAsync(); + + // Assert + completionResult.Value.ShouldBeTrue(); + completionResult.IsSuccess.ShouldBeTrue(); + } + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/ServerUserGroupTests.cs b/Kepware.Api.TestIntg/ApiClient/ServerUserGroupTests.cs new file mode 100644 index 0000000..c80da93 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ServerUserGroupTests.cs @@ -0,0 +1,154 @@ +using Kepware.Api.Model.Admin; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; +using System.Net.Http.Json; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class ServerUserGroupTests : TestApiClientBase + { + + [Fact] + public async Task GetServerUserGroupAsync_ShouldReturnServerUserGroup_WhenApiRespondsSuccessfully() + { + // Arrange + var userGroup = new ServerUserGroup{ Name= "Administrators"}; + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserGroupAsync(userGroup.Name); + + // Assert + result.ShouldNotBeNull(); + result.Name.ShouldBe(userGroup.Name); + result.Enabled!.Value.ShouldBeTrue(); + } + + [Fact] + public async Task GetServerUserGroupAsync_ShouldReturnNull_WhenApiReturnsNotFound() + { + // Arrange + var groupName = "NonExistentGroup"; + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserGroupAsync(groupName); + + // Assert + result.ShouldBeNull(); + } + + [Fact] + public async Task CreateOrUpdateServerUserGroupAsync_ShouldCreateServerUserGroup_WhenItDoesNotExist() + { + // Arrange + var userGroup = CreateTestServerUserGroup(); + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.GenericConfig.DeleteItemAsync(userGroup); + } + + [Fact] + public async Task CreateOrUpdateServerUserGroupAsync_ShouldUpdateServerUserGroup_WhenItExists() + { + // Arrange + var userGroup = CreateTestServerUserGroup(); + await _kepwareApiClient.GenericConfig.InsertItemAsync(userGroup); + userGroup.Enabled = false; + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.GenericConfig.DeleteItemAsync(userGroup); + } + + [Fact] + public async Task DeleteServerUserGroupAsync_ShouldReturnTrue_WhenDeleteSuccessful() + { + // Arrange + var userGroup = CreateTestServerUserGroup(); + await _kepwareApiClient.GenericConfig.InsertItemAsync(userGroup); + + // Act + var result = await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.GenericConfig.DeleteItemAsync(userGroup); + } + + [Fact] + public async Task DeleteServerUserGroupAsync_ShouldReturnFalse_WhenDeleteFails() + { + // Arrange + // Cannot delete the default Administrators group + var groupName = "Administrators"; + + // Act + var result = await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(groupName); + + // Assert + result.ShouldBeFalse(); + } + + [Fact] + public async Task GetServerUserGroupsAsync_ShouldReturnServerUserGroupCollection_WhenApiRespondsSuccessfully() + { + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserGroupListAsync(); + + // Assert + result.ShouldNotBeNull(); + result.Count.ShouldBeGreaterThan(2); + } + + private static ServerUserGroup CreateTestServerUserGroup(string name = "TestGroup") + { + return new ServerUserGroup + { + Name = name, + Enabled = true, + IoTagRead = true, + IoTagWrite = true, + IoTagDynamicAddressing = true, + SystemTagRead = true, + SystemTagWrite = true, + ManageLicenses = true, + ModifyServerSettings = true, + DisconnectClients = true, + ReplaceRuntimeProject = true, + ResetEventLog = true, + BrowseNamespace = true, + ProjectModificationAdd = true, + ProjectModificationEdit = true, + ProjectModificationDelete = true, + ResetOpcDiagsLog = true, + ResetCommDiagsLog = true, + ConfigApiLogAccess = true, + ViewEventLogSecurity = true, + ViewEventLogError = true, + ViewEventLogWarning = true, + ViewEventLogInfo = true + }; + } + } +} + diff --git a/Kepware.Api.TestIntg/ApiClient/ServerUserTests.cs b/Kepware.Api.TestIntg/ApiClient/ServerUserTests.cs new file mode 100644 index 0000000..fddab11 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/ServerUserTests.cs @@ -0,0 +1,277 @@ +using Kepware.Api.Model.Admin; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; +using System.Net.Http.Json; + +namespace Kepware.Api.TestIntg.ApiClient +{ + [TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")] + public class ServerUserTests : TestApiClientBase + { + + [Fact] + public async Task GetServerUserAsync_ShouldReturnServerUser_WhenApiRespondsSuccessfully() + { + // Arrange + var user = CreateTestServerUser("Administrators", "Administrator"); + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserAsync(user.Name); + + // Assert + result.ShouldNotBeNull(); + result.Name.ShouldBe(user.Name); + result.Enabled.ShouldBe(user.Enabled); + } + + [Fact] + public async Task GetServerUserAsync_ShouldReturnNull_WhenApiReturnsNotFound() + { + // Arrange + var userName = "NonExistentUser"; + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserAsync(userName); + + // Assert + result.ShouldBeNull(); + } + + [Fact] + public async Task CreateOrUpdateServerUserAsync_ShouldCreateServerUser_WhenItDoesNotExist() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task CreateOrUpdateServerUserAsync_ShouldUpdateServerUser_WhenItExists() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + await _kepwareApiClient.GenericConfig.InsertItemAsync(user); + user.Description = "Updated Description"; + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task CreateServerUserAsync_ShouldThrowArgumentException_WhenPasswordIsInvalid() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + user.Password = "short"; // Invalid password (too short) + + // Act & Assert + await Should.ThrowAsync(async () => + await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user)); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task CreateServerUserAsync_ShouldThrowArgumentException_WhenPasswordIsEmpty() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + user.Password = string.Empty; // Empty password + + // Act & Assert + await Should.ThrowAsync(async () => + await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user)); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task UpdateServerUserAsync_ShouldThrowArgumentException_WhenPasswordIsInvalid() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + await _kepwareApiClient.GenericConfig.InsertItemAsync(user); + user.Password = "short"; + + // Act & Assert + await Should.ThrowAsync(async () => + await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user)); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task UpdateServerUserAsync_ShouldNotThrowArgumentException_WhenPasswordIsEmpty() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + await _kepwareApiClient.GenericConfig.InsertItemAsync(user); + + user.Password = null; + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateServerUserAsync(user); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task DeleteServerUserAsync_ShouldReturnTrue_WhenDeleteSuccessful() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var user = CreateTestServerUser(userGroup.Name); + await _kepwareApiClient.GenericConfig.InsertItemAsync(user); + + // Act + var result = await _kepwareApiClient.Admin.DeleteServerUserAsync(user.Name); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + [Fact] + public async Task DeleteServerUserAsync_ShouldReturnFalse_WhenDeleteFails() + { + //Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + var user = CreateTestServerUser(userGroup.Name); + + + // Act + var result = await _kepwareApiClient.Admin.DeleteServerUserAsync(user.Name); + + // Assert + result.ShouldBeFalse(); + } + + [Fact] + public async Task GetServerUsersAsync_ShouldReturnServerUserCollection_WhenApiRespondsSuccessfully() + { + // Arrange + var userGroup = new ServerUserGroup + { + Name = "TestGroup", + Enabled = true + }; + + await _kepwareApiClient.Admin.CreateOrUpdateServerUserGroupAsync(userGroup); + var users = new ServerUserCollection + { + CreateTestServerUser(userGroup.Name, "User1"), + CreateTestServerUser(userGroup.Name, "User2") + }; + await _kepwareApiClient.GenericConfig.InsertItemsAsync(users); + + + // Act + var result = await _kepwareApiClient.Admin.GetServerUserListAsync(); + + // Assert + result.ShouldNotBeNull(); + result.Count.ShouldBeGreaterThan(2); + result.ShouldContain(u => u.Name == "User1"); + result.ShouldContain(u => u.Name == "User2"); + + // Clean up + await _kepwareApiClient.Admin.DeleteServerUserGroupAsync(userGroup.Name); + } + + private static ServerUser CreateTestServerUser(string group, string name = "TestUser") + { + return new ServerUser + { + Name = name, + Enabled = true, + UserGroupName = group, + Password = "ValidPassword123!", + UserType = 0 + }; + } + } +} + + diff --git a/Kepware.Api.TestIntg/ApiClient/TestConnection.cs b/Kepware.Api.TestIntg/ApiClient/TestConnection.cs new file mode 100644 index 0000000..ecf7531 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/TestConnection.cs @@ -0,0 +1,25 @@ +using Moq; +using Moq.Contrib.HttpClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public class TestConnection : TestApiClientBase + { + [Fact] + public async Task TestConnectionAsync_ShouldReturnTrue_WhenApiIsHealthy() + { + + // Act + var result = await _kepwareApiClient.TestConnectionAsync(); + + // Assert + Assert.True(result); + } + + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/UaEndpointTests.cs b/Kepware.Api.TestIntg/ApiClient/UaEndpointTests.cs new file mode 100644 index 0000000..0f81c2b --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/UaEndpointTests.cs @@ -0,0 +1,137 @@ +using Kepware.Api.Model.Admin; +using Kepware.Api.Serializer; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; +using System.Net.Http.Json; +using Xunit.Extensions.Ordering; + +namespace Kepware.Api.TestIntg.ApiClient +{ + [TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")] + public class UaEndpointTests : TestApiClientBase + { + + [SkippableFact] + [Order(1)] + public async Task CreateOrUpdateUaEndpointAsync_ShouldCreateUaEndpoint_WhenItDoesNotExist() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Arrange + var uaEndpoint = CreateTestUaEndpoint(); + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateUaEndpointAsync(uaEndpoint); + + // Assert + result.ShouldBeTrue(); + } + + [SkippableFact] + [Order(2)] + public async Task CreateOrUpdateUaEndpointAsync_ShouldUpdateUaEndpoint_WhenItExists() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Arrange + var uaEndpoint = CreateTestUaEndpoint(); + uaEndpoint.Port = 4840; + + // Act + var result = await _kepwareApiClient.Admin.CreateOrUpdateUaEndpointAsync(uaEndpoint); + + // Assert + result.ShouldBeTrue(); + } + + [SkippableFact] + [Order(3)] + public async Task GetUaEndpointAsync_ShouldReturnUaEndpoint_WhenApiRespondsSuccessfully() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Arrange + var uaEndpoint = CreateTestUaEndpoint(); + + // Act + var result = await _kepwareApiClient.Admin.GetUaEndpointAsync(uaEndpoint.Name); + + // Assert + result.ShouldNotBeNull(); + result.Name.ShouldBe(uaEndpoint.Name); + result.Port.ShouldBeOfType(); + } + + [SkippableFact] + [Order(4)] + public async Task GetUaEndpointsAsync_ShouldReturnUaEndpointCollection_WhenApiRespondsSuccessfully() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Act + var result = await _kepwareApiClient.Admin.GetUaEndpointListAsync(); + + // Assert + result.ShouldNotBeNull(); + // result.Count.ShouldBe(2); + } + + + [SkippableFact] + [Order(5)] + public async Task DeleteUaEndpointAsync_ShouldReturnTrue_WhenDeleteSuccessful() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Arrange + var uaEndpoint = CreateTestUaEndpoint(); + + // Act + var result = await _kepwareApiClient.Admin.DeleteUaEndpointAsync(uaEndpoint.Name); + + // Assert + result.ShouldBeTrue(); + } + + [SkippableFact] + [Order(6)] + public async Task DeleteUaEndpointAsync_ShouldReturnFalse_WhenDeleteFails() + { + // Skip the test if the product is not "Edge" productId + Skip.If(_productInfo.ProductId != "013", "Test only applicable for Edge productIds"); + + // Arrange + var uaEndpoint = CreateTestUaEndpoint(); + + // Act + var result = await _kepwareApiClient.Admin.DeleteUaEndpointAsync(uaEndpoint.Name); + + // Assert + result.ShouldBeFalse(); + } + + private static UaEndpoint CreateTestUaEndpoint(string endpointName = "TestEndpoint") + { + return new UaEndpoint + { + Name = endpointName, + Enabled = true, + Adapter = "Default", + Port = 49500, + SecurityNone = false, + SecurityBasic256Sha256 = UaEndpointSecurityMode.SignAndEncrypt + }; + } + } +} diff --git a/Kepware.Api.TestIntg/ApiClient/UpdateTests.cs b/Kepware.Api.TestIntg/ApiClient/UpdateTests.cs new file mode 100644 index 0000000..a721c8e --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/UpdateTests.cs @@ -0,0 +1,87 @@ +using Kepware.Api.Model; +using Microsoft.Extensions.Logging; +using Moq; +using Moq.Contrib.HttpClient; +using Shouldly; +using System.Net; +using System.Text.Json; + +namespace Kepware.Api.TestIntg.ApiClient; + +public class UpdateTests : TestApiClientBase +{ + [Fact] + public async Task Update_Item_WhenSuccessful_ShouldReturnTrue() + { + // Arrange + var channel = await AddTestChannel(); + channel.Description = "Updated Description"; + + // Act + var result = await _kepwareApiClient.GenericConfig.UpdateItemAsync(channel); + + // Assert + result.ShouldBeTrue(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Update_Item_WhenNotFound_ShouldReturnFalse() + { + // Arrange + var channel = CreateTestChannel(); + + // Act + var result = await _kepwareApiClient.GenericConfig.UpdateItemAsync(channel); + + // Assert + result.ShouldBeFalse(); + + // Clean up + await DeleteAllChannelsAsync(); + } + + [Fact] + public async Task Update_MultipleItems_ShouldUpdateAll() + { + // Arrange + var channel = await AddTestChannel(); + var device = await AddTestDevice(channel); + var tagsAdded = await AddSimulatorTestTags(device); + var tags = new List<(Tag item, Tag? oldItem)>(); + foreach (var tag in tagsAdded) + { + tags.Add((new Tag { Name = tag.Name, Description = "Updated Description" }, tag)); + }; + + // Act + var results = await _kepwareApiClient.GenericConfig.UpdateItemsAsync(tags, device); + + // Assert + results.Count.ShouldBe(tags.Count); + results.ShouldAllBe(r => r == true); + + // Clean up + await DeleteAllChannelsAsync(); + + } + + [Fact] + public async Task Update_Item_WithHttpError_ShouldReturnFalse() + { + // Arrange + var channel = await AddTestChannel(); + channel.SetDynamicProperty("InvalidProperty", "InvalidValue"); + + // Act + var result = await _kepwareApiClient.GenericConfig.UpdateItemAsync(channel); + + // Assert + result.ShouldBeFalse(); + + // Clean up + await DeleteAllChannelsAsync(); + } +} \ No newline at end of file diff --git a/Kepware.Api.TestIntg/ApiClient/_TestApiClientBase.cs b/Kepware.Api.TestIntg/ApiClient/_TestApiClientBase.cs new file mode 100644 index 0000000..268fd53 --- /dev/null +++ b/Kepware.Api.TestIntg/ApiClient/_TestApiClientBase.cs @@ -0,0 +1,307 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; +using Moq; +using Moq.Contrib.HttpClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Net; +using System.IO; +using Kepware.Api.Model; +using Kepware.Api.Serializer; +using Kepware.Api.ClientHandler; + +namespace Kepware.Api.TestIntg.ApiClient +{ + public abstract class TestApiClientBase + { + protected string TEST_ENDPOINT = "http://localhost:57412"; + protected bool _testIntegration = false; // Set to true to run integration tests + + protected readonly Mock _httpMessageHandlerMock; + protected readonly Mock> _loggerMock; + protected readonly Mock> _loggerMockAdmin; + protected readonly Mock> _loggerMockProject; + protected readonly Mock> _loggerMockGeneric; + protected readonly Mock _loggerFactoryMock; + protected readonly KepwareApiClient _kepwareApiClient; + protected readonly KepwareApiClient _badCredKepwareApiClient; + protected readonly ProductInfo _productInfo; + + protected TestApiClientBase() + { + _httpMessageHandlerMock = new Mock(); + _loggerMock = new Mock>(); + _loggerMockAdmin = new Mock>(); + _loggerMockGeneric = new Mock>(); + _loggerMockProject = new Mock>(); + _loggerFactoryMock = new Mock(); + + //_loggerFactoryMock.Setup(factory => factory.CreateLogger(It.IsAny())).Returns((string name) => + //{ + // if (name == typeof(KepwareApiClient).FullName) + // return _loggerMock.Object; + // else if (name == typeof(AdminApiHandler).FullName) + // return _loggerMockAdmin.Object; + // else if (name == typeof(GenericApiHandler).FullName) + // return _loggerMockGeneric.Object; + // else if (name == typeof(ProjectApiHandler).FullName) + // return _loggerMockProject.Object; + // else + // return Mock.Of(); + //}); + //_kepwareApiClient = kepwareApiClient; + + // Load configuration from appsettings.json + var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .Build(); + + // Check if the test integration flag is set + _testIntegration = bool.TryParse(configuration["TestSettings:IntegrationTest"], out var testIntegration) && testIntegration; + + TEST_ENDPOINT = $"{configuration["TestSettings:TestServer:Host"]}:{configuration["TestSettings:TestServer:Port"]}" ?? TEST_ENDPOINT; + + var testHost = Host.CreateDefaultBuilder() + .ConfigureServices((context, services) => + { + // Add application services + services.AddKepwareApiClient( + name: "TestClient", + baseUrl: TEST_ENDPOINT, + apiUserName: $"{configuration["TestSettings:TestServer:UserName"]}", + apiPassword: $"{configuration["TestSettings:TestServer:Password"]}", + disableCertificateValidation: true + ); + // Add application services + services.AddKepwareApiClient( + name: "BadCredClient", + baseUrl: TEST_ENDPOINT, + apiUserName: $"{configuration["TestSettings:TestServer:UserName"]}", + apiPassword: $"Test1234567890", + disableCertificateValidation: true + ); + }) + .ConfigureLogging(logging => + { + // Configure logging to use the console + logging.ClearProviders(); + logging.AddConsole(); + logging.SetMinimumLevel(LogLevel.Information); + + logging.AddFilter("Microsoft", LogLevel.Warning); + logging.AddFilter("System", LogLevel.Warning); + }) + .Build(); + + // 2. Get the KepwareApiClient + var listClients = testHost.Services.GetServices(); + _kepwareApiClient = listClients.First(client => client.ClientName == "TestClient"); + _badCredKepwareApiClient = listClients.First(client => client.ClientName == "BadCredClient"); + + // 3. Get the ProductInfo + + // Update the assignment to properly await the asynchronous method and handle the nullable return type. + var connected = _kepwareApiClient.TestConnectionAsync().GetAwaiter().GetResult(); + _productInfo = _kepwareApiClient.GetProductInfoAsync().GetAwaiter().GetResult() ?? new ProductInfo(); + + + //var httpClient = new HttpClient() + //{ + // BaseAddress = new Uri(TEST_ENDPOINT) + //}; + + + //// Encode username and password as Base64 + ////var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{configuration["TestSettings:TestServer:UserName"]}:{configuration["TestSettings:TestServer:Password"]}")); + ////httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentials); + + //_kepwareApiClient = new KepwareApiClient("TestClient", new KepwareApiClientOptions { HostUri = httpClient.BaseAddress, Username = configuration["TestSettings:TestServer:UserName"], Password = configuration["TestSettings:TestServer:Password"] }, _loggerFactoryMock.Object, httpClient); + } + + protected static async Task LoadJsonTestDataAsync() + { + var json = await File.ReadAllTextAsync("_data/simdemo_en-us.json"); + return JsonSerializer.Deserialize(json, KepJsonContext.Default.JsonProjectRoot)!; + } + + protected async Task ConfigureToServeDrivers() + { + var jsonData = await File.ReadAllTextAsync("_data/doc_drivers.json"); + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}/config/v1/doc/drivers/") + .ReturnsResponse(HttpStatusCode.OK, jsonData, "application/json"); + } + + protected void ConfigureConnectedClient( + string productName = "KEPServerEX", + string productId = "012", + int majorVersion = 6, + int minorVersion = 17, + int buildVersion = 240, + int patchVersion = 0) + { + _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}/config/v1/about") + .ReturnsResponse(HttpStatusCode.OK, $$""" + { + "product_name": "{{productName}}", + "product_id": "{{productId}}", + "product_version": "V{{majorVersion}}.{{minorVersion}}.{{buildVersion}}.{{patchVersion}}", + "product_version_major": {{majorVersion}}, + "product_version_minor": {{minorVersion}}, + "product_version_build": {{buildVersion}}, + "product_version_patch": {{patchVersion}} + } + """, "application/json"); + + // // Mock for the status endpoint + // var statusResponse = "[{\"Name\": \"ConfigAPI REST Service\", \"Healthy\": true}]"; + // _httpMessageHandlerMock.SetupRequest(HttpMethod.Get, $"{TEST_ENDPOINT}/config/v1/status") + // .ReturnsResponse(HttpStatusCode.OK, statusResponse, "application/json"); + } + + protected Channel CreateTestChannel(string name = "TestChannel", string driver = "Simulator") + { + var channel = new Channel { Name = name }; + channel.SetDynamicProperty("servermain.MULTIPLE_TYPES_DEVICE_DRIVER", driver); + channel.SetDynamicProperty("common.ALLTYPES_DESCRIPTION", "Example Simulator Channel"); + return channel; + } + + protected async Task AddTestChannel(string name = "TestChannel", string driver = "Simulator") + { + var channel = CreateTestChannel(name, driver); + return await _kepwareApiClient.Project.Channels.GetOrCreateChannelAsync(channel.Name, channel.DeviceDriver!); + } + protected async Task DeleteAllChannelsAsync() + { + var channels = await _kepwareApiClient.GenericConfig.LoadCollectionAsync(); + if (channels != null) + { + foreach (var channel in channels) + { + await _kepwareApiClient.Project.Channels.DeleteChannelAsync(channel.Name); + } + } + } + + protected Device CreateTestDevice(Channel owner, string name = "TestDevice", string driver = "Simulator") + { + var device = new Device { Name = name, Owner = owner }; + device.SetDynamicProperty("servermain.MULTIPLE_TYPES_DEVICE_DRIVER", driver); + device.SetDynamicProperty("common.ALLTYPES_DESCRIPTION", "Example Simulator Device"); + return device; + } + + protected async Task AddTestDevice(Channel owner, string name = "TestDevice", string driver = "Simulator") + { + var device = CreateTestDevice(owner, name, driver); + return await _kepwareApiClient.Project.Devices.GetOrCreateDeviceAsync(owner, device.Name); + } + + protected async Task AddAtgTestDevice(Channel owner, string name = "TestDevice") + { + var device = new Device { Name = name, Owner = owner }; + device.SetDynamicProperty("servermain.MULTIPLE_TYPES_DEVICE_DRIVER", owner.DeviceDriver); + device.SetDynamicProperty("common.ALLTYPES_DESCRIPTION", "Example Simulator Device"); + device.SetDynamicProperty("servermain.DEVICE_MODEL", 0); + device.SetDynamicProperty("servermain.DEVICE_ID_STRING", "10.10.10.10,1,0"); + + await _kepwareApiClient.GenericConfig.InsertItemAsync(device, owner); + + return device; + } + + protected Tag CreateTestTag(string name = "Tag1", string address = "K0001") + { + return new Tag { Name = name, TagAddress = address }; + } + + protected async Task AddSimulatorTestTag(Device owner, string name = "Tag1", string address = "K0001") + { + var tag = CreateTestTag(name, address); + tag.Owner = owner; + await _kepwareApiClient.GenericConfig.InsertItemAsync(tag, owner); + return await _kepwareApiClient.GenericConfig.LoadEntityAsync(tag.Name, owner); + } + + protected async Task AddSimulatorTestTag(DeviceTagGroup owner, string name = "Tag1", string address = "K0001") + { + var tag = CreateTestTag(name, address); + tag.Owner = owner; + await _kepwareApiClient.GenericConfig.InsertItemAsync(tag, owner); + return await _kepwareApiClient.GenericConfig.LoadEntityAsync(tag.Name, owner); + } + + protected List CreateSimulatorTestTags(string name = "Tag", string address = "K000", int count = 2) + { + return Enumerable.Range(1, count) + .Select(i => CreateTestTag(name: $"{name}{i}", address: $"{address}{i}")) + .ToList(); + } + + protected async Task> AddSimulatorTestTags(Device owner, string name = "Tag", string address = "K000", int count = 2) + { + var tagsList = CreateSimulatorTestTags(name, address); + foreach (var tag in tagsList) + { + tag.Owner = owner; + } + await _kepwareApiClient.GenericConfig.InsertItemsAsync(tagsList, owner: owner); + return tagsList; + } + + protected async Task> AddSimulatorTestTags(DeviceTagGroup owner, string name = "Tag1", string address = "K000", int count = 2) + { + var tagsList = CreateSimulatorTestTags(name, address); + foreach (var tag in tagsList) + { + tag.Owner = owner; + } + await _kepwareApiClient.GenericConfig.InsertItemsAsync(tagsList, owner: owner); + return tagsList; + } + + protected DeviceTagGroup CreateTestTagGroup(string name = "TagGroup1") + { + return new DeviceTagGroup { Name = name }; + + } + protected DeviceTagGroup CreateTestTagGroup(Device owner, string name = "TagGroup1") + { + return new DeviceTagGroup(name: name, owner); + + } + protected DeviceTagGroup CreateTestTagGroup(DeviceTagGroup owner, string name = "TagGroup1") + { + return new DeviceTagGroup(name: name, owner); + + } + protected async Task AddTestTagGroup(Device owner, string name = "TagGroup1", string driver = "Simulator") + { + + var tagGroup = new DeviceTagGroup(); + tagGroup.Name = name; + tagGroup.Owner = owner; + await _kepwareApiClient.GenericConfig.InsertItemAsync(tagGroup, tagGroup.Owner); + return await _kepwareApiClient.GenericConfig.LoadEntityAsync(tagGroup.Name, owner); + + } + + protected async Task AddTestTagGroup(DeviceTagGroup owner, string name = "TagGroup1", string driver = "Simulator") + { + + var tagGroup = new DeviceTagGroup(); + tagGroup.Name = name; + tagGroup.Owner = owner; + await _kepwareApiClient.GenericConfig.InsertItemAsync(tagGroup, tagGroup.Owner); + return await _kepwareApiClient.GenericConfig.LoadEntityAsync(tagGroup.Name, owner); + + } + } +} diff --git a/Kepware.Api.TestIntg/AssemblyInfo.cs b/Kepware.Api.TestIntg/AssemblyInfo.cs new file mode 100644 index 0000000..8a18fcd --- /dev/null +++ b/Kepware.Api.TestIntg/AssemblyInfo.cs @@ -0,0 +1,2 @@ +// Disabled parallelization for integration tests to avoid conflicts with server configuration changes during tests. +[assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/Kepware.Api.TestIntg/Kepware.Api.TestIntg.csproj b/Kepware.Api.TestIntg/Kepware.Api.TestIntg.csproj new file mode 100644 index 0000000..80fa793 --- /dev/null +++ b/Kepware.Api.TestIntg/Kepware.Api.TestIntg.csproj @@ -0,0 +1,53 @@ + + + + net8.0;net9.0 + enable + enable + false + false + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/Kepware.Api.TestIntg/_data/doc_drivers.json b/Kepware.Api.TestIntg/_data/doc_drivers.json new file mode 100644 index 0000000..cdd5f21 --- /dev/null +++ b/Kepware.Api.TestIntg/_data/doc_drivers.json @@ -0,0 +1,856 @@ +[ + { + "namespace": "abb_totalflow", + "display_name": "ABB Totalflow", + "doc_channels": "/config/v1/doc/drivers/ABB%20Totalflow/channels", + "doc_devices": "/config/v1/doc/drivers/ABB%20Totalflow/devices", + "doc_meter_groups": "/config/v1/doc/drivers/ABB%20Totalflow/meter_groups", + "doc_meters": "/config/v1/doc/abb_totalflow_meters" + }, + { + "namespace": "advanced_simulator", + "display_name": "Advanced Simulator", + "doc_channels": "/config/v1/doc/drivers/Advanced%20Simulator/channels", + "doc_devices": "/config/v1/doc/drivers/Advanced%20Simulator/devices" + }, + { + "namespace": "a-b_bulletin_900", + "display_name": "Allen-Bradley Bulletin 900", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Bulletin%20900/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Bulletin%20900/devices" + }, + { + "namespace": "a-b_bulletin_1609", + "display_name": "Allen-Bradley Bulletin 1609", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Bulletin%201609/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Bulletin%201609/devices" + }, + { + "namespace": "controllogix_ethernet", + "display_name": "Allen-Bradley ControlLogix Ethernet", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20ControlLogix%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20ControlLogix%20Ethernet/devices" + }, + { + "namespace": "controllogix_unsolicited_ethernet", + "display_name": "Allen-Bradley ControlLogix Server Ethernet", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20ControlLogix%20Server%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20ControlLogix%20Server%20Ethernet/devices" + }, + { + "namespace": "df1", + "display_name": "Allen-Bradley DF1", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20DF1/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20DF1/devices" + }, + { + "namespace": "allenbradley_ethernet", + "display_name": "Allen-Bradley Ethernet", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Ethernet/devices" + }, + { + "namespace": "allenbradley_micro800_ethernet", + "display_name": "Allen-Bradley Micro800 Ethernet", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Micro800%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Micro800%20Ethernet/devices" + }, + { + "namespace": "allenbradley_micro800_serial", + "display_name": "Allen-Bradley Micro800 Serial", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Micro800%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Micro800%20Serial/devices" + }, + { + "namespace": "ab_unsolicited_ethernet", + "display_name": "Allen-Bradley Server Ethernet", + "doc_channels": "/config/v1/doc/drivers/Allen-Bradley%20Server%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Allen-Bradley%20Server%20Ethernet/devices" + }, + { + "namespace": "alstom_redundant_ethernet", + "display_name": "Alstom Redundant Ethernet", + "doc_channels": "/config/v1/doc/drivers/Alstom%20Redundant%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Alstom%20Redundant%20Ethernet/devices" + }, + { + "namespace": "analog_devices", + "display_name": "Analog Devices", + "doc_channels": "/config/v1/doc/drivers/Analog%20Devices/channels", + "doc_devices": "/config/v1/doc/drivers/Analog%20Devices/devices" + }, + { + "namespace": "aromat_ethernet", + "display_name": "Aromat Ethernet", + "doc_channels": "/config/v1/doc/drivers/Aromat%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Aromat%20Ethernet/devices" + }, + { + "namespace": "aromat", + "display_name": "Aromat Serial", + "doc_channels": "/config/v1/doc/drivers/Aromat%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Aromat%20Serial/devices" + }, + { + "namespace": "directnet", + "display_name": "AutomationDirect DirectNet", + "doc_channels": "/config/v1/doc/drivers/AutomationDirect%20DirectNet/channels", + "doc_devices": "/config/v1/doc/drivers/AutomationDirect%20DirectNet/devices" + }, + { + "namespace": "plcdirect_ebc", + "display_name": "AutomationDirect EBC", + "doc_channels": "/config/v1/doc/drivers/AutomationDirect%20EBC/channels", + "doc_devices": "/config/v1/doc/drivers/AutomationDirect%20EBC/devices" + }, + { + "namespace": "plcdirect_ecom", + "display_name": "AutomationDirect ECOM", + "doc_channels": "/config/v1/doc/drivers/AutomationDirect%20ECOM/channels", + "doc_devices": "/config/v1/doc/drivers/AutomationDirect%20ECOM/devices" + }, + { + "namespace": "ksequence", + "display_name": "AutomationDirect K Sequence", + "doc_channels": "/config/v1/doc/drivers/AutomationDirect%20K%20Sequence/channels", + "doc_devices": "/config/v1/doc/drivers/AutomationDirect%20K%20Sequence/devices" + }, + { + "namespace": "productivity_3000_ethernet", + "display_name": "AutomationDirect Productivity Series Ethernet", + "doc_channels": "/config/v1/doc/drivers/AutomationDirect%20Productivity%20Series%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/AutomationDirect%20Productivity%20Series%20Ethernet/devices" + }, + { + "namespace": "bacnet", + "display_name": "BACnet/IP", + "doc_channels": "/config/v1/doc/drivers/BACnet%2FIP/channels", + "doc_devices": "/config/v1/doc/drivers/BACnet%2FIP/devices" + }, + { + "namespace": "beckhoff_twincat", + "display_name": "Beckhoff TwinCAT", + "doc_channels": "/config/v1/doc/drivers/Beckhoff%20TwinCAT/channels", + "doc_devices": "/config/v1/doc/drivers/Beckhoff%20TwinCAT/devices" + }, + { + "namespace": "bristol_bsap_ip", + "display_name": "Bristol BSAP IP", + "doc_channels": "/config/v1/doc/drivers/Bristol%20BSAP%20IP/channels", + "doc_devices": "/config/v1/doc/drivers/Bristol%20BSAP%20IP/devices" + }, + { + "namespace": "busware_ethernet", + "display_name": "Busware Ethernet", + "doc_channels": "/config/v1/doc/drivers/Busware%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Busware%20Ethernet/devices" + }, + { + "namespace": "codesys", + "display_name": "CODESYS", + "doc_channels": "/config/v1/doc/drivers/CODESYS/channels", + "doc_devices": "/config/v1/doc/drivers/CODESYS/devices" + }, + { + "namespace": "mtrim", + "display_name": "Contrex M-Series", + "doc_channels": "/config/v1/doc/drivers/Contrex%20M-Series/channels", + "doc_devices": "/config/v1/doc/drivers/Contrex%20M-Series/devices" + }, + { + "namespace": "contrex", + "display_name": "Contrex Serial", + "doc_channels": "/config/v1/doc/drivers/Contrex%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Contrex%20Serial/devices" + }, + { + "namespace": "custom_interface", + "display_name": "Custom Interface", + "doc_channels": "/config/v1/doc/drivers/Custom%20Interface/channels", + "doc_devices": "/config/v1/doc/drivers/Custom%20Interface/devices" + }, + { + "namespace": "cutlerhammer", + "display_name": "Cutler-Hammer D50/300", + "doc_channels": "/config/v1/doc/drivers/Cutler-Hammer%20D50%2F300/channels", + "doc_devices": "/config/v1/doc/drivers/Cutler-Hammer%20D50%2F300/devices" + }, + { + "namespace": "cutlerhammer_elc_ethernet", + "display_name": "Cutler-Hammer ELC Ethernet", + "doc_channels": "/config/v1/doc/drivers/Cutler-Hammer%20ELC%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Cutler-Hammer%20ELC%20Ethernet/devices" + }, + { + "namespace": "cutlerhammer_elc_serial", + "display_name": "Cutler-Hammer ELC Serial", + "doc_channels": "/config/v1/doc/drivers/Cutler-Hammer%20ELC%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Cutler-Hammer%20ELC%20Serial/devices" + }, + { + "namespace": "dataforth_isolynx", + "display_name": "Dataforth IsoLynx", + "doc_channels": "/config/v1/doc/drivers/Dataforth%20IsoLynx/channels", + "doc_devices": "/config/v1/doc/drivers/Dataforth%20IsoLynx/devices" + }, + { + "namespace": "ddeclient", + "display_name": "DDE Client", + "doc_channels": "/config/v1/doc/drivers/DDE%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/DDE%20Client/devices" + }, + { + "namespace": "dnp_master_ethernet", + "display_name": "DNP Client Ethernet", + "doc_channels": "/config/v1/doc/drivers/DNP%20Client%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/DNP%20Client%20Ethernet/devices" + }, + { + "namespace": "dnp_master_serial", + "display_name": "DNP Client Serial", + "doc_channels": "/config/v1/doc/drivers/DNP%20Client%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/DNP%20Client%20Serial/devices" + }, + { + "namespace": "enron_modbus", + "display_name": "Enron Modbus", + "doc_channels": "/config/v1/doc/drivers/Enron%20Modbus/channels", + "doc_devices": "/config/v1/doc/drivers/Enron%20Modbus/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Enron%20Modbus/meter_groups", + "doc_meters": "/config/v1/doc/enron_meters" + }, + { + "namespace": "euromap_63", + "display_name": "EUROMAP 63", + "doc_channels": "/config/v1/doc/drivers/EUROMAP%2063/channels", + "doc_devices": "/config/v1/doc/drivers/EUROMAP%2063/devices" + }, + { + "namespace": "ge_focas1_ethernet", + "display_name": "Fanuc Focas Ethernet", + "doc_channels": "/config/v1/doc/drivers/Fanuc%20Focas%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Fanuc%20Focas%20Ethernet/devices" + }, + { + "namespace": "ge_focas1_hssb", + "display_name": "Fanuc Focas HSSB", + "doc_channels": "/config/v1/doc/drivers/Fanuc%20Focas%20HSSB/channels", + "doc_devices": "/config/v1/doc/drivers/Fanuc%20Focas%20HSSB/devices" + }, + { + "namespace": "fisher_roc_ethernet", + "display_name": "Fisher ROC Ethernet", + "doc_channels": "/config/v1/doc/drivers/Fisher%20ROC%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Fisher%20ROC%20Ethernet/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Fisher%20ROC%20Ethernet/meter_groups", + "doc_meters": "/config/v1/doc/fisher_roc_ethernet_meters" + }, + { + "namespace": "fisher_rocplus_ethernet", + "display_name": "Fisher ROC Plus Ethernet", + "doc_channels": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Ethernet/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Ethernet/meter_groups", + "doc_meters": "/config/v1/doc/fisher_rocplus_ethernet_meters" + }, + { + "namespace": "fisher_rocplus_serial", + "display_name": "Fisher ROC Plus Serial", + "doc_channels": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Serial/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Fisher%20ROC%20Plus%20Serial/meter_groups", + "doc_meters": "/config/v1/doc/fisher_rocplus_serial_meters" + }, + { + "namespace": "fisher_roc_serial", + "display_name": "Fisher ROC Serial", + "doc_channels": "/config/v1/doc/drivers/Fisher%20ROC%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Fisher%20ROC%20Serial/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Fisher%20ROC%20Serial/meter_groups", + "doc_meters": "/config/v1/doc/fisher_roc_serial_meters" + }, + { + "namespace": "fuji_flex", + "display_name": "Fuji Flex", + "doc_channels": "/config/v1/doc/drivers/Fuji%20Flex/channels", + "doc_devices": "/config/v1/doc/drivers/Fuji%20Flex/devices" + }, + { + "namespace": "ge_ccm", + "display_name": "GE CCM", + "doc_channels": "/config/v1/doc/drivers/GE%20CCM/channels", + "doc_devices": "/config/v1/doc/drivers/GE%20CCM/devices" + }, + { + "namespace": "ge_ethernet", + "display_name": "GE Ethernet", + "doc_channels": "/config/v1/doc/drivers/GE%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/GE%20Ethernet/devices" + }, + { + "namespace": "ge_ethernet_global_data", + "display_name": "GE Ethernet Global Data", + "doc_channels": "/config/v1/doc/drivers/GE%20Ethernet%20Global%20Data/channels", + "doc_devices": "/config/v1/doc/drivers/GE%20Ethernet%20Global%20Data/devices" + }, + { + "namespace": "gesnp", + "display_name": "GE SNP", + "doc_channels": "/config/v1/doc/drivers/GE%20SNP/channels", + "doc_devices": "/config/v1/doc/drivers/GE%20SNP/devices" + }, + { + "namespace": "gesnpx", + "display_name": "GE SNPX", + "doc_channels": "/config/v1/doc/drivers/GE%20SNPX/channels", + "doc_devices": "/config/v1/doc/drivers/GE%20SNPX/devices" + }, + { + "namespace": "honeywell_hc900_ethernet", + "display_name": "Honeywell HC900 Ethernet", + "doc_channels": "/config/v1/doc/drivers/Honeywell%20HC900%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Honeywell%20HC900%20Ethernet/devices" + }, + { + "namespace": "honeywell_udc_ethernet", + "display_name": "Honeywell UDC Ethernet", + "doc_channels": "/config/v1/doc/drivers/Honeywell%20UDC%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Honeywell%20UDC%20Ethernet/devices" + }, + { + "namespace": "honeywell_udc", + "display_name": "Honeywell UDC Serial", + "doc_channels": "/config/v1/doc/drivers/Honeywell%20UDC%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Honeywell%20UDC%20Serial/devices" + }, + { + "namespace": "iai_super_sel", + "display_name": "IA Super SEL", + "doc_channels": "/config/v1/doc/drivers/IA%20Super%20SEL/channels", + "doc_devices": "/config/v1/doc/drivers/IA%20Super%20SEL/devices" + }, + { + "namespace": "idec", + "display_name": "Idec Serial", + "doc_channels": "/config/v1/doc/drivers/Idec%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Idec%20Serial/devices" + }, + { + "namespace": "iec_60870_5_101_master", + "display_name": "IEC 60870-5-101 Client", + "doc_channels": "/config/v1/doc/drivers/IEC%2060870-5-101%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/IEC%2060870-5-101%20Client/devices" + }, + { + "namespace": "iec_60870_5_104_master", + "display_name": "IEC 60870-5-104 Client", + "doc_channels": "/config/v1/doc/drivers/IEC%2060870-5-104%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/IEC%2060870-5-104%20Client/devices" + }, + { + "namespace": "iec_61850_mms_client", + "display_name": "IEC 61850 MMS Client", + "doc_channels": "/config/v1/doc/drivers/IEC%2061850%20MMS%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/IEC%2061850%20MMS%20Client/devices" + }, + { + "namespace": "iotechpointscan100", + "display_name": "IOtech PointScan 100", + "doc_channels": "/config/v1/doc/drivers/IOtech%20PointScan%20100/channels", + "doc_devices": "/config/v1/doc/drivers/IOtech%20PointScan%20100/devices" + }, + { + "namespace": "keyence_kv_ethernet", + "display_name": "Keyence KV Ethernet", + "doc_channels": "/config/v1/doc/drivers/Keyence%20KV%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Keyence%20KV%20Ethernet/devices" + }, + { + "namespace": "kraussmaffei_mc4_ethernet", + "display_name": "KraussMaffei MC4 Ethernet", + "doc_channels": "/config/v1/doc/drivers/KraussMaffei%20MC4%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/KraussMaffei%20MC4%20Ethernet/devices" + }, + { + "namespace": "lufkin_modbus", + "display_name": "Lufkin Modbus Serial", + "doc_channels": "/config/v1/doc/drivers/Lufkin%20Modbus%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Lufkin%20Modbus%20Serial/devices" + }, + { + "namespace": "memory_based", + "display_name": "Memory Based", + "doc_channels": "/config/v1/doc/drivers/Memory%20Based/channels", + "doc_devices": "/config/v1/doc/drivers/Memory%20Based/devices" + }, + { + "namespace": "mettler_toledo_serial", + "display_name": "Mettler Toledo Serial", + "doc_channels": "/config/v1/doc/drivers/Mettler%20Toledo%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Mettler%20Toledo%20Serial/devices" + }, + { + "namespace": "micro_dci", + "display_name": "Micro DCI", + "doc_channels": "/config/v1/doc/drivers/Micro%20DCI/channels", + "doc_devices": "/config/v1/doc/drivers/Micro%20DCI/devices" + }, + { + "namespace": "mitsubishi_cnc_ethernet", + "display_name": "Mitsubishi CNC Ethernet", + "doc_channels": "/config/v1/doc/drivers/Mitsubishi%20CNC%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Mitsubishi%20CNC%20Ethernet/devices" + }, + { + "namespace": "mitsubishi_ethernet", + "display_name": "Mitsubishi Ethernet", + "doc_channels": "/config/v1/doc/drivers/Mitsubishi%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Mitsubishi%20Ethernet/devices" + }, + { + "namespace": "mitsubishifx", + "display_name": "Mitsubishi FX", + "doc_channels": "/config/v1/doc/drivers/Mitsubishi%20FX/channels", + "doc_devices": "/config/v1/doc/drivers/Mitsubishi%20FX/devices" + }, + { + "namespace": "mitsubishifxnet", + "display_name": "Mitsubishi FX Net", + "doc_channels": "/config/v1/doc/drivers/Mitsubishi%20FX%20Net/channels", + "doc_devices": "/config/v1/doc/drivers/Mitsubishi%20FX%20Net/devices" + }, + { + "namespace": "mitsubishi_serial", + "display_name": "Mitsubishi Serial", + "doc_channels": "/config/v1/doc/drivers/Mitsubishi%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Mitsubishi%20Serial/devices" + }, + { + "namespace": "modbus_ascii", + "display_name": "Modbus ASCII Serial", + "doc_channels": "/config/v1/doc/drivers/Modbus%20ASCII%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Modbus%20ASCII%20Serial/devices" + }, + { + "namespace": "modbus_plus", + "display_name": "Modbus Plus", + "doc_channels": "/config/v1/doc/drivers/Modbus%20Plus/channels", + "doc_devices": "/config/v1/doc/drivers/Modbus%20Plus/devices" + }, + { + "namespace": "modbus", + "display_name": "Modbus RTU Serial", + "doc_channels": "/config/v1/doc/drivers/Modbus%20RTU%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Modbus%20RTU%20Serial/devices" + }, + { + "namespace": "modbus_unsolicited", + "display_name": "Modbus RTU Server Serial", + "doc_channels": "/config/v1/doc/drivers/Modbus%20RTU%20Server%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Modbus%20RTU%20Server%20Serial/devices" + }, + { + "namespace": "modbus_ethernet", + "display_name": "Modbus TCP/IP Ethernet", + "doc_channels": "/config/v1/doc/drivers/Modbus%20TCP%2FIP%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Modbus%20TCP%2FIP%20Ethernet/devices" + }, + { + "namespace": "mqtt_client", + "display_name": "MQTT Client", + "doc_channels": "/config/v1/doc/drivers/MQTT%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/MQTT%20Client/devices" + }, + { + "namespace": "mtconnect_client", + "display_name": "MTConnect Client", + "doc_channels": "/config/v1/doc/drivers/MTConnect%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/MTConnect%20Client/devices" + }, + { + "namespace": "omni_flow_computer", + "display_name": "Omni Flow Computer", + "doc_channels": "/config/v1/doc/drivers/Omni%20Flow%20Computer/channels", + "doc_devices": "/config/v1/doc/drivers/Omni%20Flow%20Computer/devices", + "doc_meter_groups": "/config/v1/doc/drivers/Omni%20Flow%20Computer/meter_groups", + "doc_meters": "/config/v1/doc/omni_meters" + }, + { + "namespace": "omron_fins_ethernet", + "display_name": "Omron FINS Ethernet", + "doc_channels": "/config/v1/doc/drivers/Omron%20FINS%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20FINS%20Ethernet/devices" + }, + { + "namespace": "omron_fins_serial", + "display_name": "Omron FINS Serial", + "doc_channels": "/config/v1/doc/drivers/Omron%20FINS%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20FINS%20Serial/devices" + }, + { + "namespace": "omronhl", + "display_name": "Omron Host Link", + "doc_channels": "/config/v1/doc/drivers/Omron%20Host%20Link/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20Host%20Link/devices" + }, + { + "namespace": "omron_nj_ethernet", + "display_name": "Omron NJ Ethernet", + "doc_channels": "/config/v1/doc/drivers/Omron%20NJ%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20NJ%20Ethernet/devices" + }, + { + "namespace": "omron_process_suite", + "display_name": "Omron Process Suite", + "doc_channels": "/config/v1/doc/drivers/Omron%20Process%20Suite/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20Process%20Suite/devices" + }, + { + "namespace": "omron_toolbus", + "display_name": "Omron Toolbus", + "doc_channels": "/config/v1/doc/drivers/Omron%20Toolbus/channels", + "doc_devices": "/config/v1/doc/drivers/Omron%20Toolbus/devices" + }, + { + "namespace": "opcdaclient", + "display_name": "OPC DA Client", + "doc_channels": "/config/v1/doc/drivers/OPC%20DA%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/OPC%20DA%20Client/devices" + }, + { + "namespace": "opcuaclient", + "display_name": "OPC UA Client", + "doc_channels": "/config/v1/doc/drivers/OPC%20UA%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/OPC%20UA%20Client/devices" + }, + { + "namespace": "opcxmldaclient", + "display_name": "OPC XML-DA Client", + "doc_channels": "/config/v1/doc/drivers/OPC%20XML-DA%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/OPC%20XML-DA%20Client/devices" + }, + { + "namespace": "optilogic", + "display_name": "Optimation OptiLogic", + "doc_channels": "/config/v1/doc/drivers/Optimation%20OptiLogic/channels", + "doc_devices": "/config/v1/doc/drivers/Optimation%20OptiLogic/devices" + }, + { + "namespace": "opto22_ethernet", + "display_name": "Opto 22 Ethernet", + "doc_channels": "/config/v1/doc/drivers/Opto%2022%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Opto%2022%20Ethernet/devices" + }, + { + "namespace": "partlow_ascii", + "display_name": "Partlow ASCII", + "doc_channels": "/config/v1/doc/drivers/Partlow%20ASCII/channels", + "doc_devices": "/config/v1/doc/drivers/Partlow%20ASCII/devices" + }, + { + "namespace": "philips_p8_pc20", + "display_name": "Philips P8/PC20", + "doc_channels": "/config/v1/doc/drivers/Philips%20P8%2FPC20/channels", + "doc_devices": "/config/v1/doc/drivers/Philips%20P8%2FPC20/devices" + }, + { + "namespace": "ping", + "display_name": "Ping", + "doc_channels": "/config/v1/doc/drivers/Ping/channels", + "doc_devices": "/config/v1/doc/drivers/Ping/devices" + }, + { + "namespace": "sattbus_ethernet", + "display_name": "SattBus Ethernet", + "doc_channels": "/config/v1/doc/drivers/SattBus%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/SattBus%20Ethernet/devices" + }, + { + "namespace": "scanivalve_ethernet", + "display_name": "Scanivalve Ethernet", + "doc_channels": "/config/v1/doc/drivers/Scanivalve%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Scanivalve%20Ethernet/devices" + }, + { + "namespace": "siemens_s5_3964r", + "display_name": "Siemens S5 (3964R)", + "doc_channels": "/config/v1/doc/drivers/Siemens%20S5%20(3964R)/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20S5%20(3964R)/devices" + }, + { + "namespace": "siemens_s5", + "display_name": "Siemens S5 (AS511)", + "doc_channels": "/config/v1/doc/drivers/Siemens%20S5%20(AS511)/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20S5%20(AS511)/devices" + }, + { + "namespace": "s7_mpi", + "display_name": "Siemens S7 MPI", + "doc_channels": "/config/v1/doc/drivers/Siemens%20S7%20MPI/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20S7%20MPI/devices" + }, + { + "namespace": "siemens_s7_plus_ethernet", + "display_name": "Siemens S7 Plus Ethernet", + "doc_channels": "/config/v1/doc/drivers/Siemens%20S7%20Plus%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20S7%20Plus%20Ethernet/devices" + }, + { + "namespace": "siemens_s7_200", + "display_name": "Siemens S7-200", + "doc_channels": "/config/v1/doc/drivers/Siemens%20S7-200/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20S7-200/devices" + }, + { + "namespace": "siemens_tcpip_ethernet", + "display_name": "Siemens TCP/IP Ethernet", + "doc_channels": "/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Ethernet/devices" + }, + { + "namespace": "siemens_tcpip_unsolicited_ethernet", + "display_name": "Siemens TCP/IP Server Ethernet", + "doc_channels": "/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Server%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Server%20Ethernet/devices" + }, + { + "namespace": "simatic505_ethernet", + "display_name": "Simatic/TI 505 Ethernet", + "doc_channels": "/config/v1/doc/drivers/Simatic%2FTI%20505%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Simatic%2FTI%20505%20Ethernet/devices" + }, + { + "namespace": "simatic505_serial", + "display_name": "Simatic/TI 505 Serial", + "doc_channels": "/config/v1/doc/drivers/Simatic%2FTI%20505%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Simatic%2FTI%20505%20Serial/devices" + }, + { + "namespace": "simulator", + "display_name": "Simulator", + "doc_channels": "/config/v1/doc/drivers/Simulator/channels", + "doc_devices": "/config/v1/doc/drivers/Simulator/devices" + }, + { + "namespace": "ethertrak", + "display_name": "SIXNET EtherTRAK", + "doc_channels": "/config/v1/doc/drivers/SIXNET%20EtherTRAK/channels", + "doc_devices": "/config/v1/doc/drivers/SIXNET%20EtherTRAK/devices" + }, + { + "namespace": "sixnet_udr", + "display_name": "SIXNET UDR", + "doc_channels": "/config/v1/doc/drivers/SIXNET%20UDR/channels", + "doc_devices": "/config/v1/doc/drivers/SIXNET%20UDR/devices" + }, + { + "namespace": "snmp", + "display_name": "SNMP", + "doc_channels": "/config/v1/doc/drivers/SNMP/channels", + "doc_devices": "/config/v1/doc/drivers/SNMP/devices" + }, + { + "namespace": "squared", + "display_name": "SquareD Serial", + "doc_channels": "/config/v1/doc/drivers/SquareD%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/SquareD%20Serial/devices" + }, + { + "namespace": "system_monitor", + "display_name": "System Monitor", + "doc_channels": "/config/v1/doc/drivers/System%20Monitor/channels", + "doc_devices": "/config/v1/doc/drivers/System%20Monitor/devices" + }, + { + "namespace": "unitelway", + "display_name": "Telemecanique Uni-Telway", + "doc_channels": "/config/v1/doc/drivers/Telemecanique%20Uni-Telway/channels", + "doc_devices": "/config/v1/doc/drivers/Telemecanique%20Uni-Telway/devices" + }, + { + "namespace": "thermowestronics_ethernet", + "display_name": "Thermo Westronics Ethernet", + "doc_channels": "/config/v1/doc/drivers/Thermo%20Westronics%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Thermo%20Westronics%20Ethernet/devices" + }, + { + "namespace": "thermowestronics_serial", + "display_name": "Thermo Westronics Serial", + "doc_channels": "/config/v1/doc/drivers/Thermo%20Westronics%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Thermo%20Westronics%20Serial/devices" + }, + { + "namespace": "tiway_host_adapter", + "display_name": "TIWAY Host Adapter", + "doc_channels": "/config/v1/doc/drivers/TIWAY%20Host%20Adapter/channels", + "doc_devices": "/config/v1/doc/drivers/TIWAY%20Host%20Adapter/devices" + }, + { + "namespace": "torque_tool_ethernet", + "display_name": "Torque Tool Ethernet", + "doc_channels": "/config/v1/doc/drivers/Torque%20Tool%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Torque%20Tool%20Ethernet/devices" + }, + { + "namespace": "toshiba_ethernet", + "display_name": "Toshiba Ethernet", + "doc_channels": "/config/v1/doc/drivers/Toshiba%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Toshiba%20Ethernet/devices" + }, + { + "namespace": "toshiba", + "display_name": "Toshiba Serial", + "doc_channels": "/config/v1/doc/drivers/Toshiba%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Toshiba%20Serial/devices" + }, + { + "namespace": "toyopuc_serial", + "display_name": "Toyopuc PC2 Serial", + "doc_channels": "/config/v1/doc/drivers/Toyopuc%20PC2%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Toyopuc%20PC2%20Serial/devices" + }, + { + "namespace": "toyopuc_ethernet_pc3", + "display_name": "Toyopuc PC3/PC2 Ethernet", + "doc_channels": "/config/v1/doc/drivers/Toyopuc%20PC3%2FPC2%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Toyopuc%20PC3%2FPC2%20Ethernet/devices" + }, + { + "namespace": "triconex_ethernet", + "display_name": "Triconex Ethernet", + "doc_channels": "/config/v1/doc/drivers/Triconex%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Triconex%20Ethernet/devices" + }, + { + "namespace": "userconfigdrv", + "display_name": "U-CON (user-configurable)", + "doc_channels": "/config/v1/doc/drivers/U-CON%20(user-configurable)/channels", + "doc_devices": "/config/v1/doc/drivers/U-CON%20(user-configurable)/devices" + }, + { + "namespace": "universal_device", + "display_name": "Universal Device", + "doc_channels": "/config/v1/doc/drivers/Universal%20Device/channels", + "doc_devices": "/config/v1/doc/drivers/Universal%20Device/devices" + }, + { + "namespace": "wago_ethernet", + "display_name": "Wago Ethernet", + "doc_channels": "/config/v1/doc/drivers/Wago%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Wago%20Ethernet/devices" + }, + { + "namespace": "weatherford_8500", + "display_name": "Weatherford 8500 Serial", + "doc_channels": "/config/v1/doc/drivers/Weatherford%208500%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Weatherford%208500%20Serial/devices" + }, + { + "namespace": "wits_level_0_active", + "display_name": "WITS Level 0 Active", + "doc_channels": "/config/v1/doc/drivers/WITS%20Level%200%20Active/channels", + "doc_devices": "/config/v1/doc/drivers/WITS%20Level%200%20Active/devices" + }, + { + "namespace": "wits_level_0_passive", + "display_name": "WITS Level 0 Passive", + "doc_channels": "/config/v1/doc/drivers/WITS%20Level%200%20Passive/channels", + "doc_devices": "/config/v1/doc/drivers/WITS%20Level%200%20Passive/devices" + }, + { + "namespace": "intouchclient", + "display_name": "Wonderware InTouch Client", + "doc_channels": "/config/v1/doc/drivers/Wonderware%20InTouch%20Client/channels", + "doc_devices": "/config/v1/doc/drivers/Wonderware%20InTouch%20Client/devices" + }, + { + "namespace": "yaskawa_memobus_plus", + "display_name": "Yaskawa Memobus Plus (SA85)", + "doc_channels": "/config/v1/doc/drivers/Yaskawa%20Memobus%20Plus%20(SA85)/channels", + "doc_devices": "/config/v1/doc/drivers/Yaskawa%20Memobus%20Plus%20(SA85)/devices" + }, + { + "namespace": "yaskawa_mp_ethernet", + "display_name": "Yaskawa MP Series Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yaskawa%20MP%20Series%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yaskawa%20MP%20Series%20Ethernet/devices" + }, + { + "namespace": "yaskawa_mp_serial", + "display_name": "Yaskawa MP Series Serial", + "doc_channels": "/config/v1/doc/drivers/Yaskawa%20MP%20Series%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Yaskawa%20MP%20Series%20Serial/devices" + }, + { + "namespace": "yokogawa_controller_serial", + "display_name": "Yokogawa Controller", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20Controller/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20Controller/devices" + }, + { + "namespace": "yokogawa_cx", + "display_name": "Yokogawa CX Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20CX%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20CX%20Ethernet/devices" + }, + { + "namespace": "yokogawa_darwin", + "display_name": "Yokogawa Darwin Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20Darwin%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20Darwin%20Ethernet/devices" + }, + { + "namespace": "yokogawa_darwin_serial", + "display_name": "Yokogawa Darwin Serial", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20Darwin%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20Darwin%20Serial/devices" + }, + { + "namespace": "yokogawa_dx", + "display_name": "Yokogawa DX Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20DX%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20DX%20Ethernet/devices" + }, + { + "namespace": "yokogawa_dx_serial", + "display_name": "Yokogawa DX Serial", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20DX%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20DX%20Serial/devices" + }, + { + "namespace": "yokogawa_dxp", + "display_name": "Yokogawa DXP Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20DXP%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20DXP%20Ethernet/devices" + }, + { + "namespace": "yokogawa_gx", + "display_name": "Yokogawa GX Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20GX%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20GX%20Ethernet/devices" + }, + { + "namespace": "yokogawa_hr", + "display_name": "Yokogawa HR2400 Serial", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20HR2400%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20HR2400%20Serial/devices" + }, + { + "namespace": "yokogawa_mw", + "display_name": "Yokogawa MW Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20MW%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20MW%20Ethernet/devices" + }, + { + "namespace": "yokogawa_mx", + "display_name": "Yokogawa MX Ethernet", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20MX%20Ethernet/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20MX%20Ethernet/devices" + }, + { + "namespace": "yokogawa_ys100_serial", + "display_name": "Yokogawa YS100 Serial", + "doc_channels": "/config/v1/doc/drivers/Yokogawa%20YS100%20Serial/channels", + "doc_devices": "/config/v1/doc/drivers/Yokogawa%20YS100%20Serial/devices" + } +] \ No newline at end of file diff --git a/Kepware.Api.TestIntg/_data/simdemo_en-us.json b/Kepware.Api.TestIntg/_data/simdemo_en-us.json new file mode 100644 index 0000000..ce4243c --- /dev/null +++ b/Kepware.Api.TestIntg/_data/simdemo_en-us.json @@ -0,0 +1,2432 @@ +{ + "project": { + "common.ALLTYPES_DESCRIPTION": "Example project utilizing Simulator Driver.", + "servermain.PROJECT_TITLE": "Simulation Driver Demo", + "channels": [ + { + "common.ALLTYPES_NAME": "Channel1", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Channel", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.CHANNEL_DIAGNOSTICS_CAPTURE": false, + "servermain.CHANNEL_UNIQUE_ID": 1704486747, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_METHOD": 2, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_DUTY_CYCLE": 10, + "servermain.CHANNEL_NON_NORMALIZED_FLOATING_POINT_HANDLING": 0, + "simulator.CHANNEL_ITEM_PERSISTENCE": false, + "simulator.CHANNEL_ITEM_PERSISTENCE_DATA_FILE": "C:\\ProgramData\\Kepware\\KEPServerEX\\V6\\Simulator\\Channel1.dat", + "devices": [ + { + "common.ALLTYPES_NAME": "Device1", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Device", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.DEVICE_MODEL": 0, + "servermain.DEVICE_UNIQUE_ID": 1808204482, + "servermain.DEVICE_ID_FORMAT": 1, + "servermain.DEVICE_ID_STRING": "1", + "servermain.DEVICE_ID_HEXADECIMAL": 1, + "servermain.DEVICE_ID_DECIMAL": 1, + "servermain.DEVICE_ID_OCTAL": 1, + "servermain.DEVICE_DATA_COLLECTION": true, + "servermain.DEVICE_SCAN_MODE": 0, + "servermain.DEVICE_SCAN_MODE_RATE_MS": 1000, + "servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE": false, + "tags": [ + { + "common.ALLTYPES_NAME": "Tag1", + "common.ALLTYPES_DESCRIPTION": "Ramping Read/Write tag used to verify client connection", + "servermain.TAG_ADDRESS": "R0001", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Tag2", + "common.ALLTYPES_DESCRIPTION": "Constant Read/Write tag used to verify client connection", + "servermain.TAG_ADDRESS": "K0001", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + } + ] + }, + { + "common.ALLTYPES_NAME": "Data Type Examples", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Channel", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.CHANNEL_DIAGNOSTICS_CAPTURE": false, + "servermain.CHANNEL_UNIQUE_ID": 3467605889, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_METHOD": 2, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_DUTY_CYCLE": 10, + "servermain.CHANNEL_NON_NORMALIZED_FLOATING_POINT_HANDLING": 0, + "simulator.CHANNEL_ITEM_PERSISTENCE": false, + "simulator.CHANNEL_ITEM_PERSISTENCE_DATA_FILE": "C:\\ProgramData\\Kepware\\KEPServerEX\\V6\\Simulator\\Data Type Examples.dat", + "devices": [ + { + "common.ALLTYPES_NAME": "16 Bit Device", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Device", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.DEVICE_MODEL": 0, + "servermain.DEVICE_UNIQUE_ID": 18472794, + "servermain.DEVICE_ID_FORMAT": 1, + "servermain.DEVICE_ID_STRING": "3", + "servermain.DEVICE_ID_HEXADECIMAL": 3, + "servermain.DEVICE_ID_DECIMAL": 3, + "servermain.DEVICE_ID_OCTAL": 3, + "servermain.DEVICE_DATA_COLLECTION": true, + "servermain.DEVICE_SCAN_MODE": 0, + "servermain.DEVICE_SCAN_MODE_RATE_MS": 1000, + "servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE": false, + "tag_groups": [ + { + "common.ALLTYPES_NAME": "B Registers", + "common.ALLTYPES_DESCRIPTION": "Boolean registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0001", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0002", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0003", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0004", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "BooleanArray", + "common.ALLTYPES_DESCRIPTION": "Array of 4 Boolean Registers", + "servermain.TAG_ADDRESS": "B0010 [4]", + "servermain.TAG_DATA_TYPE": 21, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "K Registers", + "common.ALLTYPES_DESCRIPTION": "Constant Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.00", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.01", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.02", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.03", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double1", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0400", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double2", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0404", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double3", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0408", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double4", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0412", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DoubleArray", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "K0440 [4]", + "servermain.TAG_DATA_TYPE": 29, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord1", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0500", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord2", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0502", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord3", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0504", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord4", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0506", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWordArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "K0550 [4]", + "servermain.TAG_DATA_TYPE": 27, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float1", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0600", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float2", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0602", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float3", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0604", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float4", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0606", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "FloatArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "K0660 [4]", + "servermain.TAG_DATA_TYPE": 28, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong1", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1200", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong2", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1204", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong3", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1208", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong4", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1212", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLongArray", + "common.ALLTYPES_DESCRIPTION": "64-bit signed integer array", + "servermain.TAG_ADDRESS": "K1240 [4]", + "servermain.TAG_DATA_TYPE": 33, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long1", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0700", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long2", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0702", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long3", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0704", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long4", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0706", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LongArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer array", + "servermain.TAG_ADDRESS": "K0770 [4]", + "servermain.TAG_DATA_TYPE": 26, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord1", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1100", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord2", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1104", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord3", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1108", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord4", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1112", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWordArray", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned Integer array", + "servermain.TAG_ADDRESS": "K1140 [4]", + "servermain.TAG_DATA_TYPE": 34, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short1", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0800", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short2", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0801", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short3", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0802", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short4", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0803", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ShortArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer array", + "servermain.TAG_ADDRESS": "K0880 [4]", + "servermain.TAG_DATA_TYPE": 24, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word1", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0900", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word2", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0901", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word3", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0902", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word4", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0903", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "WordArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "K0990 [4]", + "servermain.TAG_DATA_TYPE": 25, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "R Registers", + "common.ALLTYPES_DESCRIPTION": "Ramping Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.00", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.01", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.02", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.03", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double1", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0400", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double2", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0404", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double3", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0408", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double4", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0412", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DoubleArray", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "R0440 [4]", + "servermain.TAG_DATA_TYPE": 29, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord1", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0500", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord2", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0502", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord3", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0504", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord4", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0506", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWordArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "R0550 [4]", + "servermain.TAG_DATA_TYPE": 27, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float1", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0600", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float2", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0602", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float3", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0604", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float4", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0606", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "FloatArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "R0660 [4]", + "servermain.TAG_DATA_TYPE": 28, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong1", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1200", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong2", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1204", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong3", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1208", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong4", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1212", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLongArray", + "common.ALLTYPES_DESCRIPTION": "64-bit signed integer array", + "servermain.TAG_ADDRESS": "R1240 [4]", + "servermain.TAG_DATA_TYPE": 33, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long1", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0700", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long2", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0702", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long3", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0704", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long4", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0706", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LongArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer array", + "servermain.TAG_ADDRESS": "R0770 [4]", + "servermain.TAG_DATA_TYPE": 26, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord1", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1100", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord2", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1104", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord3", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1108", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord4", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1112", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWordArray", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned Integer array", + "servermain.TAG_ADDRESS": "R1140 [4]", + "servermain.TAG_DATA_TYPE": 34, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short1", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0800", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short2", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0801", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short3", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0802", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short4", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0803", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ShortArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer array", + "servermain.TAG_ADDRESS": "R0880 [4]", + "servermain.TAG_DATA_TYPE": 24, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word1", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0900", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word2", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0901", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word3", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0902", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word4", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0903", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "WordArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "R0990 [4]", + "servermain.TAG_DATA_TYPE": 25, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "S Registers", + "common.ALLTYPES_DESCRIPTION": "String Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "String1", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0001", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String2", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0002", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String3", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0003", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String4", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0004", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "StringArray[4]", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string array", + "servermain.TAG_ADDRESS": "S0010 [4]", + "servermain.TAG_DATA_TYPE": 20, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + } + ] + }, + { + "common.ALLTYPES_NAME": "8 Bit Device", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Device", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.DEVICE_MODEL": 1, + "servermain.DEVICE_UNIQUE_ID": 881303962, + "servermain.DEVICE_ID_FORMAT": 1, + "servermain.DEVICE_ID_STRING": "2", + "servermain.DEVICE_ID_HEXADECIMAL": 2, + "servermain.DEVICE_ID_DECIMAL": 2, + "servermain.DEVICE_ID_OCTAL": 2, + "servermain.DEVICE_DATA_COLLECTION": true, + "servermain.DEVICE_SCAN_MODE": 0, + "servermain.DEVICE_SCAN_MODE_RATE_MS": 1000, + "servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE": false, + "tag_groups": [ + { + "common.ALLTYPES_NAME": "B Registers", + "common.ALLTYPES_DESCRIPTION": "Boolean registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0001", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0002", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0003", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "Boolean register", + "servermain.TAG_ADDRESS": "B0004", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "BooleanArray", + "common.ALLTYPES_DESCRIPTION": "Array of 4 Boolean Registers", + "servermain.TAG_ADDRESS": "B0010 [4]", + "servermain.TAG_DATA_TYPE": 21, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "K Registers", + "common.ALLTYPES_DESCRIPTION": "Constant Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.00", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.01", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.02", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "K0100.03", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte1", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0200", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte2", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0201", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte3", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0202", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte4", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0203", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ByteArray", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "K0220 [4]", + "servermain.TAG_DATA_TYPE": 23, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char1", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "K0300", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char2", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "K0301", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char3", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "K0302", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char4", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "K0303", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "CharArray", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer array", + "servermain.TAG_ADDRESS": "K0330 [4]", + "servermain.TAG_DATA_TYPE": 22, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double1", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0400", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double2", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0408", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double3", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0416", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double4", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0424", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DoubleArray", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "K0440 [4]", + "servermain.TAG_DATA_TYPE": 29, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord1", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0500", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord2", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0504", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord3", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0508", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord4", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0512", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWordArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "K0550 [4]", + "servermain.TAG_DATA_TYPE": 27, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float1", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0600", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float2", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0604", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float3", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0608", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float4", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "K0612", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "FloatArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "K0660 [4]", + "servermain.TAG_DATA_TYPE": 28, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong1", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1200", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong2", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1208", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong3", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1216", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong4", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "K1224", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLongArray", + "common.ALLTYPES_DESCRIPTION": "64-bit signed integer array", + "servermain.TAG_ADDRESS": "K1240 [4]", + "servermain.TAG_DATA_TYPE": 33, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long1", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0700", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long2", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0704", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long3", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0708", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long4", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "K0712", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LongArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer array", + "servermain.TAG_ADDRESS": "K0770 [4]", + "servermain.TAG_DATA_TYPE": 26, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord1", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1100", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord2", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1108", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord3", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1116", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord4", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "K1124", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWordArray", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned Integer array", + "servermain.TAG_ADDRESS": "K1140 [4]", + "servermain.TAG_DATA_TYPE": 34, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short1", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0800", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short2", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0802", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short3", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0804", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short4", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "K0806", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ShortArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer array", + "servermain.TAG_ADDRESS": "K0880 [4]", + "servermain.TAG_DATA_TYPE": 24, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word1", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0900", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word2", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0902", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word3", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0904", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word4", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "K0906", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "WordArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "K0990 [4]", + "servermain.TAG_DATA_TYPE": 25, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "R Registers", + "common.ALLTYPES_DESCRIPTION": "Ramping Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "Boolean1", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.00", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean2", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.01", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean3", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.02", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Boolean4", + "common.ALLTYPES_DESCRIPTION": "1-Bit Boolean", + "servermain.TAG_ADDRESS": "R0100.03", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte1", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0200", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte2", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0201", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte3", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0202", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Byte4", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0203", + "servermain.TAG_DATA_TYPE": 3, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ByteArray", + "common.ALLTYPES_DESCRIPTION": "8-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "R0220 [4]", + "servermain.TAG_DATA_TYPE": 23, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char1", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "R0300", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char2", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "R0301", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char3", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "R0302", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Char4", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer", + "servermain.TAG_ADDRESS": "R0303", + "servermain.TAG_DATA_TYPE": 2, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "CharArray", + "common.ALLTYPES_DESCRIPTION": "8-Bit signed integer array", + "servermain.TAG_ADDRESS": "R0330 [4]", + "servermain.TAG_DATA_TYPE": 22, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double1", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0400", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double2", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0408", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double3", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0416", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Double4", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0424", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DoubleArray", + "common.ALLTYPES_DESCRIPTION": "64-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "R0440 [4]", + "servermain.TAG_DATA_TYPE": 29, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord1", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0500", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord2", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0504", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord3", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0508", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWord4", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0512", + "servermain.TAG_DATA_TYPE": 7, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "DWordArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "R0550 [4]", + "servermain.TAG_DATA_TYPE": 27, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float1", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0600", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float2", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0604", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float3", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0608", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Float4", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point", + "servermain.TAG_ADDRESS": "R0612", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "FloatArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit IEEE floating point array", + "servermain.TAG_ADDRESS": "R0660 [4]", + "servermain.TAG_DATA_TYPE": 28, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong1", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1200", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong2", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1208", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong3", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1216", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLong4", + "common.ALLTYPES_DESCRIPTION": "64 bit signed integer", + "servermain.TAG_ADDRESS": "R1224", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LLongArray", + "common.ALLTYPES_DESCRIPTION": "64-bit signed integer array", + "servermain.TAG_ADDRESS": "R1240 [4]", + "servermain.TAG_DATA_TYPE": 33, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long1", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0700", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long2", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0704", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long3", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0708", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Long4", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer", + "servermain.TAG_ADDRESS": "R0712", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "LongArray", + "common.ALLTYPES_DESCRIPTION": "32-Bit signed integer array", + "servermain.TAG_ADDRESS": "R0770 [4]", + "servermain.TAG_DATA_TYPE": 26, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord1", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1100", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord2", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1108", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord3", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1116", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWord4", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned integer", + "servermain.TAG_ADDRESS": "R1124", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "QWordArray", + "common.ALLTYPES_DESCRIPTION": "64-bit unsigned Integer array", + "servermain.TAG_ADDRESS": "R1140 [4]", + "servermain.TAG_DATA_TYPE": 34, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short1", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0800", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short2", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0802", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short3", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0804", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Short4", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer", + "servermain.TAG_ADDRESS": "R0806", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "ShortArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit signed integer array", + "servermain.TAG_ADDRESS": "R0880 [4]", + "servermain.TAG_DATA_TYPE": 24, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word1", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0900", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word2", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0902", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word3", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0904", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Word4", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer", + "servermain.TAG_ADDRESS": "R0906", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "WordArray", + "common.ALLTYPES_DESCRIPTION": "16-Bit unsigned integer array", + "servermain.TAG_ADDRESS": "R0990 [4]", + "servermain.TAG_DATA_TYPE": 25, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + }, + { + "common.ALLTYPES_NAME": "S Registers", + "common.ALLTYPES_DESCRIPTION": "String Registers", + "tags": [ + { + "common.ALLTYPES_NAME": "String1", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0001", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String2", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0002", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String3", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0003", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "String4", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string", + "servermain.TAG_ADDRESS": "S0004", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "StringArray[4]", + "common.ALLTYPES_DESCRIPTION": "Null terminated Unicode string array", + "servermain.TAG_ADDRESS": "S0010 [4]", + "servermain.TAG_DATA_TYPE": 20, + "servermain.TAG_READ_WRITE_ACCESS": 1, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + } + ] + } + ] + }, + { + "common.ALLTYPES_NAME": "Simulation Examples", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Channel", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.CHANNEL_DIAGNOSTICS_CAPTURE": false, + "servermain.CHANNEL_UNIQUE_ID": 2691320731, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_METHOD": 2, + "servermain.CHANNEL_WRITE_OPTIMIZATIONS_DUTY_CYCLE": 10, + "servermain.CHANNEL_NON_NORMALIZED_FLOATING_POINT_HANDLING": 0, + "simulator.CHANNEL_ITEM_PERSISTENCE": false, + "simulator.CHANNEL_ITEM_PERSISTENCE_DATA_FILE": "C:\\ProgramData\\Kepware\\KEPServerEX\\V6\\Simulator\\Simulation Examples.dat", + "devices": [ + { + "common.ALLTYPES_NAME": "Functions", + "common.ALLTYPES_DESCRIPTION": "Example Simulator Device", + "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator", + "servermain.DEVICE_MODEL": 0, + "servermain.DEVICE_UNIQUE_ID": 2266623120, + "servermain.DEVICE_ID_FORMAT": 1, + "servermain.DEVICE_ID_STRING": "4", + "servermain.DEVICE_ID_HEXADECIMAL": 4, + "servermain.DEVICE_ID_DECIMAL": 4, + "servermain.DEVICE_ID_OCTAL": 4, + "servermain.DEVICE_DATA_COLLECTION": true, + "servermain.DEVICE_SCAN_MODE": 0, + "servermain.DEVICE_SCAN_MODE_RATE_MS": 1000, + "servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE": false, + "tags": [ + { + "common.ALLTYPES_NAME": "Ramp1", + "common.ALLTYPES_DESCRIPTION": "Value increments by 4 from 35 to 100 every 120 ms", + "servermain.TAG_ADDRESS": "RAMP (120, 35, 100, 4)", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp2", + "common.ALLTYPES_DESCRIPTION": "Value decrements by 0.25 from 200.50 to 150.75 every 300 ms", + "servermain.TAG_ADDRESS": "RAMP (300, 150.750000, 200.500000, -0.250000)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp3", + "common.ALLTYPES_DESCRIPTION": "Value increments by 1 from 0 to 1000 every 250 ms", + "servermain.TAG_ADDRESS": "RAMP (250, 0, 1000, 1)", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp4", + "common.ALLTYPES_DESCRIPTION": "Value decrements by 5 from 1000 to -1000 every 2000 ms", + "servermain.TAG_ADDRESS": "RAMP (2000, -1000, 1000, -5)", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp5", + "common.ALLTYPES_DESCRIPTION": "Value decrements by 500 from 1000000 to -1000000 every 250 ms", + "servermain.TAG_ADDRESS": "RAMP (250, -1000000, 1000000, -500)", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp6", + "common.ALLTYPES_DESCRIPTION": "Value increments by 1250 from 0 to 1 billion every 1000 ms", + "servermain.TAG_ADDRESS": "RAMP (1000, 0, 1000000000, 1250)", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp7", + "common.ALLTYPES_DESCRIPTION": "Value decrements by 1 billion to -1 billion every 1000 ms", + "servermain.TAG_ADDRESS": "RAMP (1000, -1000000000, 1000000000, -5555)", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Ramp8", + "common.ALLTYPES_DESCRIPTION": "Value decrements by 0.25 from 200.50 to 150.75 every 300 ms", + "servermain.TAG_ADDRESS": "RAMP (1000, 150.750000, 200.500000, -0.250000)", + "servermain.TAG_DATA_TYPE": 9, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random1", + "common.ALLTYPES_DESCRIPTION": "Random values from -20 to 75 that change every 30 ms", + "servermain.TAG_ADDRESS": "RANDOM (30, -20, 75)", + "servermain.TAG_DATA_TYPE": 4, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random2", + "common.ALLTYPES_DESCRIPTION": "Random values from 0 to 1000 that change every 100 ms", + "servermain.TAG_ADDRESS": "RANDOM (100, 0, 1000)", + "servermain.TAG_DATA_TYPE": 5, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random3", + "common.ALLTYPES_DESCRIPTION": "Random values from -1000 to 0 that change every 100 ms", + "servermain.TAG_ADDRESS": "RANDOM (100, -1000, 0)", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random4", + "common.ALLTYPES_DESCRIPTION": "Random values from -999 to 999 that change every 1000 ms", + "servermain.TAG_ADDRESS": "RANDOM (1000, -999, 999)", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random5", + "common.ALLTYPES_DESCRIPTION": "Random values from -1000000000 to 1000000000 that change every 100 ms", + "servermain.TAG_ADDRESS": "RANDOM (100, -1000000000, 1000000000)", + "servermain.TAG_DATA_TYPE": 6, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random6", + "common.ALLTYPES_DESCRIPTION": "Random values from -1000000 to 1000000 that change every 1000 ms", + "servermain.TAG_ADDRESS": "RANDOM (1000, -1000000, 1000000)", + "servermain.TAG_DATA_TYPE": 13, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random7", + "common.ALLTYPES_DESCRIPTION": "Random values from 0 to 1000000000 that change every 1000 ms", + "servermain.TAG_ADDRESS": "RANDOM (1000, 0, 1000000000)", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Random8", + "common.ALLTYPES_DESCRIPTION": "Random values from 0 to 1000000 that change every 100 ms", + "servermain.TAG_ADDRESS": "RANDOM (100, 0, 1000000)", + "servermain.TAG_DATA_TYPE": 14, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Sine1", + "common.ALLTYPES_DESCRIPTION": "Sine values between -40 and 40 at 0.05 Hz with 0 phase shift", + "servermain.TAG_ADDRESS": "SINE (10, -40.000000, 40.000000, 0.050000, 0)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Sine2", + "common.ALLTYPES_DESCRIPTION": "Sine values between -40 and 40 at 0.05 Hz with 180 phase shift", + "servermain.TAG_ADDRESS": "SINE (10, -40.000000, 40.000000, 0.050000, 180)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Sine3", + "common.ALLTYPES_DESCRIPTION": "Sine values between -40 and 40 at 0.1 Hz with 0 phase shift", + "servermain.TAG_ADDRESS": "SINE (10, -40.000000, 40.000000, 0.100000, 0)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "Sine4", + "common.ALLTYPES_DESCRIPTION": "Sine values between -40 and 40 at 0.1 Hz with 360 phase shift", + "servermain.TAG_ADDRESS": "SINE (10, -40.000000, 40.000000, 0.100000, 360)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "User1", + "common.ALLTYPES_DESCRIPTION": "Sequential string values that change every 1000 ms", + "servermain.TAG_ADDRESS": "USER (1000,Hello,world!,This,is,a,test.)", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "User2", + "common.ALLTYPES_DESCRIPTION": "Sequential float values that change every 250 ms", + "servermain.TAG_ADDRESS": "USER (250,15.16,23.42,4.8)", + "servermain.TAG_DATA_TYPE": 8, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "User3", + "common.ALLTYPES_DESCRIPTION": "Sequential Boolean values that change every 200 ms", + "servermain.TAG_ADDRESS": "USER (200,1,0,0,1,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0)", + "servermain.TAG_DATA_TYPE": 1, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + }, + { + "common.ALLTYPES_NAME": "User4", + "common.ALLTYPES_DESCRIPTION": "A comma is a delimiter unless it is preceded with a backslash", + "servermain.TAG_ADDRESS": "USER (1500,To display a comma\\, place,a backslash in front of it.)", + "servermain.TAG_DATA_TYPE": 0, + "servermain.TAG_READ_WRITE_ACCESS": 0, + "servermain.TAG_SCAN_RATE_MILLISECONDS": 100, + "servermain.TAG_SCALING_TYPE": 0 + } + ] + } + ] + } + ], + "aliases": [ + { + "common.ALLTYPES_NAME": "Alias1", + "common.ALLTYPES_DESCRIPTION": "Example Alias", + "servermain.ALIAS_MAPPED_TO": "Channel1.Device1", + "servermain.ALIAS_SCAN_RATE_MILLISECONDS": 0 + } + ], + "client_interfaces": [ + { + "common.ALLTYPES_NAME": "aeserverinterface", + "aeserverinterface.ENABLE_AE_SERVER": false, + "aeserverinterface.ENABLE_SIMPLE_EVENTS": true, + "aeserverinterface.MAX_SUBSCRIPTION_BUFFER_SIZE": 100, + "aeserverinterface.MIN_SUBSCRIPTION_BUFFER_TIME_MS": 1000, + "aeserverinterface.MIN_KEEP_ALIVE_TIME_MS": 1000 + }, + { + "common.ALLTYPES_NAME": "opcdaserver", + "opcdaserver.PROJECT_OPC_DA_1_ENABLED": true, + "opcdaserver.PROJECT_OPC_DA_2_ENABLED": true, + "opcdaserver.PROJECT_OPC_DA_3_ENABLED": true, + "opcdaserver.PROJECT_OPC_SHOW_HINTS_ON_BROWSE": false, + "opcdaserver.PROJECT_OPC_SHOW_TAG_PROPERTIES_ON_BROWSE": false, + "opcdaserver.PROJECT_OPC_SHUTDOWN_WAIT_SEC": 15, + "opcdaserver.PROJECT_OPC_SYNC_REQUEST_WAIT_SEC": 15, + "opcdaserver.PROJECT_OPC_ENABLE_DIAGS": false, + "opcdaserver.PROJECT_OPC_MAX_CONNECTIONS": 512, + "opcdaserver.PROJECT_OPC_MAX_TAG_GROUPS": 2000, + "opcdaserver.PROJECT_OPC_REJECT_UNSUPPORTED_LANG_ID": true, + "opcdaserver.PROJECT_OPC_IGNORE_DEADBAND_ON_CACHE": false, + "opcdaserver.PROJECT_OPC_IGNORE_BROWSE_FILTER": false, + "opcdaserver.PROJECT_OPC_205A_DATA_TYPE_SUPPORT": true, + "opcdaserver.PROJECT_OPC_SYNC_READ_ERROR_ON_BAD_QUALITY": false, + "opcdaserver.PROJECT_OPC_RETURN_INITIAL_UPDATES_IN_SINGLE_CALLBACK": false, + "opcdaserver.PROJECT_OPC_RESPECT_CLIENT_LANG_ID": true, + "opcdaserver.PROJECT_OPC_COMPLIANT_DATA_CHANGE": true, + "opcdaserver.PROJECT_OPC_IGNORE_GROUP_UPDATE_RATE": false + }, + { + "common.ALLTYPES_NAME": "thingworxinterface", + "thingworxinterface.ENABLED": false, + "thingworxinterface.HOSTNAME": "localhost", + "thingworxinterface.PORT": 443, + "thingworxinterface.RESOURCE": "/Thingworx/WS", + "thingworxinterface.APPKEY": "", + "thingworxinterface.ALLOW_SELF_SIGNED_CERTIFICATE": false, + "thingworxinterface.TRUST_ALL_CERTIFICATES": false, + "thingworxinterface.DISABLE_ENCRYPTION": false, + "thingworxinterface.MAX_THING_COUNT": 500, + "thingworxinterface.THING_NAME": "KEPServerEX", + "thingworxinterface.PUBLISH_FLOOR_MSEC": 1000, + "thingworxinterface.LOGGING_ENABLED": false, + "thingworxinterface.LOG_LEVEL": 3, + "thingworxinterface.VERBOSE": false, + "thingworxinterface.STORE_AND_FORWARD_ENABLED": false, + "thingworxinterface.STORAGE_PATH": "C:\\ProgramData\\Kepware\\KEPServerEX\\V6\\", + "thingworxinterface.DATASTORE_MAXSIZE": 2048, + "thingworxinterface.FORWARD_MODE": 0, + "thingworxinterface.DATASTORE_ID": 421728385, + "thingworxinterface.DELAY_BETWEEN_PUBLISHES": 0, + "thingworxinterface.MAX_UPDATES_PER_PUBLISH": 25000, + "thingworxinterface.PROXY_ENABLED": false, + "thingworxinterface.PROXY_HOST": "localhost", + "thingworxinterface.PROXY_PORT": 3128, + "thingworxinterface.PROXY_USERNAME": "", + "thingworxinterface.PROXY_PASSWORD": "" + }, + { + "common.ALLTYPES_NAME": "uaserverinterface", + "uaserverinterface.PROJECT_OPC_UA_ENABLE": true, + "uaserverinterface.PROJECT_OPC_UA_DIAGNOSTICS": false, + "uaserverinterface.PROJECT_OPC_UA_ANONYMOUS_LOGIN": false, + "uaserverinterface.PROJECT_OPC_UA_MAX_CONNECTIONS": 128, + "uaserverinterface.PROJECT_OPC_UA_MIN_SESSION_TIMEOUT_SEC": 15, + "uaserverinterface.PROJECT_OPC_UA_MAX_SESSION_TIMEOUT_SEC": 60, + "uaserverinterface.PROJECT_OPC_UA_TAG_CACHE_TIMEOUT_SEC": 5, + "uaserverinterface.PROJECT_OPC_UA_BROWSE_TAG_PROPERTIES": false, + "uaserverinterface.PROJECT_OPC_UA_BROWSE_ADDRESS_HINTS": false, + "uaserverinterface.PROJECT_OPC_UA_MAX_DATA_QUEUE_SIZE": 2, + "uaserverinterface.PROJECT_OPC_UA_MAX_RETRANSMIT_QUEUE_SIZE": 10, + "uaserverinterface.PROJECT_OPC_UA_MAX_NOTIFICATION_PER_PUBLISH": 65536 + } + ] + } +} \ No newline at end of file diff --git a/Kepware.Api.TestIntg/appsettings.json b/Kepware.Api.TestIntg/appsettings.json new file mode 100644 index 0000000..d321bea --- /dev/null +++ b/Kepware.Api.TestIntg/appsettings.json @@ -0,0 +1,11 @@ +{ + "TestSettings": { + "IntegrationTest": true, + "TestServer": { + "Host": "http://localhost", + "Port": 57412, + "UserName": "Administrator", + "Password": "ReallyStrongPassword400!" + } + } +} \ No newline at end of file diff --git a/Kepware.Api/Kepware.Api.csproj b/Kepware.Api/Kepware.Api.csproj index 1b4b4d0..0ce56e2 100644 --- a/Kepware.Api/Kepware.Api.csproj +++ b/Kepware.Api/Kepware.Api.csproj @@ -28,6 +28,7 @@ +