diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..4799dec1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "LaaProductionWeb/LaaPackages"] + path = LaaProductionWeb/LaaPackages + url = https://slm.sms-esaap.com/la_operations/laapackages.git diff --git a/Common/.shared/SharedAssemblyInfo.cs b/Common/.shared/SharedAssemblyInfo.cs index 2c53cf85..ae1a5838 100644 --- a/Common/.shared/SharedAssemblyInfo.cs +++ b/Common/.shared/SharedAssemblyInfo.cs @@ -15,4 +15,3 @@ using System.Reflection; [assembly: AssemblyVersion("2.6.10.*")] -[assembly: AssemblyFileVersion("2.6.10.0")] \ No newline at end of file diff --git a/Common/Common.sln b/Common/Common.sln index d0f714ff..21dceb97 100644 --- a/Common/Common.sln +++ b/Common/Common.sln @@ -149,8 +149,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MagFlux", "MagFlux", "{C939 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protocols", "Protocols", "{94579693-7AC6-4FF0-B540-1F3780E1BCFA}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MjkControlledCodeRef", "MjkControlledCodeRef", "{B4F8545B-F379-42A5-BDE9-763FD7B79598}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxToolBox", "Ui\MagFluxToolBox\MagFluxToolBox.csproj", "{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxConfig", "Hardware\WaterMeter\MagFlux\MagFluxConfig\MagFluxConfig.csproj", "{70398B99-B134-4BBD-968B-7399B70C3CE2}" @@ -169,8 +167,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaProduction", "LaaProduct EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonConsole", "CommonConsole\CommonConsole.csproj", "{AFC428F5-0141-4A3F-BEF2-470A89D972F6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "modbus_master_csharp", "modbus_master_csharp\modbus_master_csharp.csproj", "{F14940F8-3C86-4BB7-A915-B021E4B3052D}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OmniPlus", "OmniPlus", "{68323534-4337-4E3A-89BC-11D8BB55343A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus", "OmniPlus\OmniPlus\OmniPlus.csproj", "{F8D84B9A-0FCF-4083-B067-8C39B7314152}" @@ -203,8 +199,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InspectionUI.RemoteControl" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Hardware.Interfaces.Ports", "Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj", "{9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.SIRTBroadcaster", "Ui\Common.UI.SIRTBroadcaster\Common.UI.SIRTBroadcaster.csproj", "{8D3B1C46-B23E-46CC-9B59-24E34DE60510}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.VFM", "Ui\Common.UI.VFM\Common.UI.VFM.csproj", "{9C1C5522-E986-4FD6-8F2F-19821D704A88}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OmniPlus", "OmniPlus", "{68A1B84B-B38F-4BD1-94A8-DB18600457FF}" @@ -227,10 +221,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Hardware.WaterMeter. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Utils.Extensions", "Utils\Common.Utils.Extensions\Common.Utils.Extensions.csproj", "{05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.WPFConnector", "Ui\Common.UI.WPFConnector\Common.UI.WPFConnector.csproj", "{37E4BF89-44AE-4133-BE0B-8355F791A79D}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.WPF", "Ui\Common.UI.WPF\Common.UI.WPF.csproj", "{F7316525-FF8E-4651-BA67-3C9B948D1E91}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MagFluxApi-MJK controlled Code", "MagFluxApi-MJK controlled Code", "{56768A27-D0E4-430E-8E75-AFC7319F189A}" + ProjectSection(SolutionItems) = preProject + Hardware\WaterMeter\MagFlux\MagFluxApi\magflux_api.dll = Hardware\WaterMeter\MagFlux\MagFluxApi\magflux_api.dll + Hardware\WaterMeter\MagFlux\MagFluxApi\shared_code.dll = Hardware\WaterMeter\MagFlux\MagFluxApi\shared_code.dll + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "api_doc", "api_doc", "{E6081C0A-8452-44B4-8EB4-E0CAE9119830}" + ProjectSection(SolutionItems) = preProject + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\CalibrationPoint.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\CalibrationPoint.cs + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\CalibrationPoints.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\CalibrationPoints.cs + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFlux.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFlux.cs + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFluxAPI.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFluxAPI.cs + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFluxRequestProtocol.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\IMagFluxRequestProtocol.cs + Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\SensorInfo.cs = Hardware\WaterMeter\MagFlux\MagFluxApi\api_doc\SensorInfo.cs + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Hardware.Interfaces.Ports.SirtBroadcaster", "Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SirtBroadcaster\Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj", "{F408DE9E-01E6-4CFF-AE79-B572B0674FA2}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4 @@ -3913,70 +3923,6 @@ Global {AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x64.Build.0 = Release|Any CPU {AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x86.ActiveCfg = Release|Any CPU {AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.ActiveCfg = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.Build.0 = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.ActiveCfg = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.Build.0 = Debug|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.Build.0 = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.ActiveCfg = Release|Any CPU - {F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.Build.0 = Release|Any CPU {F8D84B9A-0FCF-4083-B067-8C39B7314152}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU {F8D84B9A-0FCF-4083-B067-8C39B7314152}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU {F8D84B9A-0FCF-4083-B067-8C39B7314152}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -4809,70 +4755,6 @@ Global {9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}.XP32bit|x64.Build.0 = Release|Any CPU {9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}.XP32bit|x86.ActiveCfg = Release|Any CPU {9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}.XP32bit|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.COM|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|x64.Build.0 = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Debug|x86.Build.0 = Debug|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.PerformTest|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.Release|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.ReleaseTest|x86.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|Any CPU.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|x64.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|x64.Build.0 = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|x86.ActiveCfg = Release|Any CPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510}.XP32bit|x86.Build.0 = Release|Any CPU {9C1C5522-E986-4FD6-8F2F-19821D704A88}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU {9C1C5522-E986-4FD6-8F2F-19821D704A88}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU {9C1C5522-E986-4FD6-8F2F-19821D704A88}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -5513,70 +5395,6 @@ Global {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}.XP32bit|x64.Build.0 = Release|Any CPU {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}.XP32bit|x86.ActiveCfg = Release|Any CPU {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}.XP32bit|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.COM|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|x64.ActiveCfg = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|x64.Build.0 = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|x86.ActiveCfg = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Debug|x86.Build.0 = Debug|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.PerformTest|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.Release|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.ReleaseTest|x86.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|Any CPU.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|x64.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|x64.Build.0 = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|x86.ActiveCfg = Release|Any CPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D}.XP32bit|x86.Build.0 = Release|Any CPU {F7316525-FF8E-4651-BA67-3C9B948D1E91}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU {F7316525-FF8E-4651-BA67-3C9B948D1E91}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU {F7316525-FF8E-4651-BA67-3C9B948D1E91}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -5641,6 +5459,70 @@ Global {F7316525-FF8E-4651-BA67-3C9B948D1E91}.XP32bit|x64.Build.0 = Release|Any CPU {F7316525-FF8E-4651-BA67-3C9B948D1E91}.XP32bit|x86.ActiveCfg = Release|Any CPU {F7316525-FF8E-4651-BA67-3C9B948D1E91}.XP32bit|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.COM|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|x64.ActiveCfg = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|x64.Build.0 = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|x86.ActiveCfg = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Debug|x86.Build.0 = Debug|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.PerformTest|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.Release|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.ReleaseTest|x86.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|Any CPU.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|x64.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|x64.Build.0 = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|x86.ActiveCfg = Release|Any CPU + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2}.XP32bit|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5707,7 +5589,6 @@ Global {35726BCF-975C-4B49-BEFA-C00D90394F1D} = {696A94BE-7237-4AE2-9E36-6059DE519971} {C9393A97-C0BB-4D59-A879-B572BE04CE15} = {5563DD3B-2287-4BED-97BF-F0389FF505AF} {94579693-7AC6-4FF0-B540-1F3780E1BCFA} = {C9393A97-C0BB-4D59-A879-B572BE04CE15} - {B4F8545B-F379-42A5-BDE9-763FD7B79598} = {C9393A97-C0BB-4D59-A879-B572BE04CE15} {A5E7CE52-3101-4E9B-B896-C2C0FADE4812} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {70398B99-B134-4BBD-968B-7399B70C3CE2} = {C9393A97-C0BB-4D59-A879-B572BE04CE15} {B5DA260C-71CC-45CA-B79E-D1B376AF718C} = {C9393A97-C0BB-4D59-A879-B572BE04CE15} @@ -5717,7 +5598,6 @@ Global {8BDD2789-96D4-43EA-AAD7-0F49D0347998} = {EC10DAFE-88CF-42D5-99E7-D247938B6430} {FD30EB7A-7809-4E62-9374-791D31877D6D} = {696A94BE-7237-4AE2-9E36-6059DE519971} {AFC428F5-0141-4A3F-BEF2-470A89D972F6} = {C17363DF-A043-4F25-8EBA-2B3B078227DC} - {F14940F8-3C86-4BB7-A915-B021E4B3052D} = {B4F8545B-F379-42A5-BDE9-763FD7B79598} {F8D84B9A-0FCF-4083-B067-8C39B7314152} = {68323534-4337-4E3A-89BC-11D8BB55343A} {01A28A70-D5E6-4898-8C22-E64400A3B80F} = {68323534-4337-4E3A-89BC-11D8BB55343A} {4806D89A-FBFB-41BC-AAA7-2242444BF55A} = {FA3B769A-E83E-40F0-923A-DFA124AF0C2C} @@ -5732,7 +5612,6 @@ Global {C6BFAC88-5647-4131-90B1-4D6265E08348} = {68323534-4337-4E3A-89BC-11D8BB55343A} {41E949AD-FBF6-47A3-AC1D-7E17AB7F1252} = {68323534-4337-4E3A-89BC-11D8BB55343A} {9AE071C0-DB12-4E09-A3C7-43F6DCD518D6} = {B9444AB7-1EB1-484A-8DE6-4EEE03498CD7} - {8D3B1C46-B23E-46CC-9B59-24E34DE60510} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {9C1C5522-E986-4FD6-8F2F-19821D704A88} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {68A1B84B-B38F-4BD1-94A8-DB18600457FF} = {5563DD3B-2287-4BED-97BF-F0389FF505AF} {9D89FA2A-1217-4CE9-B217-E7602B974EA9} = {68A1B84B-B38F-4BD1-94A8-DB18600457FF} @@ -5744,8 +5623,10 @@ Global {28FD69D1-B2DA-485D-9571-711BF3917350} = {696A94BE-7237-4AE2-9E36-6059DE519971} {4E8BB839-D40A-488C-88CE-F21811F1F476} = {43B54F41-6F09-4BCB-9F82-77621275831B} {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3} = {7A0EE7B8-6B7E-41E9-B679-319C8CA48CF1} - {37E4BF89-44AE-4133-BE0B-8355F791A79D} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {F7316525-FF8E-4651-BA67-3C9B948D1E91} = {03D4F23E-7E4A-4091-BC96-036C996D351A} + {56768A27-D0E4-430E-8E75-AFC7319F189A} = {C9393A97-C0BB-4D59-A879-B572BE04CE15} + {E6081C0A-8452-44B4-8EB4-E0CAE9119830} = {56768A27-D0E4-430E-8E75-AFC7319F189A} + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2} = {B9444AB7-1EB1-484A-8DE6-4EEE03498CD7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164} diff --git a/Common/CommonConsole/CommonConsole.csproj b/Common/CommonConsole/CommonConsole.csproj index bf303d6d..77be462a 100644 --- a/Common/CommonConsole/CommonConsole.csproj +++ b/Common/CommonConsole/CommonConsole.csproj @@ -55,6 +55,14 @@ + + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2} + Common.Hardware.Interfaces.Ports.SirtBroadcaster + + + {B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD} + Common.Hardware.Interfaces.Ports.Sirt + {9ae071c0-db12-4e09-a3c7-43f6dcd518d6} Common.Hardware.Interfaces.Ports @@ -87,21 +95,10 @@ {F8D84B9A-0FCF-4083-B067-8C39B7314152} OmniPlus - - {8D3B1C46-B23E-46CC-9B59-24E34DE60510} - Common.UI.SIRTBroadcaster - - - {37E4BF89-44AE-4133-BE0B-8355F791A79D} - Common.UI.WPFConnector - {05f0ccaf-9f2b-45f9-a7f8-12f29ad182f3} Common.Utils.Extensions - - - \ No newline at end of file diff --git a/Common/CommonConsole/Program.cs b/Common/CommonConsole/Program.cs index 4bcf5fff..4d24daf1 100644 --- a/Common/CommonConsole/Program.cs +++ b/Common/CommonConsole/Program.cs @@ -1,40 +1,518 @@ namespace CommonConsole { - using Common.Hardware.WaterMeter.eRegister; - using Common.UI.WPFConnector; - using System; public class Program { public static void Main() { - //var connector = EregisterConnector.CreateNew("COM6", 1000); + int value = 333333333; + var bytes1 = BitConverter.GetBytes(value); - //connector.Add(1, 0319020415, 0319020415);//433 - //connector.AddHexCommand(1, "00-00"); - //connector.Add(2, 0319020441, 0319020441);//433 - //connector.AddHexCommand(2, "00-00"); - //connector.Add(3, 4291317405, 4291317405);//433 - //connector.AddHexCommand(3, "00-00"); + Array.Reverse(bytes1); - //connector.RunCommands(); + Console.WriteLine(BitConverter.ToString(bytes1).Replace('-', ' ')); + var hex = string.Empty; - var connector = EregisterConnector.CreateNew("COM6", 1000); + while (value > 0) + { + hex = $"{value % 256:X2}{hex}"; + value /= 256; + } - connector.Add(1, 0319020415, 0319020415);//433 - connector.AddHexCommand(1, "00-00"); - connector.Add(2, 0319020441, 0319020441);//433 - connector.AddHexCommand(2, "00-00"); - connector.Add(3, 4291317405, 4291317405);//433 - connector.AddHexCommand(3, "00-00"); - - connector.InitInspection(); + Console.WriteLine(hex); } + + + /// + /// 0B + /// D0 + /// FF C6 25 F3 + /// 00 + /// 0A + /// 11 08 + /// 11 08 + /// + /// 04 01 C7 47 9F 77 17 00 6A 00 08 08 00 00 00 00 05 68 46 89 02 01 01 16 00 0A 00 00 02 71 02 71 00 00 00 00 00 00 00 08 + /// + //var bytes = new[] { 0x08, 0x11 }; + //var bits = new Byte[16]; + //var x = 0; + + //foreach (var @byte in bytes) + //{ + // for (var i = 0; i< 8; i++, x++) + // { + // bits[x] = (Byte) ((@byte >> i) & 1); + // } + //} + + //Array.Reverse(bits); + + //var type = bits[15] == 0 ? 'B' : 'R'; + + //var majorBits = new Byte[8]; + //majorBits[0] = bits[14]; + //majorBits[1] = bits[13]; + //majorBits[2] = bits[12]; + + //var major = 0; + + //for (var i = 0; i< 8; i++) + //{ + // major |= majorBits[i] << i; + //} + + //var minorBits = new Byte[8]; + //majorBits[0] = bits[11]; + //majorBits[1] = bits[10]; + //majorBits[2] = bits[9]; + //majorBits[2] = bits[8]; + + //var minor = 0; + + //for (var i = 0; i< 8; i++) + //{ + // minor |= minorBits[i] << i; + //} + + //Console.WriteLine($"{type}{major}.{minor}.{0x08}"); + + + //var programmingBatch = new JusteRegisterProgrammingBatch(); + + //if (programmingBatch.StartOnCOMPort("COM6")) + //{ + // var task = new JusteRegisterProgrammingTask + // { + // Cmd = JustSirtMessage.W_PAM, + // P1 = new P811 + // { + // DelPamSemi = true + // }, + // Address = 319020415, + // Data = new Byte[] + // { + // // Metrology parameters + // 0x92, 0x10, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x71, 0x02, 0x00, 0x00, + + // // Provide Pin Auth Level III + // 0x43, 0x03, 0x63, 0x93, 0x73, 0x22, + // } + // }; + // programmingBatch.Run(task); + + // Console.ReadKey(); + + // programmingBatch.Stop(); + //} + //else + //{ + // Console.WriteLine("Not connected!"); + //} + + + // 01020304050607081112131415161718 + // E6C88800DEB868C0D6A84880CE982840 + //var encryptionKey = new Byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }; + //var task = new JusteRegisterProgrammingTask + //{ + // Cmd = JustSirtMessage.W_PAM, + // P1 = new P811 + // { + // DelPamSemi = true, + // WakeUpCmd = true + // }, + // Address = 4291305226, + // // Address = 319020415, + // Data = new Byte[] + // { + // // Change Key + // // 0x6C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + + // // LED on + // // 0x1F, 0x01, 0x08, + + // // Reboot + // 0x0E, 0x00, + + // // Provide Pin Auth Level I + // // 0x43, 0x01, 0x14, 0x30, 0x68, 0xD0, + + // // Provide Pin Auth Level II + // // 0x43, 0x02, 0x14, 0x0E, 0x80, 0x40, + + // // Provide Pin Auth Level III + // 0x43, 0x03, 0x63, 0x93, 0x73, 0x22, + + // // Reset credits + // // 0x1F, 0x01, 0x03, + // }, + // EncryptionKey = encryptionKey + //}; + //programmingBatch.Run(task); + //task.Wait(); + + // 55 81 14 00 FF C8 1F 0A 0B 07 FA E3 AA EA 8A 7B 7B D9 A7 D7 D5 B8 16 + // 55 81 14 00 FF C8 1F 0A 0B 07 FA E3 AA EA 8A 7B 7B D9 A7 D7 D5 B8 16 + + //var task = new JusteRegisterTask + //{ + // Cmd = JustSirtMessage.W_PAM, + // P1 = new P811 + // { + // DelPamSemi = true + // }, + // Address = 319020415, + // Data = new Byte[] + // { + // // WUP stay awake + // 0x00, 0x00, + + // // LAT + // 0x02, 0x00, + + // // MBUS 7 + // 0x05, 0x07, + + // // TX + // 0x10, 0x00, 0x03, + + // // Provide Pin Auth Level I + // // 0x43, 0x01, 0x14, 0x30, 0x68, 0xD0, + + // // Provide Pin Auth Level II + // 0x43, 0x02, 0x14, 0x0E, 0x80, 0x40, + + // // Provide Pin Auth Level III + // // 0x43, 0x03, 0x63, 0x93, 0x73, 0x22, + + // // Reset credits + // // 0x1F, 0x01, 0x03, + // } + //}; + //programmingBatch.Run(task); + //task.Wait(); + + //task = new JusteRegisterTask + //{ + // Cmd = JustSirtMessage.W_PAM, + // P1 = new P811 + // { + // DelPamSemi = true + // }, + // Address = 319020415, + // Data = new Byte[] + // { + // // Parametersatz + + + // // Provide Pin Auth Level I + // // 0x43, 0x01, 0x14, 0x30, 0x68, 0xD0, + + // // Provide Pin Auth Level II + // 0x43, 0x02, 0x14, 0x0E, 0x80, 0x40, + + // // Provide Pin Auth Level III + // // 0x43, 0x03, 0x63, 0x93, 0x73, 0x22, + + // // Reset credits + // // 0x1F, 0x01, 0x03, + // } + //}; + //programmingBatch.Run(task); + //task.Wait(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //public static byte[] Decrypt(Byte[] key, params Byte[] message) + //{ + // var decryptLength = message.Length; + // var decryptedBytes = new Byte[decryptLength]; + + // for (int i = 0; i < decryptLength; i++) + // { + // decryptedBytes[i] = message[i]; + // } + + // var start = 14; + // var end = start + decryptedBytes[7] 6; + // var token = decryptedBytes[9]; + + // for (var i = start; i < end; i++) + // { + // token += (Byte)(decryptedBytes[i (token & 0x3) 1] >> ((token >> 6) & 0x1)); + + // decryptedBytes[i] ^= key[(token >> 2) & 0x0F]; + + // if (token > 127) + // { + // decryptedBytes[i] = (Byte)~decryptedBytes[i]; + // } + // } + + // return decryptedBytes; + //} + + //public static byte[] Encrypt(Byte[] key, UInt32 address, params Byte[] telegramBytes) + //{ + // Console.WriteLine(address); + // Console.WriteLine(BitConverter.ToString(key)); + // Console.WriteLine(BitConverter.ToString(telegramBytes)); + + // var telegramLength = telegramBytes.Length; + // var telegramIndex = 0; + + // var encryptedBytes = new Byte[telegramLength + 6]; + // var encryptLength = encryptedBytes.Length; + // var index = 0; + + // encryptedBytes[index++] = (Byte)(address >> 24); + // encryptedBytes[index++] = (Byte)(address >> 16); + // encryptedBytes[index++] = (Byte)(address >> 8); + // encryptedBytes[index++] = (Byte)(address >> 0); + + // foreach (var _byte in telegramBytes) + // { + // encryptedBytes[index++] = telegramBytes[telegramIndex++]; + // } + + // var telegramCRC = CalculateCrc(encryptedBytes, 1, (UInt16)(encryptLength 3)); + + // encryptedBytes[index++] = (Byte)(telegramCRC >> 8); + // encryptedBytes[index++] = (Byte)(telegramCRC >> 0); + + // Console.WriteLine(BitConverter.ToString(encryptedBytes)); + + // var token = (Byte)0xFF; + // var reference = address; + + // for (var i = 0; i < encryptLength; i++) + // { + // // Update pKeyDefinition for this byte + // token += (Byte)(((reference >> ((token & 0x3) << 3)) & 0xFF) >> ((token >> 6) & 1)); + + // // Update the unencrypted reference before the byte gets encrypted + // reference = (reference << 8); + // reference += encryptedBytes[i]; + + // // Encrypt the data by applying the resepective key + // encryptedBytes[i] ^= key[((token >> 2) & 0x0F)]; + + // // Check if data has to be inverted + // if (token > 127) + // { + // encryptedBytes[i] = (Byte)~encryptedBytes[i]; + // } + // } + + // Console.WriteLine(BitConverter.ToString(encryptedBytes)); + // Console.WriteLine(); + + // return encryptedBytes; + //} + + //public static ushort CalculateCrc(byte[] data, ushort start, ushort length) + //{ + // byte zeichen, test; + // ushort crc_result; + // ushort ui_index; + // byte h; + + // crc_result = 0xFFFF; + // ui_index = start; + + // if (data.Length >= length + start) + // { + // while (ui_index < length + start) + // { + // zeichen = data[ui_index]; + // ui_index++; + + // for (h = 0; h < 8; h++) + // { + // test = 0; + + // if ((crc_result & 0x8000) != 0) + // { + // test = 0x80; + // } + + // crc_result <<= 1; + + // if (((zeichen & 0x80) ^ test) != 0) + // { + // crc_result ^= 0x1021; + // } + // zeichen <<= 1; + // } + // } + // } + + // return crc_result; + //} } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//var connector = EregisterConnector.CreateNew("COM6", 1000); + +//connector.Add(1, 0319020415, 0319020415);//433 +//connector.AddHexCommand(1, "00 00"); + +//connector.Add(2, 0319020441, "4291317405", "4291317405", null, false); // 433 +//connector.InitInspection(); + +//connector.Add(3, 4291317405, 4291317405);//433 +//connector.AddHexCommand(3, "00 00"); + +// connector.RunCommands(); + + +//var connector = EregisterConnector.CreateNew("COM6", 1000); + +//connector.Add(1, 0319020415, 0319020415);//433 +//connector.AddHexCommand(1, "00 00"); +//connector.Add(2, 0319020441, 0319020441);//433 +//connector.AddHexCommand(2, "00 00"); +//connector.Add(3, 4291317405, 4291317405);//433 +//connector.AddHexCommand(3, "00 00"); + +//connector.InitInspection(); + +//var connection = new OmniConnection(); +//connection.UseUniPro("COM16"); + +//var system = connection.ViewSystemParameters(); + +//connection.Disconnect(); // 0x08, 0x0E, 0x13, 0x03, 0xEE, 0xAC, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x92, 0x0A, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x13, 0x13, 0x03, 0xEE, 0xAC, 0x07, 0x0E, 0x10, 0xA0, 0x57, 0x4E, 0xDA, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x05, 0xA0, 0x0C, 0x03, 0x01, 0x2E, 0x46, 0x7C, 0x76, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x25, 0x14, 0x3B // 0x0B, 0x10, 0x13, 0x03, 0xEE, 0xAC, 0x00, 0x0A, 0x11, 0x0B, 0x11, 0x08, 0x04, 0x02, 0xC8, 0xF4, 0xFB, 0xA7, 0x18, 0x00, 0x65, 0x00, 0x35, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xEE, 0x34, 0x02, 0x01, 0x01, 0x16, 0x00, 0x25, 0x02, 0x71, 0x00, 0x00, 0x82, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0xC3 diff --git a/Common/CommonCore.Configuration/ServiceUrls.cs b/Common/CommonCore.Configuration/ServiceUrls.cs index df18db27..a446a236 100644 --- a/Common/CommonCore.Configuration/ServiceUrls.cs +++ b/Common/CommonCore.Configuration/ServiceUrls.cs @@ -9,6 +9,11 @@ namespace Xylem.Common.CommonCore.Configuration /// public static class ServiceUrls { + + // return code: 404 not found, 400 Error with text, 200 okay + private const String DefaultEolDataForSentinelServiceUrl = + "http://sla12iis01.emea.sensus.net/LaaProductionWeb/api/cordonel/eolprogress/"; + private const String DefaultGetPcbIdsFromSafeServiceUrl = "http://sla12iis01.emea.sensus.net/MeterProcessState/GetPcbIdsFromSafe?ContainerDbId="; @@ -33,11 +38,10 @@ namespace Xylem.Common.CommonCore.Configuration private const String DefaultSetCordonelAppVersionServiceUrl = "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/SetCordonelProgress?PcbId="; - private const String DefaultGetProductionSkipAndLifeTimeInfoUrl = - "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/GetProductionSkipAndLifeTimeInfo?PcbId="; + private const String DefaultGetCordonelRequirementInfoUrl = + "http://sla12iis01.emea.sensus.net/LaaProductionWeb/api/cordonel/requirements/pcbid/"; private const String DefaultGetCordonelAppVersionServiceUrl = - //"http://localhost:56011/api/ProccesState/GetCordonelAppVersion?PcbId="; "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/GetCordonelAppVersion?PcbId="; private const String DefaultListAllCordonelCustomersWithFilterServiceUrl = @@ -205,13 +209,14 @@ namespace Xylem.Common.CommonCore.Configuration private const String PressureSensorTestURL_GetTestResults = "http://sla12iis01.emea.sensus.net/MeterProcessState/api/CordonelPressureSensorTest/GetTestResults/{0}"; - public const string LaaProductionAPI + public const String LaaProductionAPI #if DEBUG == false // when false uses always the production url. = "http://localhost:52822"; #else = "http://sla12iis01.emea.sensus.net"; #endif + /// /// GET: test specification for water meter with pressure sensor. /// @@ -325,6 +330,16 @@ namespace Xylem.Common.CommonCore.Configuration return ConfigurationManager.AppSettings["DownloadDbDataAtEolServiceUrl"] ?? DefaultDbDataAtEolServiceUrl; } + /// + /// Get EOL data for sentinel + /// + /// + public static String EolDataForSentinelServiceUrl() + { + return ConfigurationManager.AppSettings["EolDataForSentinelServiceUrl"] ?? + DefaultEolDataForSentinelServiceUrl; + } + /// /// Get all Cordonel safes description files. /// @@ -383,10 +398,10 @@ namespace Xylem.Common.CommonCore.Configuration /// - Required life time for shipping line. /// /// - public static String GetProductionSkipAndLifeTimeInfoServiceUrl() + public static String GetCordonelRequirementInfoServiceUrl() { - return ConfigurationManager.AppSettings["GetProductionSkipAndLifeTimeInfoUrl"] ?? - DefaultGetProductionSkipAndLifeTimeInfoUrl; + return ConfigurationManager.AppSettings["GetCordonelRequirementInfoServiceUrl"] ?? + DefaultGetCordonelRequirementInfoUrl; } /// @@ -462,7 +477,7 @@ namespace Xylem.Common.CommonCore.Configuration /// - /// FW-Update report doanload as string + /// FW-Update report download as string /// /// public static String DownloadFwUpdateReportServiceUrl() diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Common.Hardware.Interfaces.Ports.SIRT.csproj b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Common.Hardware.Interfaces.Ports.SIRT.csproj index 260e2b49..f9f5ff7f 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Common.Hardware.Interfaces.Ports.SIRT.csproj +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Common.Hardware.Interfaces.Ports.SIRT.csproj @@ -7,8 +7,8 @@ {B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD} Library Properties - Common.Hardware.Interfaces.Ports.SIRT - Common.Hardware.Interfaces.Ports.SIRT + Common.Hardware.Interfaces.Ports.Sirt + Common.Hardware.Interfaces.Ports.Sirt v4.0 512 true @@ -41,6 +41,8 @@ + + diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtMessage.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtMessage.cs new file mode 100644 index 00000000..60dc011b --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtMessage.cs @@ -0,0 +1,166 @@ +namespace Common.Hardware.Interfaces.Ports.Sirt +{ + using System; + + public class JustSirtMessage + { + public const Byte MIN_LEN = 12; + public const Byte PC2SIRT = 0x55; + public const Byte SIRT2PC = 0xFF; + public const Byte W_PAM = 0x81; + public const Byte R_PAM = 0x82; + public const Byte W_REG = 0x84; + public const Byte R_REG = 0x87; + public const Byte FROMAIR = 0x11; + public const Byte ACKNANSW = 0x12; + public const Byte STOP = 0x16; + public const Byte BUP = 0x00; + public const Byte LAT = 0x01; + public const Byte DEBUG = 0x0B; + public const Byte SEMI = 0x08; + + private readonly DateTime timestamp; + + private Byte[] bytes; + + public JustSirtMessage(DateTime? timestamp = null) + { + this.timestamp = timestamp ?? DateTime.Now; + this.bytes = new Byte[MIN_LEN]; + this.bytes[0] = PC2SIRT; + } + + public JustSirtMessage(Byte[] bytes, DateTime? timestamp = null) + { + this.timestamp = timestamp ?? DateTime.Now; + this.bytes = bytes; + } + + public Byte Cmd + { + get => this.bytes[1]; + set => this.bytes[1] = value; + } + + public Byte P1 + { + get => this.bytes[2]; + set => this.bytes[2] = value; + } + + public Byte P2 + { + get => this.bytes[3]; + set => this.bytes[3] = value; + } + + public UInt32 Address + { + get + { + var address = 0U; + + address ^= (UInt32)this.bytes[4] << 24; + address ^= (UInt32)this.bytes[5] << 16; + address ^= (UInt32)this.bytes[6] << 8; + address ^= (UInt32)this.bytes[7] << 0; + + return address; + } + set + { + this.bytes[4] = (Byte)(value >> 24); + this.bytes[5] = (Byte)(value >> 16); + this.bytes[6] = (Byte)(value >> 8); + this.bytes[7] = (Byte)(value >> 0); + } + } + + public Byte Length => this.bytes[8]; + + public Byte[] Data + { + get + { + var data = new Byte[this.Length]; + + Array.Copy(this.bytes, 9, data, 0, this.Length); + + return data; + } + set + { + if (value is null) + { + value = new Byte[0]; + } + + this.bytes[8] = (Byte)value.Length; + + Array.Resize(ref this.bytes, MIN_LEN + this.Length); + Array.Clear(this.bytes, 9, this.bytes.Length - 9); + Array.Copy(value, 0, this.bytes, 9, this.Length); + } + } + + public UInt16 CRC + { + get + { + var length = this.bytes.Length; + var crc = default(UInt16); + + crc ^= (UInt16)(this.bytes[length - 3] << 8); + crc ^= (UInt16)(this.bytes[length - 2] << 0); + + return crc; + } + } + + public Byte[] ToByteArray() + { + var length = this.bytes.Length; + var crc = this.CRCCCITT(1, length - 3); + + this.bytes[length - 3] = (Byte)(crc >> 8); + this.bytes[length - 2] = (Byte)(crc >> 0); + this.bytes[length - 1] = STOP; + + return this.bytes; + } + + public override String ToString() + => BitConverter.ToString(this.ToByteArray()); + + public static implicit operator Byte[](JustSirtMessage message) + => message.ToByteArray() ?? new Byte[0]; + + private UInt16 CRCCCITT(Int32 start, Int32 length) + { + var crc = (UInt16)0xFFFF; + + for (var b = start; b < length; b++) + { + var _byte = this.bytes[b]; + var token = (UInt16)((_byte << 8) & 0xFF00); + + for (var i = 0; i < 8; i++) + { + if (0x8000 == ((crc ^ token) & 0x8000)) + { + crc <<= 1; + crc ^= 0x1021; + } + else + { + crc <<= 1; + } + + token <<= 1; + } + } + + return crc; + } + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtProxy.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtProxy.cs new file mode 100644 index 00000000..5b3ba0a5 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/JustSirtProxy.cs @@ -0,0 +1,135 @@ +namespace Common.Hardware.Interfaces.Ports.Sirt +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Timers; + + public class JustSirtProxy + { + private readonly JustSerialPort serialPort; + private readonly List buffer; + private readonly Timer timer; + + public JustSirtProxy(String portName) + { + var settings = new SerialPortSettings + { + BaudRate = SerialPortBaudRate.X115200, + DataBits = SerialPortDataBits.X8, + Parity = SerialPortParity.None, + PortName = portName, + StopBits = SerialPortStopBits.One + }; + this.serialPort = new JustSerialPort(settings); + this.buffer = new List(); + this.timer = new Timer(); + } + + public event Action MessageReceived; + + public Boolean IsOpen => this.serialPort.IsOpen; + + public event Action Logging + { + add => this.serialPort.Logging += value; + remove => this.serialPort.Logging -= value; + } + + public void Log(Object value) => this.serialPort.Log(value); + + public Boolean TryClose() + { + var closed = false; + + try + { + this.timer.Stop(); + this.serialPort.TryClose(); + + closed = true; + } + catch (Exception e) + { + this.Log(e); + } + + return closed; + } + + public Boolean TryOpen() + { + var opened = this.serialPort.TryOpen(); + + if (opened) + { + this.timer.Elapsed += this.Timer_Elapsed; + this.timer.AutoReset = true; + this.timer.Interval = 50; + this.timer.Start(); + + opened = true; + } + + return opened; + } + + public void WriteBytes(params Byte[] bytes) + => this.serialPort.WriteBytes(bytes); + + private Byte[] bytes; + private Int32 bytesLength; + private Int32 bufferLength; + private Int32 start; + private Int32 lengthIX; + private Byte length; + private Int32 stopIX; + + private void Timer_Elapsed(Object sender, ElapsedEventArgs _1) + { + this.bytes = this.serialPort.ReadBytes(); + this.bytesLength = this.bytes.Length; + + if (this.bytesLength > 0) + { + this.buffer.AddRange(this.bytes); + } + + this.bufferLength = this.buffer.Count; + this.start = this.buffer.IndexOf(JustSirtMessage.SIRT2PC); + + if (this.start < 0) + { + this.buffer.Clear(); + + return; + } + + this.lengthIX = this.start + 8; + + if (this.lengthIX >= this.bufferLength) + { + return; + } + + this.length = this.buffer[this.lengthIX]; + this.stopIX = this.lengthIX + this.length + 3; + + if (this.stopIX >= this.bufferLength) + { + return; + } + else if (this.buffer[this.stopIX] != JustSirtMessage.STOP) + { + return; + } + + this.bytesLength = this.stopIX - this.start + 1; + this.bytes = new Byte[this.bytesLength]; + + this.buffer.CopyTo(this.start, this.bytes, 0, this.bytesLength); + this.buffer.RemoveRange(0, this.start + this.bytesLength); + this.MessageReceived?.Invoke(new JustSirtMessage(this.bytes)); + } + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/AuthLevel.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/AuthLevel.cs index 773aba4d..b44d72cb 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/AuthLevel.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/AuthLevel.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/BluetoothOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/BluetoothOperating.cs index 08dc29bd..99808a1e 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/BluetoothOperating.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/BluetoothOperating.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/ByteExtensions.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/ByteExtensions.cs index 7998ddce..126d2107 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/ByteExtensions.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/ByteExtensions.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/OperatingModes.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/OperatingModes.cs index 40e3c564..d3f71913 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/OperatingModes.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/OperatingModes.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { public enum OperatingModes { diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P11.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P11.cs index 8db46bc4..5190ae48 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P11.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P11.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P12.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P12.cs index a08d608b..84df10ad 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P12.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P12.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P811.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P811.cs index b75e6f3e..1560ca73 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P811.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/P811.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/PamTimeout.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/PamTimeout.cs index 82439494..c4de0a52 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/PamTimeout.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/PamTimeout.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/RFModuleOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/RFModuleOperating.cs index 1bd570b9..46e6ab45 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/RFModuleOperating.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/RFModuleOperating.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/SirtOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/SirtOperating.cs index 0ca06941..3f1ae2c3 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/SirtOperating.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Parameters/SirtOperating.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters +namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadPamRequest.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadPamRequest.cs index 1286ac80..163d86b0 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadPamRequest.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadPamRequest.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Requests +namespace Common.Hardware.Interfaces.Ports.Sirt.Requests { - using Common.Hardware.Interfaces.Ports.SIRT; + using Common.Hardware.Interfaces.Ports.Sirt; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadRegRequest.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadRegRequest.cs index 63204a19..ffa8a30c 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadRegRequest.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/ReadRegRequest.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Requests +namespace Common.Hardware.Interfaces.Ports.Sirt.Requests { - using Common.Hardware.Interfaces.Ports.SIRT; + using Common.Hardware.Interfaces.Ports.Sirt; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WritePamRequest.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WritePamRequest.cs index 6ee93778..4a8ad6de 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WritePamRequest.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WritePamRequest.cs @@ -1,7 +1,7 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Requests +namespace Common.Hardware.Interfaces.Ports.Sirt.Requests { - using Common.Hardware.Interfaces.Ports.SIRT; - using Common.Hardware.Interfaces.Ports.SIRT.Parameters; + using Common.Hardware.Interfaces.Ports.Sirt; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WriteRegRequest.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WriteRegRequest.cs index 6bb31c25..2884faef 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WriteRegRequest.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Requests/WriteRegRequest.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Requests +namespace Common.Hardware.Interfaces.Ports.Sirt.Requests { - using Common.Hardware.Interfaces.Ports.SIRT; + using Common.Hardware.Interfaces.Ports.Sirt; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/AcknOrAnswerResponse.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/AcknOrAnswerResponse.cs index 694d24b9..85edc932 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/AcknOrAnswerResponse.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/AcknOrAnswerResponse.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Responses +namespace Common.Hardware.Interfaces.Ports.Sirt.Responses { - using Common.Hardware.Interfaces.Ports.SIRT.Parameters; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/FromAirResponse.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/FromAirResponse.cs index 0e2fe379..f047291f 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/FromAirResponse.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Responses/FromAirResponse.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Responses +namespace Common.Hardware.Interfaces.Ports.Sirt.Responses { - using Common.Hardware.Interfaces.Ports.SIRT.Parameters; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTRequest.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTRequest.cs index 3d5dad0d..f69f0a82 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTRequest.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTRequest.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTResponse.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTResponse.cs index 9639b92a..9f6183e9 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTResponse.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTResponse.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTTask[TRequest].cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTTask[TRequest].cs index 3a2aaee5..0df55bcc 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTTask[TRequest].cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SIRTTask[TRequest].cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtBroadcaster.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtBroadcaster.cs index 95ba8780..81a5dd56 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtBroadcaster.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtBroadcaster.cs @@ -1,7 +1,7 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { - using Common.Hardware.Interfaces.Ports.SIRT.Responses; - using Common.Hardware.Interfaces.Ports.SIRT.Tasks; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Tasks; using System; using System.Collections.Concurrent; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtConstants.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtConstants.cs index a65dd005..b32094de 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtConstants.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtConstants.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtMessage.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtMessage.cs index fb65ac63..84efb828 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtMessage.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtMessage.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtTask.cs index 65c9ddaa..ef5eb16e 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/SirtTask.cs @@ -1,7 +1,7 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { - using Common.Hardware.Interfaces.Ports.SIRT.Requests; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Requests; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ActivateSIRTTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ActivateSIRTTask.cs index 3edcd315..90e854ed 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ActivateSIRTTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ActivateSIRTTask.cs @@ -1,8 +1,8 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks +namespace Common.Hardware.Interfaces.Ports.Sirt.Tasks { - using Common.Hardware.Interfaces.Ports.SIRT.Parameters; - using Common.Hardware.Interfaces.Ports.SIRT.Requests; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; + using Common.Hardware.Interfaces.Ports.Sirt.Requests; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; @@ -20,7 +20,7 @@ new BluetoothOperating { BtOff = true }, new RFModuleOperating { RfOff = true }, new RFModuleOperating { OpMode = OperatingModes.ReceiveF1TransmitSensusRFF3 }, - // new PamTimeout { Minutes = 1 } + new PamTimeout { Minutes = 1 } }; } diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/DeleteFromPamPoolTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/DeleteFromPamPoolTask.cs index 2d6f52f4..ecaacb53 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/DeleteFromPamPoolTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/DeleteFromPamPoolTask.cs @@ -1,8 +1,8 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks +namespace Common.Hardware.Interfaces.Ports.Sirt.Tasks { using System; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; public class DeleteFromPamPoolTask : WritePamTask { diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/IdentifySIRTTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/IdentifySIRTTask.cs index 18f0e7c5..21cf0319 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/IdentifySIRTTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/IdentifySIRTTask.cs @@ -1,7 +1,7 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks +namespace Common.Hardware.Interfaces.Ports.Sirt.Tasks { - using Common.Hardware.Interfaces.Ports.SIRT.Requests; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Requests; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ReadPamPoolTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ReadPamPoolTask.cs index b88b4d94..d4c24c25 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ReadPamPoolTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/ReadPamPoolTask.cs @@ -1,7 +1,7 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT.Tasks +namespace Common.Hardware.Interfaces.Ports.Sirt.Tasks { - using Common.Hardware.Interfaces.Ports.SIRT.Requests; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Requests; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/WritePamTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/WritePamTask.cs index fedde649..2fce37d7 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/WritePamTask.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SIRT/Tasks/WritePamTask.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.Interfaces.Ports.SIRT +namespace Common.Hardware.Interfaces.Ports.Sirt { - using Common.Hardware.Interfaces.Ports.SIRT.Requests; + using Common.Hardware.Interfaces.Ports.Sirt.Requests; using System; diff --git a/Common/Ui/Common.UI.WPFConnector/Common.UI.WPFConnector.csproj b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj similarity index 55% rename from Common/Ui/Common.UI.WPFConnector/Common.UI.WPFConnector.csproj rename to Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj index ba3a3fb7..27f8de1f 100644 --- a/Common/Ui/Common.UI.WPFConnector/Common.UI.WPFConnector.csproj +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj @@ -4,16 +4,18 @@ Debug AnyCPU - {37E4BF89-44AE-4133-BE0B-8355F791A79D} + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2} Library - Properties - Common.UI.WPFConnector - Common.UI.WPFConnector + Common.Hardware.Interfaces.Ports.SirtBroadcaster + Common.Hardware.Interfaces.Ports.SirtBroadcaster v4.0 512 + true true + + AnyCPU true full false @@ -24,6 +26,7 @@ IDE0003;IDE0049; + AnyCPU pdbonly true bin\Release\ @@ -31,8 +34,10 @@ prompt 4 + + + - @@ -40,20 +45,31 @@ - - + + + + + + + + + + + + + - - {4E8BB839-D40A-488C-88CE-F21811F1F476} - Common.Hardware.WaterMeter.eRegister + + {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3} + Common.Utils.Extensions - - {f7316525-ff8e-4651-ba67-3c9b948d1e91} - Common.UI.WPF + + {B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD} + Common.Hardware.Interfaces.Ports.Sirt diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtBroadcaster.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtBroadcaster.cs new file mode 100644 index 00000000..d65f0d8f --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtBroadcaster.cs @@ -0,0 +1,168 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster +{ + using Common.Hardware.Interfaces.Ports.Sirt; + + using System; + using System.Collections.Concurrent; + using System.Threading; + + public class JustSirtBroadcaster + { + private static readonly ConcurrentDictionary runningTasks + = new ConcurrentDictionary(); + private readonly JustSirtProxy proxy; + + public JustSirtBroadcaster(String portName) + { + this.proxy = new JustSirtProxy(portName); + this.proxy.MessageReceived += this.Proxy_MessageReceived; + } + + public event Action Logging + { + add => this.proxy.Logging += value; + remove => this.proxy.Logging -= value; + } + + public String SirtId { get; private set; } + + public Int32 MHz { get; private set; } + + public void Log(Object value) => this.proxy.Log(value); + + public Boolean TryActivate() + { + var activated = this.proxy.TryOpen(); + + if (activated) + { + runningTasks.Clear(); + } + + var awaiter = new ManualResetEventSlim(); + + var task = JustSirtTask.ActivateSIRT; + task.Cancelled += _ => awaiter.Set(); + task.Completed += _task => + { + activated = _task.TaskStatus == JustTaskStatus.Completed; + + if (activated) + { + awaiter.Set(); + } + }; + task = runningTasks.AddOrUpdate(task.Address, task, (a, t) => task); + + task.PrepareForRun(); + this.proxy.WriteBytes(task); + this.Log(task); + awaiter.Wait(); + awaiter.Reset(); + + if (activated) + { + task = JustSirtTask.IdentifySIRT; + task.Cancelled += _ => awaiter.Set(); + task.Completed += _task => + { + activated = _task.TaskStatus == JustTaskStatus.Completed; + + if (activated) + { + awaiter.Set(); + } + }; + task = runningTasks.AddOrUpdate(task.Address, task, (a, t) => task); + + task.PrepareForRun(); + this.proxy.WriteBytes(task); + this.Log(task); + awaiter.Wait(); + awaiter.Reset(); + + if (activated) + { + this.SirtId = BitConverter.ToString(task.LastPayload); + this.MHz = this.SirtId[10] == '0' ? 868 : 433; + } + } + + return activated; + } + + public Boolean TryDeactivate() + { + this.proxy.MessageReceived -= this.Proxy_MessageReceived; + + return this.proxy.TryClose(); + } + + public JustTaskStatus TryRun(JustSirtTask task) + { + if (!this.proxy.IsOpen) + { + return JustTaskStatus.ProxyNotOpen; + } + + var address = task.Address; + + if (runningTasks.TryGetValue(address, out var runningTask) && runningTask != null) + { + return JustTaskStatus.InRunningTasks; + } + + var countInPamPool = 0; + + foreach (var _task in runningTasks.Values) + { + if (_task != null && _task.Cmd == JustSirtMessage.W_PAM) + { + countInPamPool++; + } + } + + if (countInPamPool >= 5) + { + return JustTaskStatus.PamPoolIsFull; + } + + task = runningTasks.AddOrUpdate(address, task, (a, t) => task); + + if (task.TaskStatus == JustTaskStatus.Completed) + { + this.Task_DismissFromRunningTasks(task); + + return JustTaskStatus.Completed; + } + + task.Cancelled += this.Task_DismissFromRunningTasks; + task.Completed += this.Task_DismissFromRunningTasks; + + task.PrepareForRun(); + this.proxy.WriteBytes(task); + this.Log($"{task.Address}|{BitConverter.ToString(task)}"); + + return JustTaskStatus.Sent; + } + + private void Proxy_MessageReceived(JustSirtMessage message) + { + var address = message.Address; + + if (runningTasks.TryGetValue(address, out var task) && task != null) + { + task.ReceiveMessage(message, this.MHz); + this.Log($"{address}|{message}"); + } + } + + private void Task_DismissFromRunningTasks(JustSirtTask task) + { + task.Cancelled -= this.Task_DismissFromRunningTasks; + task.Completed -= this.Task_DismissFromRunningTasks; + + runningTasks.TryRemove(task.Address, out var _); + } + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtTask.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtTask.cs new file mode 100644 index 00000000..ab12f286 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustSirtTask.cs @@ -0,0 +1,143 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster +{ + using Common.Hardware.Interfaces.Ports.Sirt; + using Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters; + + using System; + using System.Collections.Concurrent; + using System.Timers; + + public class JustSirtTask + { + private readonly Timer timer = new Timer(); + private readonly JustSirtMessage request = new JustSirtMessage(); + private readonly ConcurrentStack responses = new ConcurrentStack(); + + public event Action Completed; + public event Action Cancelled; + + public Byte Cmd + { + get => this.request.Cmd; + set => this.request.Cmd = value; + } + + public Byte P1 + { + get => this.request.P1; + set => this.request.P1 = value; + } + + public Byte P2 + { + get => this.request.P2; + set => this.request.P2 = value; + } + + public UInt32 Address + { + get => this.request.Address; + set => this.request.Address = value; + } + + public Byte[] Data + { + get => this.request.Data; + set => this.request.Data = value; + } + + public JustTaskStatus TaskStatus { get; protected set; } + + public Byte[] LastPayload + => this.responses.TryPeek(out var response) + ? response.Data + : default(Byte[]); + + public virtual void ReceiveMessage(JustSirtMessage response, Int32 mhz) + { + this.responses.Push(response); + + if (this.TaskStatus != JustTaskStatus.Completed) + { + this.TaskStatus = JustTaskStatus.Running; + + if (this.request.Cmd == JustSirtMessage.W_PAM) + { + if (response.Cmd == JustSirtMessage.FROMAIR && response.Data[0] == JustSirtMessage.SEMI) + { + this.TaskStatus = JustTaskStatus.Completed; + } + } + else if (response.Cmd == JustSirtMessage.ACKNANSW) + { + this.TaskStatus = JustTaskStatus.Completed; + } + } + + if (this.TaskStatus == JustTaskStatus.Completed) + { + this.Completed?.Invoke(this); + this.timer.Stop(); + } + } + + public virtual void PrepareForRun() + { + this.responses.Clear(); + this.TaskStatus = JustTaskStatus.Pending; + this.timer.AutoReset = false; + this.timer.Interval = 10_000; + this.timer.Elapsed += (sender, _1) => + { + this.TaskStatus = JustTaskStatus.Cancelled; + + this.Cancelled?.Invoke(this); + }; + this.timer.Start(); + } + + public virtual Byte[] ToByteArray() + => this.request.ToByteArray(); + + public override String ToString() + => BitConverter.ToString(this.ToByteArray()); + + public static implicit operator Byte[] (JustSirtTask task) + => task?.ToByteArray() ?? new Byte[] { }; + + public static readonly JustSirtTask ActivateSIRT = new JustSirtTask + { + Cmd = JustSirtMessage.W_REG, + Address = 0x20000000, + P2 = 0x05, + Data = new Byte[] + { + new SirtOperating { /* default */ }, + new BluetoothOperating { BtOff = true }, + new RFModuleOperating { RfOff = true }, + new RFModuleOperating { OpMode = OperatingModes.ReceiveF1TransmitSensusRFF3 }, + new PamTimeout { Minutes = 1 } + } + }; + + public static readonly JustSirtTask IdentifySIRT = new JustSirtTask + { + Cmd = JustSirtMessage.R_REG, + Address = 0x11001820, + P2 = 0x08 + }; + + public static readonly JustSirtTask ReadPamPool = new JustSirtTask + { + Cmd = JustSirtMessage.R_PAM, + Address = 0xFFFFFFFF + }; + + public static JustSirtTask DeleteFromPamPool(UInt32 address) => new JustSirtTask + { + Cmd = JustSirtMessage.W_PAM, + P1 = new P811 { DelPamAdr = true }, + Address = address + }; +} +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustTaskStatus.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustTaskStatus.cs new file mode 100644 index 00000000..d554b507 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/JustTaskStatus.cs @@ -0,0 +1,15 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster +{ + public enum JustTaskStatus + { + Pending = 0, + Running = 1, + Completed = 2, + Cancelled = 3, + InRunningTasks = 4, + PamPoolIsFull = 5, + InPamPool = 6, + Sent = 7, + ProxyNotOpen = 8, + } +} \ No newline at end of file diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/BluetoothOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/BluetoothOperating.cs new file mode 100644 index 00000000..b06d1b6e --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/BluetoothOperating.cs @@ -0,0 +1,63 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + public class BluetoothOperating + { + private readonly Byte[] bits; + + public BluetoothOperating() => this.bits = new Byte[8]; + + private BluetoothOperating(Byte[] bits) => this.bits = bits; + + /// + /// 0 -> Transparent Mode at 115k2 Baud 8,n,1 + /// + public Boolean BtOpMode + { + get => this.bits[0] == 1; + } + + /// + /// + /// + /// true + /// after "TIME_OFF" is elapsed without any command via Bluetooth, Bluetooth interface will be switched off + /// + /// + /// false + /// normal operation + /// + /// + /// + public Boolean BtPwrSave + { + get => this.bits[6] == 1; + set => this.bits[6] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// BT module will be switched off + /// + /// + /// false + /// normal operation + /// + /// + /// + public Boolean BtOff + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(BluetoothOperating param) + => param.bits.GetByte(); + + public static implicit operator BluetoothOperating(Byte _byte) + => new BluetoothOperating(_byte.GetBits()); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/ByteExtensions.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/ByteExtensions.cs new file mode 100644 index 00000000..1eea4a9b --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/ByteExtensions.cs @@ -0,0 +1,31 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + public static class ByteExtensions + { + public static Byte[] GetBits(this Byte @byte) + { + var bits = new Byte[8]; + + for (int i = 0; i < 8; i++) + { + bits[i] = (Byte)((@byte >> i) & 1); + } + + return bits; + } + + public static Byte GetByte(this Byte[] bits) + { + var @byte = default(int); + + for (int i = 0; i < 8; i++) + { + @byte |= bits[i] << i; + } + + return (Byte)@byte; + } + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/OperatingModes.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/OperatingModes.cs new file mode 100644 index 00000000..2611e461 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/OperatingModes.cs @@ -0,0 +1,14 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + public enum OperatingModes + { + Off = 0, + ReceiveF1TransmitSensusRFF3 = 1, + ReceiveF2TransmitSensusRFF2 = 2, + ReceiveWirelessMbusT1CMode = 3, + ReceiveWirelessMbusS1Mode = 4, + Receive = 5, + TestMode = 8, + Undefined = 15 + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P11.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P11.cs new file mode 100644 index 00000000..6d6f1b1b --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P11.cs @@ -0,0 +1,178 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + /// + /// Parameter P11 is given at third position of "Telegram from Air" telegram and give more detailed information about the + /// received packets from radio section of SIRT.The bits of Parameter 11 are decoded as following, where Bit 0 is the least + /// significant bit: + /// + public class P11 + { + private readonly Byte[] bits; + + public P11() => this.bits = new Byte[8]; + + private P11(Byte[] bits) => this.bits = bits; + + /// + /// + /// + /// true + /// RF-Module2 is source + /// + /// + /// false + /// RF-Module1 is source + /// + /// + /// only valid if both RF-Module programmed for Sensus RF + /// + public Boolean SrcChannel + { + get => this.bits[0] == 1; + set => this.bits[0] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// both RF module data are valid + /// + /// + /// false + /// only one RF module data is valid + /// + /// + /// only valid if both RF-Module programmed for Sensus RF + /// + public Boolean BothValid + { + get => this.bits[1] == 1; + set => this.bits[1] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// RF-Module1 data is invalid + /// + /// + /// false + /// RF-Module1 data is valid + /// + /// + /// i.e. radio checksum is wrong ... + /// + public Boolean InvalidMod1 + { + get => this.bits[2] == 1; + set => this.bits[2] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// RF-Module2 data is invalid + /// + /// + /// false + /// RF-Module2 data is valid + /// + /// + /// i.e. radio checksum is wrong ... + /// + public Boolean InvalidMod2 + { + get => this.bits[3] == 1; + set => this.bits[3] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// invalid -> module detects length > 128 + /// + /// + /// false + /// all ok + /// + /// + /// + public Boolean LenOverflow + { + get => this.bits[4] == 1; + set => this.bits[4] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// will look at PAM / RAC Pool + /// + /// + /// false + /// no attention for PAM / RAC + /// + /// + /// + public Boolean Attention + { + get => this.bits[5] == 1; + set => this.bits[5] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// + /// If .modeSensus = 0 wireless M-busMode -> T1 - Mode + /// If .modeSensus = 1 SensusRF -> receive at f2 + /// + /// + /// + /// false + /// + /// If .modeSensus = 0 wireless M-busMode -> S1 - Mode + /// If .modeSensus = 1 SensusRF -> receive at f1 + /// + /// + /// + /// + public Boolean ModeRF + { + get => this.bits[6] == 1; + set => this.bits[6] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// Sensus RF Mode + /// + /// + /// false + /// wireless M-Bus Mode + /// + /// + /// + public Boolean ModeSensus + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(P11 param) + => param.bits.GetByte(); + + public static implicit operator P11(Byte _byte) + => new P11(_byte.GetBits()); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P12.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P12.cs new file mode 100644 index 00000000..6e435376 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P12.cs @@ -0,0 +1,170 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + /// + /// P12 is the parameter of "Acknowledge or Answer" message and is placed at third position, + /// if telegram from SIRT-> PC begins with {0xFF, 0x12}. + /// This parameter gives more detailed information about the last command or request which + /// was send to SIRT. + /// Parameter 12 is given at third position of acknowledge- or answer telegram from SIRT. + /// + public class P12 + { + private readonly Byte[] bits; + + public P12() => this.bits = new Byte[8]; + + private P12(Byte[] bits) => this.bits = bits; + + /// + /// + /// + /// true + /// requested buffer is full or not available + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean BufFull + { + get => this.bits[0] == 1; + set => this.bits[0] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// operating system is busy + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean OsBusy + { + get => this.bits[1] == 1; + set => this.bits[1] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// wrong CRC recognized + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean WrongCRC + { + get => this.bits[2] == 1; + set => this.bits[2] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// command cannot be executed + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean CmdNotExecuted + { + get => this.bits[3] == 1; + set => this.bits[3] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// telegram or command Byte unknown + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean CmdUnknown + { + get => this.bits[4] == 1; + set => this.bits[4] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// no such entry found + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean NoEntry + { + get => this.bits[5] == 1; + set => this.bits[5] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// unknown fixed byte + /// + /// + /// false + /// Ok + /// + /// + /// + public Boolean ByteUnknown + { + get => this.bits[6] == 1; + set => this.bits[6] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// address was 0xFFFFFFFF + /// + /// + /// false + /// normal address + /// + /// + /// + public Boolean WildCardAddr + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(P12 param) + => param.bits.GetByte(); + + public static implicit operator P12(Byte _byte) + => new P12(_byte.GetBits()); + } +} \ No newline at end of file diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P811.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P811.cs new file mode 100644 index 00000000..bafefbac --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/P811.cs @@ -0,0 +1,241 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + /// + /// Parameter P81-1 is the first modifier of "Write to PAM Pool" command and is placed at third position, + /// if telegram from PC -> SIRT begins with {0x55, 0x81}. + /// This Byte describe in detailed what PAM message should do in detail. + /// There is an public priority within the bits which are described at next table: + /// + /// + /// 7 + /// 6 + /// 5 + /// 4 + /// 3 + /// 2 + /// 1 + /// 0 + /// Description + /// + /// + /// 1 + /// X + /// X + /// X + /// X + /// X + /// X + /// X + /// delete all entries from pool, regardless of address + /// + /// + /// 0 + /// 1 + /// X + /// X + /// X + /// X + /// X + /// X + /// delete entry with this radio address from pool + /// + /// + /// 0 + /// 0 + /// 1 + /// X + /// X + /// X + /// X + /// X + /// write entry with this radio address to pool and delete after transmit + /// + /// + /// 0 + /// 0 + /// 0 + /// 1 + /// X + /// X + /// X + /// X + /// write entry with this radio address to pool and delete after SEMI received + /// + /// + /// 0 + /// 0 + /// 0 + /// 0 + /// 1 + /// X + /// X + /// X + /// write entry with this radio address to pool and leave entry at pool + /// + /// + /// 0 + /// 0 + /// 0 + /// 0 + /// 0 + /// 1 + /// X + /// 0/1 + /// write entry with this radio address to pool, create Wake Up sequence and send out PAM after receive a BUP(LAT) from this address and delete after timeOutPam is elapsed + /// + /// + /// 0 + /// 0 + /// 0 + /// 0 + /// 0 + /// 0 + /// X + /// X + /// write entry with this radio address to pool and delete after timeOutPam is elapsed + /// + /// + /// + public class P811 + { + private readonly Byte[] bits; + + public P811() => this.bits = new Byte[8]; + + private P811(Byte[] bits) => this.bits = bits; + + /// + /// + /// + /// true + /// module 2 is Wakeup Transmitter + /// + /// + /// false + /// module 1 is Wakeup Transmitter + /// + /// + /// + public Boolean WakeUpModul + { + get => this.bits[0] == 1; + set => this.bits[0] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// first transmit Wakeup Sequence and afterwards normal PAM + /// + /// + /// false + /// normal PAM + /// + /// + /// + public Boolean WakeUpCmd + { + get => this.bits[2] == 1; + set => this.bits[2] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// ignore timeout register for automatic delete of PAM + /// + /// + /// false + /// do nothing special + /// + /// + /// + public Boolean IgnoreTimeout + { + get => this.bits[3] == 1; + set => this.bits[3] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// delete entry from PAM pool after SEMI receipt + /// + /// + /// false + /// do nothing after SEMI receipt + /// + /// + /// + public Boolean DelPamSemi + { + get => this.bits[4] == 1; + set => this.bits[4] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// delete entry from PAM pool after PAM transmit + /// + /// + /// false + /// do nothing after PAM transmit + /// + /// + /// + public Boolean DelPamTx + { + get => this.bits[5] == 1; + set => this.bits[5] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// delete from PAM pool + /// + /// + /// false + /// write to PAM pool + /// + /// + /// + public Boolean DelPamAdr + { + get => this.bits[6] == 1; + set => this.bits[6] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// delete all entries from PAM pool + /// + /// + /// false + /// do nothing special + /// + /// + /// + public Boolean DelPamAll + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(P811 param) + => param.bits.GetByte(); + + public static implicit operator P811(Byte _byte) + => new P811(_byte.GetBits()); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PAMStatus.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PAMStatus.cs new file mode 100644 index 00000000..d1a20132 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PAMStatus.cs @@ -0,0 +1,65 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster +{ + using Common.Utils.Extensions; + + using System; + + public class PAMStatus + { + private readonly Byte[] bits; + + public PAMStatus(Byte _byte) + => this.bits = _byte.GetBits(); + + public Boolean CMD_UNKNOWN => this.bits[0] == 1; + + public Boolean WRONG_AUTH => this.bits[1] == 1; + + public Boolean EXPIRED_AUTH => this.bits[2] == 1; + + public Boolean MIXED_TYPES => this.bits[3] == 1; + + public Boolean OUT_OF_RANGE => this.bits[4] == 1; + + public override String ToString() + { + var status = nameof(OK); + var value = this.bits.ToByte(); + + if ((value & 1) == 1) + { + status = nameof(CMD_UNKNOWN); + } + + if ((value & 2) == 2) + { + status = nameof(WRONG_AUTH); + } + + if ((value & 4) == 4) + { + status = nameof(EXPIRED_AUTH); + } + + if ((value & 8) == 8) + { + status = nameof(MIXED_TYPES); + } + + if ((value & 16) == 16) + { + status = nameof(OUT_OF_RANGE); + } + + return status; + } + + public static Byte OK = 0; + + public static implicit operator Byte(PAMStatus status) + => status?.bits?.ToByte() ?? 0xFF; + + public static implicit operator String(PAMStatus status) + => status?.ToString(); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PamTimeout.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PamTimeout.cs new file mode 100644 index 00000000..70b95d7f --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/PamTimeout.cs @@ -0,0 +1,32 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + public class PamTimeout + { + public PamTimeout() => this.Minutes = 0; + + private PamTimeout(Byte minutes) => this.Minutes = minutes; + + /// + /// + /// + /// value == 0 + /// PAM will never automatically deleted + /// + /// + /// value != 0 + /// duration after a PAM will be automatically deleted out of PAM-Pool, if no other rule deletes entry before + /// + /// + /// Several bits at parameter P81-1 or P81-2 may delete entry at PAM-Pool before 5 minutes elapsed. + /// + public Byte Minutes { get; set; } + + public static implicit operator Byte(PamTimeout param) + => param.Minutes; + + public static implicit operator PamTimeout(Byte _byte) + => new PamTimeout(_byte); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/RFModuleOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/RFModuleOperating.cs new file mode 100644 index 00000000..37c5fe33 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/RFModuleOperating.cs @@ -0,0 +1,76 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + public class RFModuleOperating + { + private readonly Byte[] bits; + + public RFModuleOperating() => this.bits = new Byte[8]; + + private RFModuleOperating(Byte[] bits) => this.bits = bits; + + /// + /// 0 -> Transparent Mode at 115k2 Baud 8,n,1 + /// + public OperatingModes OpMode + { + get + { + var bits = new Byte[8]; + + Array.Copy(this.bits, 0, bits, 0, 4); + + return (OperatingModes)bits.GetByte(); + } + set + { + var bits = ((Byte)value).GetBits(); + + Array.Copy(bits, 0, this.bits, 0, 4); + } + } + + /// + /// + /// + /// true + /// external antenna + /// + /// + /// false + /// internal antenna + /// + /// + /// + public Boolean Antenna + { + get => this.bits[4] == 1; + set => this.bits[4] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// Module not powered + /// + /// + /// false + /// Module powered + /// + /// + /// + public Boolean RfOff + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(RFModuleOperating param) + => param.bits.GetByte(); + + public static implicit operator RFModuleOperating(Byte _byte) + => new RFModuleOperating(_byte.GetBits()); + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/SirtOperating.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/SirtOperating.cs new file mode 100644 index 00000000..93446ba5 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Parameters/SirtOperating.cs @@ -0,0 +1,136 @@ +namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters +{ + using System; + + public class SirtOperating + { + private readonly Byte[] bits; + + public SirtOperating() => this.bits = new Byte[8]; + + private SirtOperating(Byte[] bits) => this.bits = bits; + + /// + /// + /// + /// true + /// Bluetooth is output for non-requested messages + /// + /// + /// false + /// USB port is output for non-requested messages + /// + /// + /// non requested messages are received radio payloads if a radio module is switched on + /// + public Boolean DataBtOut + { + get => this.bits[0] == 1; + set => this.bits[0] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// : if both RF-Modules are set to SensusRF Mode, both payloads of RF-Modules will be send out + /// + /// + /// false + /// if both RF-Modules are set to SensusRF Mode, the channel with higher RSSI Level will be send out + /// + /// + /// for test purposes both receiver outputs can be shown - but remember Double traffic rate on Bluetoothor USB-output + /// + public Boolean BothChsOut + { + get => this.bits[1] == 1; + set => this.bits[1] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// also payloads with incorrect radio-CRC will send out! + /// + /// + /// false + /// normal operation + /// + /// + /// may be only interesting for test purposes + /// + public Boolean IgnoreCRC + { + get => this.bits[2] == 1; + set => this.bits[2] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// don't switch Power path off if going to USB Suspend and drawing more current as allowed + /// + /// + /// false + /// switch Power path off if going to USB Suspend + /// + /// + /// New at Version 1.0.0.6 + /// + public Boolean IgnoreUSBrules + { + get => this.bits[3] == 1; + set => this.bits[3] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// after "TIME_OFF" is elapsed without any command to SIRT, SIRT will be switched off + /// + /// + /// false + /// normal operation + /// + /// + /// timeout starts at beginning, if any command or communication to and from SIRT is initiated + /// + public Boolean SirtPwrSave + { + get => this.bits[6] == 1; + set => this.bits[6] = (Byte)(value ? 1 : 0); + } + + /// + /// + /// + /// true + /// SIRT will be switched off {like push off button} + /// + /// + /// false + /// normal operation + /// + /// + /// + /// SIRT can be switched off per command, but no answer will send if this bit was set.SIRT can not be switched + /// on per command only by pushing green button for a second + /// + /// + public Boolean SirtOff + { + get => this.bits[7] == 1; + set => this.bits[7] = (Byte)(value ? 1 : 0); + } + + public static implicit operator Byte(SirtOperating param) + => param.bits.GetByte(); + + public static implicit operator SirtOperating(Byte _byte) + => new SirtOperating(_byte.GetBits()); + } +} diff --git a/Common/Ui/Common.UI.WPFConnector/Properties/AssemblyInfo.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Properties/AssemblyInfo.cs similarity index 85% rename from Common/Ui/Common.UI.WPFConnector/Properties/AssemblyInfo.cs rename to Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Properties/AssemblyInfo.cs index ece2b4ee..b18a3667 100644 --- a/Common/Ui/Common.UI.WPFConnector/Properties/AssemblyInfo.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports.SirtBroadcaster/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("WPFConnector")] +[assembly: AssemblyTitle("Common.Hardware.Interfaces.Ports.SirtBroadcaster")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WPFConnector")] +[assembly: AssemblyProduct("Common.Hardware.Interfaces.Ports.SirtBroadcaster")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("37e4bf89-44ae-4133-be0b-8355f791a79d")] +[assembly: Guid("f408de9e-01e6-4cff-ae79-b572b0674fa2")] // Version information for an assembly consists of the following four values: // diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/Common.Hardware.Interfaces.Ports.csproj b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/Common.Hardware.Interfaces.Ports.csproj index b94e8bae..d98df42c 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/Common.Hardware.Interfaces.Ports.csproj +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/Common.Hardware.Interfaces.Ports.csproj @@ -42,6 +42,7 @@ + diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/JustSerialPort.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/JustSerialPort.cs new file mode 100644 index 00000000..47254b14 --- /dev/null +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/JustSerialPort.cs @@ -0,0 +1,135 @@ +namespace Common.Hardware.Interfaces.Ports +{ + using System; + using System.Collections.Concurrent; + using System.IO.Ports; + + public class JustSerialPort + { + private static readonly ConcurrentDictionary serialPorts + = new ConcurrentDictionary(); + private readonly SerialPortSettings serialPortSettings; + private readonly String portName; + private Int32 readBufferSize; + private Byte[] buffer; + + public Boolean IsOpen + { + get => serialPorts.TryGetValue(this.portName, out var serialPort) + && serialPort.IsOpen; + } + + public JustSerialPort(SerialPortSettings serialPortSettings) + { + + this.serialPortSettings = serialPortSettings; + this.portName = this.serialPortSettings.PortName; + } + + public event Action Logging; + + public void Log(Object message) + => this.Logging?.Invoke($"{this.portName}|{message}"); + + public Boolean TryClose() + { + var closed = false; + + try + { + if (serialPorts.TryRemove(this.portName, out var serialPort)) + { + serialPort.Close(); + serialPort = null; + closed = true; + } + } + catch (Exception e) + { + this.Log(e); + } + + return closed; + } + + public Boolean TryOpen() + { + var opened = false; + + _ = this.TryClose(); + + try + { + var serialPort = new SerialPort + { + BaudRate = this.serialPortSettings.BaudRate, + DataBits = this.serialPortSettings.DataBits, + Parity = this.serialPortSettings.Parity, + PortName = this.serialPortSettings.PortName, + StopBits = this.serialPortSettings.StopBits, + WriteTimeout = 100, + ReadTimeout = 100, + }; + + if (serialPorts.TryAdd(this.portName, serialPort)) + { + serialPort.Open(); + + this.readBufferSize = serialPort.ReadBufferSize; + this.buffer = new Byte[this.readBufferSize]; + opened = serialPort.IsOpen; + } + } + catch (Exception e) + { + this.Log(e); + } + + return opened; + } + + public Byte[] ReadBytes() + { + var length = 0; + var bytes = new Byte[length]; + + if (serialPorts.TryGetValue(this.portName, out var serialPort)) + { + if (serialPort.IsOpen && serialPort.BytesToRead > 0) + { + Array.Clear(this.buffer, 0, this.readBufferSize); + + length = serialPort.Read(this.buffer, 0, this.readBufferSize); + bytes = new Byte[length]; + + Array.Copy(this.buffer, 0, bytes, 0, length); + } + } + + return bytes; + } + + public override String ToString() + => $"{this.serialPortSettings.PortName}, " + + $"{this.serialPortSettings.BaudRate}, " + + $"{this.serialPortSettings.DataBits}, " + + $"{this.serialPortSettings.Parity}, " + + $"{this.serialPortSettings.StopBits}"; + + public void WriteBytes(params Byte[] bytes) + { + if (bytes != null) + { + var bytesLength = bytes.Length; + + if (bytes.Length > 0 && serialPorts.TryGetValue(this.portName, out var serialPort)) + { + if (serialPort.IsOpen) + { + serialPort.Write(bytes, 0, bytes.Length); + } + } + } + } + } +} diff --git a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/SerialPortBase.cs b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/SerialPortBase.cs index 71143b4c..5da34d03 100644 --- a/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/SerialPortBase.cs +++ b/Common/Hardware/Interfaces/Ports/Common.Hardware.Interfaces.Ports/SerialPortBase.cs @@ -105,7 +105,7 @@ } else { - this.LogMessage($"{this.PortName} cann't be addedd!"); + this.LogMessage($"{this.PortName} can not be addedd!"); } } catch (Exception e) @@ -116,16 +116,16 @@ public override String ToString() => serialPorts.TryGetValue(this.PortName, out var serialPort) - ? $"{serialPort.PortName}, " + - $"{serialPort.BaudRate}, " + - $"{serialPort.DataBits}, " + - $"{serialPort.Parity}, " + - $"{serialPort.StopBits}" - : $"{this.settings.PortName}, " + - $"{this.settings.BaudRate}, " + - $"{this.settings.DataBits}, " + - $"{this.settings.Parity}, " + - $"{this.settings.StopBits}"; + ? $"{serialPort.PortName}, " + + $"{serialPort.BaudRate}, " + + $"{serialPort.DataBits}, " + + $"{serialPort.Parity}, " + + $"{serialPort.StopBits}" + : $"{this.settings.PortName}, " + + $"{this.settings.BaudRate}, " + + $"{this.settings.DataBits}, " + + $"{this.settings.Parity}, " + + $"{this.settings.StopBits}"; public virtual Byte[] Write(params Byte[] data) { diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs index 30583d81..b0e2ea9f 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs @@ -88,8 +88,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// private static readonly List _excludedFromCompareParameters = new List { - "SYSTEM_UpgradePermissions", // Once set to deviating from 0xFF it will maintain this after reboot, - // it only can be overwritten temporary in RAM! + //THW 15-Aug-2024 reactivated "SYSTEM_UpgradePermissions", + //// Once set to deviating from 0xFF it will maintain this after reboot, + //// it only can be overwritten temporary in RAM! + "CUSTOMER_AlarmVisualMask", // Will be cyclically overwritten by SENSUSRADIO "SENSUSRADIO_UpgFWVersion" // After a FW-Update the FW version has changed }; diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs index 76190452..59227a53 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs @@ -41,9 +41,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus } GenesisStatus status; + try { - var url = ServiceUrls.GetProductionSkipAndLifeTimeInfoServiceUrl(); + var url = ""; // ServiceUrls.GetProductionSkipAndLifeTimeInfoServiceUrl(); url += $"{pcbId}&orderNumber={orderNumber}"; var response = LocalWebRequest.GetRequest(url, 2000); status = JsonConvert.DeserializeObject(response); @@ -58,6 +59,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus } var type = typeof(GenesisStatus); + foreach (var prop in type.GetProperties()) { try @@ -86,6 +88,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus public static Boolean BuildLifeTimeInformation(GenesisMeter currentGenesis, GenesisStatus status) { Boolean retVal; + if (currentGenesis == null || status == null) return false; // read information from genesis diff --git a/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataPackages.csproj b/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataPackages.csproj index d6cac487..b1eddd98 100644 --- a/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataPackages.csproj +++ b/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataPackages.csproj @@ -212,9 +212,6 @@ MinimumRecommendedRules.ruleset - - Properties\SharedAssemblyInfo.cs - diff --git a/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataTypes/Calibration.cs b/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataTypes/Calibration.cs index 7a982ea8..af42c27a 100644 --- a/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataTypes/Calibration.cs +++ b/Common/Hardware/WaterMeter/MagFlux/DataPackages/DataTypes/Calibration.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes { diff --git a/Common/Hardware/WaterMeter/MagFlux/DataPackages/MeasurementRecords/MagFluxRecord.cs b/Common/Hardware/WaterMeter/MagFlux/DataPackages/MeasurementRecords/MagFluxRecord.cs index 575d0cff..0d8a3097 100644 --- a/Common/Hardware/WaterMeter/MagFlux/DataPackages/MeasurementRecords/MagFluxRecord.cs +++ b/Common/Hardware/WaterMeter/MagFlux/DataPackages/MeasurementRecords/MagFluxRecord.cs @@ -14,17 +14,17 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.MeasurementRecor /// /// Sensor Id of MagFlux /// - public String SensorId; + public String SensorId { set; get; } /// /// Serial number of MagFlux /// - public String UniqueId; + public String UniqueId { set; get; } /// /// Status of sensor and electronics /// - public UInt32 StatusBits; + public UInt32 StatusBits { set; get; } /// /// String delimiter to separate elements in ToString() routine diff --git a/Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoint.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoint.cs similarity index 89% rename from Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoint.cs rename to Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoint.cs index 8048e942..3d3fcf63 100644 --- a/Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoint.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoint.cs @@ -1,7 +1,9 @@ -using System; -using System.Xml; +// Ignore Spelling: lps -namespace XYLEM.Device +using System; +using XYLEM.Base; + +namespace XYLEM { /// /// A single calibration point @@ -64,6 +66,19 @@ namespace XYLEM.Device return this.CompareTo(other) == 0; } + public override bool Equals(object obj) + { + if (!(obj is CalibrationPoint)) return false; + + CalibrationPoint p = (CalibrationPoint)obj; + return this == p; + } + + public override int GetHashCode() + { + return HashTools.ShiftAndWrap(ReferenceFlowRate_lps.GetHashCode(), 2) ^ ReportedFlowRate_lps.GetHashCode(); + } + #region Operator == > < ! .. public static bool operator ==(CalibrationPoint a, CalibrationPoint b) { diff --git a/Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoints.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoints.cs similarity index 89% rename from Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoints.cs rename to Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoints.cs index fa33eb6e..1fcffee1 100644 --- a/Common/modbus_master_csharp/src/modbus_master_csharp/Device/CalibrationPoints.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/CalibrationPoints.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Xml; +using XYLEM.Base; using XYLEM.Base.XML; -namespace XYLEM.Device +namespace XYLEM { [Serializable] public class CalibrationPoints : IComparable, IEquatable @@ -143,6 +141,31 @@ namespace XYLEM.Device return this.CompareTo(other) == 0; } + public override bool Equals(object obj) + { + if (!(obj is CalibrationPoints)) return false; + + CalibrationPoints p = (CalibrationPoints)obj; + return this == p; + } + + public override int GetHashCode() + { + if (calibrations == null) + { + return base.GetHashCode(); + } + else + { + int hash = 0; + foreach (var calibration in calibrations) + { + hash = HashTools.ShiftAndWrap(hash.GetHashCode(), 2) ^ calibration.GetHashCode(); + } + return hash; + } + } + #region Operator == > < ! .. public static bool operator ==(CalibrationPoints a, CalibrationPoints b) { diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFlux.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFlux.cs new file mode 100644 index 00000000..900a6477 --- /dev/null +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFlux.cs @@ -0,0 +1,67 @@ +using System; +using System.IO.Ports; +using XYLEM.Base.Config; +using XYLEM.Communication; + +namespace XYLEM +{ + /// + /// Command interface for MagFlux 6200 + /// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft + /// + internal interface IMagFlux : IMagFluxRequestProtocol + { + #region When sharing same serial port + + /// + /// Connect when using same serial port + /// + /// + /// + /// + Boolean Connect(UInt16 id, ModbusCom md_com); + + /// + /// Get current device com settings + /// + /// + SerialPortSettingClass GetComSetting(); + + /// + /// Current modbus device device ID / address + /// + UInt16 Device_ID { get; } + + #endregion + + + #region For stand alone use without sharing same serial port + + #endregion + /// + /// Make communication connection to Meter + /// !!NOTE!! Only one meter is supported for each com port + /// + /// Like "COM1" + /// >Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting + /// true on okay or false on error + Boolean Connect(string comport, UInt16 id = 1); + + /// + /// Make communication connection to Meter with a specific communication setup + /// !!NOTE!! Only one meter is supported for each com port + /// + /// >Like "COM1" + /// >Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting + /// Like 9600 (default on RS485) + /// Like Parity.Even (default on RS485) + /// + Boolean Connect(string comport, UInt16 id, UInt32 baudRate, Parity parity); + + /// + /// Close communication connection to Meter + /// + /// true on okay or false on error + Boolean CloseConnection(); + } +} diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxAPI.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxAPI.cs new file mode 100644 index 00000000..b6c16d95 --- /dev/null +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxAPI.cs @@ -0,0 +1,40 @@ +using System.IO.Ports; +using XYLEM.Device; + +namespace XYLEM +{ + public interface IMagFluxAPI + { + + /// + /// Make communication connection to Meter + /// + /// Imported note: Devices placed on same serial connection, must have same communication settings. + /// Ex. All devices on same serial connection must be configured to same baudrate, parity + /// + /// + /// Like "COM1" + /// Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting + /// folder path for where to log file should be saved + /// RUN_TYPE.Normal with connection to serial port, if not set + /// Return a MagFlux device or "null" if failing connect + IMagFluxRequestProtocol Connect(string comport, ushort id = 1, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal); + + /// + /// Make communication connection to Meter with a specific communication setup + /// + /// Imported note: Devices placed on same serial connection, must have same communication settings. + /// Ex. All devices on serial connection must be configured to same baudrate, parity + /// + /// + /// >Like "COM1" + /// Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting + /// Like 9600 (default on RS485) + /// Like Parity.Even (default on RS485) + /// folder path for where to log file should be saved + /// RUN_TYPE.Normal with connection to serial port, if not set + /// Return a MagFlux device or "null" if failing connect + /// if the configuration is not valid + IMagFluxRequestProtocol Connect(string comport, ushort id, uint baudRate, Parity parity, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal); + } +} \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxRequestProtocol.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxRequestProtocol.cs new file mode 100644 index 00000000..0e48929e --- /dev/null +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/IMagFluxRequestProtocol.cs @@ -0,0 +1,374 @@ +using System; +using System.Collections.Generic; +using XYLEM.Base; + +namespace XYLEM +{ + /// + /// Command interface for MagFlux + /// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft + /// + public interface IMagFluxRequestProtocol + { + /// + /// Is connected + /// + /// true if yes + Boolean IsConnected(); + + /// + /// Get current device Modbus ID / Device Address + /// + /// 1-246 + /// true on okay or false on error + Boolean GetDeviceID(out int value_out); + + /// + /// Simple Check if a device ID is Free or responding + /// Reads address 0 to check on any device response + /// Is used in SetDeviceID() before attempting change ID + /// + /// + /// Return True if no device was responding on ID + Boolean IsDeviceID_Free(uint id_to_check); + + /// + /// Set current device Modbus ID / Device Address + /// + /// 1-246 (Don't use device ID 247, it is a MJK broad cast) + /// true on okay or false on error + /// Notes: + /// There is a simple check on new device id is free (read address 0 check on) + /// Change of device ID is instantly and may loose any communication if not able to function on this ID. + /// Troubleshooting on failing: + /// * Power off and remove optional USBC cable on MagFlux. + /// * Remove all other devices on RS485 and retry connection. + /// * Check Device ID manually on LCD other program like 840126 with USBC connection. + Boolean SetDeviceID(UInt16 new_id); + + /// + /// Get printout of communication counters + /// + /// + string GetComCounters(); + + /// + /// Set location for where log data can saved. + /// + /// path for where to log file should be saved + /// set a custom log file name without extension (ex. "UserCustomLogFile") or null if use default + /// true on okay or false on error + Boolean SetLogLocation(String path, string filename = null); + + /// + /// Open saved log file + /// + void OpenLogFile(); + + /// + /// Get latest log added to log file while this program was running + /// + /// How long to go back after log messages, if Null then standard 1 minute + /// "Lasted" Log messages Queue After last connection + List GetLatestLogs(DateTime? from = null); + + /// + /// Unique-ID for the MagFlux electronics + /// + /// a hex decimal string 0x1234ABCDEF or NULL at error + /// true on okay or false on error + Boolean GetUniqueId(out string value_out); + + /// + /// MagFlux metrology board serial number + /// More info on: + /// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers + /// + /// a serial number ex. 510360.00000105W46Y23 or NULL at error + /// true on okay or false on error + Boolean GetBoardSerialNo(out string value_out); + + /// + /// MagFlux metrology board serial number + /// More info on: + /// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers + /// + /// a serial number ex. 510360.00000105W46Y23 + /// true on okay or false on error + Boolean SetBoardSerialNo(string new_serial_number); + + /// + /// Get the firmware version + /// + /// like 1.2.4 (MAJOR.MINOR.REVISION) + /// true on okay or false on error + Boolean GetFirmwareVersion(out string value_out); + + /// + /// Get Current device register version + /// + /// like "51" or on connecting error "?", "0", "-1" + /// true on okay or false on error + Boolean GetRegisterVersion(out string value_out); + + /// + /// Get Current communication register version used by the interface + /// + /// like "51" or on error "?", "0", "-1" + /// true on okay or false on error + Boolean GetAPIRegisterVersion(out string value_out); + + /// + /// Get the firmware build date + /// + /// like 2022/12/24 13:00:00 or 2022-12-24 13:45:10 + /// true on okay or false on error + Boolean GetFwBuildDate(out string value_out); + + /// + /// Git Hash to Unique identify firmware + /// + /// like 0xABCDE123 + /// true on okay or false on error + Boolean GetFwGitHash(out string value_out); + + + /// + /// Get Device runtime after Last reset + /// + /// Time since last device reset in seconds + /// + Boolean GetRuntimeAfterLastReset_sec(out UInt32 value_out); + + /// + /// Flow rate calibrated + /// + /// Actual flow rate [l/s] + /// true on okay or false on error + Boolean GetFlowRate_lps(out Single value_out); + + /// + /// !!! Warning make sure to turn off simulation, when calibration off sensor is done !!! + /// ---- + /// Set a fixed test flow to force MagFlux, for check of digital output pulse etc. + /// ---- + /// Will also activate and start fixed simulated flow in device + /// Used for getting a fixed simulated flow before sensor calibration from MagFlux + /// Note on limitation: + /// The actual resulting flow is depended on sensor calibration and MagFlux conversion from m/s to flow. + /// Always check resulting flow with GetFlowRate_lps() to verify if the same as expected + /// With a calibration of all 0 (equal no calibration 1:1) normally produce same GetFlowRate_lps() down to 3 digit precision. + /// + /// The fixed flow to force MagFlux to output [l/s] + /// true on okay or false on error + Boolean SetSimulatedFlow_lps(double value_lps); + + /// + /// Get the correction factor from board "1.0000" is default none calibration board + /// + /// + /// true on okay or false on error + Boolean GetElectrodeBoardCorrectionFactor(out Single value_out); + + /// + /// Get Empty pipe control bits + /// Bit0="EPD disabled", 1="Enabled w. Flags only", 2="EPD enabled full" + /// + /// empty pipe control bits + /// true on okay or false on error + Boolean GetEmptyPipeControl(out Int32 epd_cntl_bits); + + /// + /// Ignore Empty pipe flag on Healthy, because it is not yet working correct + /// Note: Not 100% secure all test is working during empty pipe, metrology board firmware may not allow running during detection of empty pipe + /// + /// Default is currently True and will be set True on each connect (In the future when Empty pipe works it will be default false) + Boolean GetIgnoreFailOnEmptyPipeOnHealthy(); + + + /// + /// Ignore Empty pipe flag on Healthy, because it is not yet working correct + /// Note: Not 100% secure all test is working during empty pipe, metrology board firmware may not allow running during detection of empty pipe + /// + /// True to ignore empty pipe warning + void SetIgnoreFailOnEmptyPipeOnHealthy(Boolean doIgnore); + + /// + /// !!! Warning don't use this feature on already correct calibrated and configured boards !!! + /// Can only be used for demo and not for real sensor customer calibration measurement + /// ---- + /// Set a uncalibrated blank board to defaults, that allow using it for testing + /// ---- + /// Note: + /// Limitations will take up to a minute to exit, if all configs needs to be set in a blank device + /// * If "1.00" and device Healthy not, then rewrite "ElectrodeBoardCorrectionFactor" as "1.00" to remove PDS Invalid system calibration error + /// * If Sensor serial number is "0", it will be changed to "2" + /// * If Flange type is "0", It will be changed to "1" equal "EN-1092-1" + /// * If board PCB SN is blank "", then to "Demo [Date on change]" + /// * if Empty Pipe Control bits is all "0", then turn on "Enable w. flags only" + /// * Prepare with a default calibration that is 1:1 + /// + /// true on okay or false on error + Boolean SetPCBToDemoDefaults(); + + /// + /// Is the fixed test flow active + /// Used for getting a fixed simulated flow from MagFlux + /// + /// true if ON + Boolean IsSimulatedFlowActive(); + + /// + /// Turn on/off fixed test flow output from MagFlux + /// Used for getting a fixed simulated flow from MagFlux + /// + /// + /// true on okay or false on error + Boolean SetSimulatedFlowActive(Boolean testFlowOn); + + /// + /// Total forward volume (Positive flow volume totalizator) + /// + /// volume in in liter [l] + /// true on okay or false on error + Boolean GetForwardVolume_l(out Double value_out); + + /// + /// Total backward volume (Reversed or negative flow volume totalizator) + /// + /// + /// true on okay or false on error + Boolean GetBackwardVolume_l(out Double value_out); + + /// + /// Get the general sensor information + /// + /// sensor information + /// true on okay or false on error + Boolean GetSensorInfo(out SensorInfo value_out); + + /// + /// MagFlux Sensor serial number + /// + /// a decimal serial number ex. 12345678 or NULL at error + /// true on okay or false on error + Boolean GetSensorSerialNo(out string value_out); + + /// + /// Set MagFlux Sensor serial number + /// + /// + /// true on okay or false on error + Boolean SetSensorSerialNo(UInt64 new_serial_number); + + /// + /// MagFlux Sensor nominal DN size in millimeters + /// + /// DN size in [mm] is -1 on error + /// true on okay or false on error + Boolean GetDn_mm(out Int32 dn_mm_out); + + /// + /// Set Sensor nominal DN size in millimeters + /// + /// DN size in [mm] ex 50 is 50mm or DN50 + /// true on okay or false on error + Boolean SetDn_mm(UInt16 new_dn_mm); + + /// + /// Get Sensor Flange Type + /// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207" + /// + /// Flange type number + /// true on okay or false on error + Boolean GetFlangeType(out Int32 flangeType_out); + + /// + /// Set Sensor Flange Type + /// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207" + /// + /// Flange type number + /// true on okay or false on error + Boolean SetFlangeType(UInt16 new_flangeType); + + /// + /// get what volume per pulse for both forward and reverse counter is + /// Note: will return only forward pulse volume if both settings is not the same. + /// + /// A pulse volume in [ml] (milliliter) + /// true on okay or false on error + Boolean GetVolumePerPulse_ml(out UInt32 pls_vol_ml); + + /// + /// Set what volume per pulse for both forward and reverse counter is + /// + /// A pulse volume in [ml] (milliliter) + /// true on okay or false on error + Boolean SetVolumePerPulse_ml(UInt32 pls_vol_ml); + + /// + /// Get what pulse turn on time for both forward and reverse counter is + /// Note: will return only forward turn on time if both settings is not the same. + /// + /// A pulse turn on time in ms (millisecond) Note setting to 0 will result in pulse time be as fast as device support + /// true on okay or false on error + Boolean GetPulseOutput_Ton_ms(out UInt16 pls_Ton_ms); + + /// + /// Set what pulse turn on time for both forward and reverse counter is + /// + /// A pulse turn on time in ms (millisecond) + /// true on okay or false on error + Boolean SetPulseOutput_Ton_ms(UInt16 pls_Ton_ms); + + /// + /// Check if there is problem with the DUT + /// use " to get a list of error messages for debug problems + /// + /// >true if device operates correctly + Boolean GetDeviceHealthy(); + + /// + /// get a list of error messages for debug problem + /// + /// Will return a empty list if there is no messages to return + /// true on okay or false on error + Boolean GetDeviceErrorMessages(out List status_list_out); + + /// + /// This function prepares the DUT for the calibration. + /// + /// ATTENTION: + /// This function needs to be called before the calibration process starts any flow of water. + /// + /// true on okay or false on error + Boolean PrepareDeviceForCalibration(); + + /// + /// This function will abort started or failed calibration to bring DUT back to normal calibration state + /// + /// true on okay or false on error + Boolean AbortDeviceForCalibration(); + + /// + /// The maximum calibration points that is supported by the device + /// + /// number of points possible to get and set in device + int GetCalibrationPointsMax(); + + /// + /// Get list of calibration points saved in DUT + /// + /// The calibrations points from device + /// true on okay or false on error + Boolean GetCalibrationPoints(out CalibrationPoints values_read); + + /// + /// set calibration in DUT. + /// Remember to run before the calibration process is started. + /// + /// A list of calibration points to write to DUT + /// true on okay or false on error + Boolean SetCalibrationPoints(CalibrationPoints new_calibration_points); + } +} diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/SensorInfo.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/SensorInfo.cs new file mode 100644 index 00000000..7a8b4451 --- /dev/null +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/api_doc/SensorInfo.cs @@ -0,0 +1,90 @@ +using System; + +namespace XYLEM +{ + public class SensorInfo + { + /// + ///Sensor serial number ex. 0x1234ABCDEF or 0 as unknown / not defined + /// + public UInt64 SerialNumber { get; private set; } + + /// + /// MagFlux Sensor nominal DN size in millimeters + /// + public Int32 DN_mm { get; private set; } + + /// + /// MagFlux Sensor Flange Type + /// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207" + /// + public Int32 FlangeType { get; private set; } + + /// + /// Calibration method was used. 0 is default, for calibration on flow rig for 5 min per point + /// + public Int32 CalibrationVersion { get; private set; } + + /// + /// Sampling scheme code used by front end measurement. //NL// 0=32/40, 1=20/40 + /// + public Int32 SamplingSchemeCode { get; private set; } + + /// + /// Coil driver frequency, 0 = 0.625Hz, 1= 1.25Hz, 2 = 2.5Hz, 3 = 5Hz, 4 = 10Hz, + /// + public Int32 CoilDriverFrequencyConfig { get; private set; } + + /// + /// Number of calibration points + /// The same as calling "Calibration.Get_number_of_calibrations()" + /// + public Int32 NumberOfCalibrations { get; private set; } + + /// + /// List of calibration points saved in DUT + /// + public CalibrationPoints Calibration { get; private set; } + + + public SensorInfo( + UInt64 SerialNumber, + Int32 DN_mm, + Int32 FlangeType, + Int32 CalibrationVersion, + Int32 SamplingSchemeCode, + Int32 CoilDriverFrequencyConfig, + CalibrationPoints Calibration) + { + this.SerialNumber = SerialNumber; + this.DN_mm = DN_mm; + this.FlangeType = FlangeType; + this.CalibrationVersion = CalibrationVersion; + this.SamplingSchemeCode = SamplingSchemeCode; + this.CoilDriverFrequencyConfig = CoilDriverFrequencyConfig; + this.Calibration = Calibration; + if (null == this.Calibration) + { + this.NumberOfCalibrations = 0; + } + else + { + this.NumberOfCalibrations = this.Calibration.Get_number_of_calibrations(); + } + } + + public override String ToString() + { + String strReturn = ""; + strReturn += $"SN: {SerialNumber}" + Environment.NewLine; + strReturn += $"DN{DN_mm} [mm]" + Environment.NewLine; + strReturn += $"Flange: {FlangeType}" + Environment.NewLine; + strReturn += $"Cal. Ver: {CalibrationVersion}" + Environment.NewLine; + strReturn += $"Sampling Scheme: {SamplingSchemeCode}" + Environment.NewLine; + strReturn += $"Coil Freq.: {CoilDriverFrequencyConfig}" + Environment.NewLine; + strReturn += $"Number of Cal.points: {NumberOfCalibrations}" + Environment.NewLine; + strReturn += $"Cal.points:" + Environment.NewLine + Calibration.ToString(); + return strReturn; + } + } +} diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/magflux_api.dll b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/magflux_api.dll new file mode 100644 index 00000000..b60e13aa Binary files /dev/null and b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/magflux_api.dll differ diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/shared_code.dll b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/shared_code.dll new file mode 100644 index 00000000..61ae455b Binary files /dev/null and b/Common/Hardware/WaterMeter/MagFlux/MagFluxApi/shared_code.dll differ diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/CommunicationConfig.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/CommunicationConfig.cs index 11ae3929..2dd69031 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/CommunicationConfig.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/CommunicationConfig.cs @@ -1,4 +1,6 @@ using System; +using Xylem.Common.Hardware.Interfaces.Ports.PortCore; +using Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol; namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxConfig { diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/MagFluxConfig.csproj b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/MagFluxConfig.csproj index f51296f0..7df7d4b8 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/MagFluxConfig.csproj +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/MagFluxConfig.csproj @@ -57,5 +57,15 @@ + + + {2E139F63-B6FE-4EA9-A098-85364FE9B26C} + PortCore + + + {63E0AC5E-B7C8-4363-A2FE-BE489E648FF0} + TransmitProtocol + + \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/Properties/AssemblyInfo.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/Properties/AssemblyInfo.cs index 04865a04..4c287db8 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/Properties/AssemblyInfo.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxConfig/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -10,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Xylem")] [assembly: AssemblyProduct("MagFluxConfig")] -[assembly: AssemblyCopyright("Copyright © Xylem 2023")] +[assembly: AssemblyCopyright("Copyright © Xylem 2023..2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,4 +32,3 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateDef.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateDef.cs index 7ea856a0..63f8fda1 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateDef.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateDef.cs @@ -38,7 +38,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.Consts new StateStruct(State.FlowOutOfRange, "Flow above calibrated region"), new StateStruct(State.FlowNewStart, "Flow calculation new start"), new StateStruct(State.TemperatureOutOfRange, "Temperature out of range"), - new StateStruct(State.EmptyPipe, "Empty pipe detected"), + new StateStruct(State.EmptyPipe, "Empty Pipe Detected"), new StateStruct(State.DisconnectedOrHwFault, "Disconnected or hardware fault") }; } @@ -74,7 +74,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.Consts public static List GetInfoOfAllErrorStates() { var errorStateInfos = (from state in _stateContainer where state.State - != State.Okay select state.Info).ToList(); + != State.Okay select state.Info).ToList(); return errorStateInfos; } diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateStruct.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateStruct.cs index 4bb8e795..8f9409b2 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateStruct.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Consts/StateStruct.cs @@ -5,7 +5,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.Consts /// /// Concatenation between final test state and text /// - struct StateStruct + internal struct StateStruct { /// /// Assign state information tas text for state diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs index c39d1be9..9eee69f4 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs @@ -106,7 +106,42 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore } = "?"; /// - /// Represent pcb serial number + /// Represent MagFlux API Version + /// + public String MagFluxRegisterApiVersion + { + get; + private set; + } = "?"; + + + /// + /// Represent sensor serial number + /// + public String SensorSerialNo + { + get; private set; + } + + /// + /// Represents Empty Pipe Detection control bits + /// Bit0="EPD disabled", 1="Enabled w. Flags only", 2="EPD enabled full" + /// + public Int32 EpdControlBits + { + get; private set; + } + + /// + /// Represent pcb calibration + /// + public Single BoardCalib + { + get; private set; + } + + /// + /// Represent pcb identification /// public String PcbId { @@ -800,18 +835,33 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore { FwGitHash = gitHash; } + if (RequestProtocol.GetApiRegisterVersion(out var apiRegisterVersion)) + { + MagFluxRegisterApiVersion = apiRegisterVersion; + } if (RequestProtocol.GetUniqueId(out var uniqueId)) { UniqueId = uniqueId; } - // The PcbId will be named as SensorSerialNo by MJK + if (RequestProtocol.GetSensorSerialNo(out var sensorSerialNo)) + { + SensorSerialNo = sensorSerialNo; + } if (RequestProtocol.GetPcbId(out var pcbId)) { PcbId = pcbId; } + if (RequestProtocol.GetElectrodeBoardCorrectionFactor(out var boardCalib)) + { + BoardCalib = boardCalib; + } + if (RequestProtocol.GetEmptyPipeControl(out var epd_cntl_bits)) + { + EpdControlBits = epd_cntl_bits; + } RequestProtocol?.GetCalibrationPoints(out _); - StreamingProtocol?.SetDecodingMask(pcbId, uniqueId); + StreamingProtocol?.SetDecodingMask(SensorSerialNo, uniqueId); return IsLoggedOn; } @@ -981,7 +1031,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore } } } - return ret.HasValue ? ret.Value : false; + return ret ?? false; } @@ -1017,6 +1067,42 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore RequestProtocol?.CloseConnection(); } + ///// + ///// Turn on/off fixed test flow output from MagFlux + ///// Used for getting a fixed simulated flow from MagFlux + ///// + ///// + ///// true on okay or false on error + //public Boolean SetSimulatedFlowActive(Boolean testFlowOn) + //{ + // _logger.Info($"Slot:{Slot} - Set test flow"); + // return RequestProtocol.SetSimulatedFlowActive(on); + //} + + ///// + ///// Is the fixed test flow active + ///// Used for getting a fixed simulated flow from MagFlux + ///// + ///// true if ON + //public Boolean IsSimulatedFlowActive() + //{ + // _logger.Info($"Slot:{Slot} - Get test flow setting"); + // return RequestProtocol.IsSimulatedFlowActive(); + //}; + + /// + /// Set PCB settings and PCB calibrations to default. + /// + public Boolean SetPCBToDemoDefaults() + { + _logger.Info($"Slot:{Slot} - Set PCB settings and PCB calibrations to default"); + if (RequestProtocol == null) + return false; + var retVal = RequestProtocol.SetPCBToDemoDefaults(); + RequestProtocol?.CloseConnection(); + return retVal; + } + /// /// Set a new meter size to MagFlux /// @@ -1031,14 +1117,14 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore } /// - /// Set a new pcbId to MagFlux + /// Set a new sensor serial number to MagFlux /// - public Boolean SetPcbId(UInt32 pcbId) + public Boolean SetSensorSerialNo(UInt32 sensorSerialNo) { - _logger.Info($"Slot:{Slot} - Set meter PCB ID (Sensor serial no.)"); + _logger.Info($"Slot:{Slot} - Set sensor serial no."); if (RequestProtocol == null) return false; - var retVal = RequestProtocol.SetPcbId(pcbId); + var retVal = RequestProtocol.SetSensorSerialNo(sensorSerialNo); RequestProtocol?.CloseConnection(); return retVal; } @@ -1086,7 +1172,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore throw new NotImplementedException(); } - /// + /// public void SetLcdText(Boolean release, Byte[] textInHex) { throw new NotImplementedException(); diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Properties/AssemblyInfo.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Properties/AssemblyInfo.cs index 4155a811..ecda56d2 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Properties/AssemblyInfo.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Xylem")] [assembly: AssemblyProduct("MagFluxCore")] -[assembly: AssemblyCopyright("Copyright © Xylem 2023")] +[assembly: AssemblyCopyright("Copyright © Xylem 2023..2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,4 +33,3 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/Properties/AssemblyInfo.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/Properties/AssemblyInfo.cs index d4f9d6ab..c23e017c 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/Properties/AssemblyInfo.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Xylem")] [assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Copyright © Xylem 2023")] +[assembly: AssemblyCopyright("Copyright © Xylem 2023..2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,4 +33,3 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs index 0bf07ae7..3c7562f7 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using NLog; +using XYLEM; using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore; using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.EventArguments; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes; using Xylem.Common.Utils.Logging; -using XYLEM.Device; namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol { @@ -18,28 +18,37 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol public class RequestProtocol : BaseProtocol { private readonly String _ident; - private readonly ILogger _logger; + private readonly ILogger _logger; private IMagFluxRequestProtocol _magFluxRequestProtocol; + private IMagFluxAPI _magFluxApi; // calibration point in cubic meters per hour private List _calibPointsCmPerH; /// + /// + /// - MagFluxApi + /// public RequestProtocol(String ident) : base(ident) { _ident = ident; - _magFluxRequestProtocol = new MagFlux6200(); + _magFluxApi = new MagFluxAPI(); _calibPointsCmPerH = new List(); - _logger = NLogHelper.CreateOrGetMultiLogger(_ident, "", "RequestProtocol", "MeterBase", "MeterBase"); + _logger = NLogHelper.CreateOrGetMultiLogger(_ident, "", "RequestProtocol", "MeterBase", + "MeterBase"); } /// > + /// + /// - MagFluxApi + /// public override void Dispose() { _calibPointsCmPerH.Clear(); _calibPointsCmPerH = null; - _magFluxRequestProtocol?.CloseConnection(); + CloseConnection(); _magFluxRequestProtocol = null; + _magFluxApi = null; base.Dispose(); } @@ -54,21 +63,6 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol throw new NotImplementedException(); } - /// - /// Wrapper to connect MagFlux - /// - /// - /// - /// - Initial - /// - public Boolean IsConnected() - { - if (_magFluxRequestProtocol == null) return false; - var retVal = _magFluxRequestProtocol.IsConnected(); - _logger.Debug(retVal ? $"{_ident} Connection established: true" : $"{_ident} Connection check request failed!"); - return retVal; - } - /// /// Wrapper to connect MagFlux /// @@ -77,13 +71,23 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol /// /// - Initial /// + /// + /// - MagFluxApi + /// public Boolean Connect(String portName) { - if (_magFluxRequestProtocol == null) return false; - var retVal = _magFluxRequestProtocol.Connect(portName); - _logger.Debug(retVal ? $"{_ident} Connection established to {portName}" : - $"{_ident} Connection to {portName} failed!"); + if (_magFluxApi == null) return false; + _magFluxRequestProtocol = _magFluxApi.Connect(portName); + if (_magFluxRequestProtocol == null) + { + _logger.Debug($"{_ident} Connection to {portName} failed! Object reference returned null"); + return false; + } + Thread.Sleep(100); + var retVal = _magFluxRequestProtocol.IsConnected(); + _logger.Debug(retVal ? $"{_ident} Connection established to {portName}" : + $"{_ident} Connection to {portName} failed!"); return retVal; } @@ -106,7 +110,8 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.SetLogLocation(path, fileName); if (string.IsNullOrEmpty(fileName)) fileName = "?"; - _logger.Debug(retVal ? $"{_ident} Logging set to: {path}\\{fileName}" : $"{_ident} Logging path setup failed!"); + _logger.Debug(retVal ? $"{_ident} Logging set to: {path}\\{fileName}" : + $"{_ident} Logging path setup failed!"); return retVal; } @@ -116,38 +121,177 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol } /// - /// Wrapper to get the PcbId which equals the sensor serial number + /// Wrapper to set experimental boards to defaults regarding board serial number + /// and board calibration values + /// + /// + /// + /// - Initial + /// + public Boolean SetPCBToDemoDefaults() + { + if (_magFluxRequestProtocol == null) return false; + var retVal = _magFluxRequestProtocol.SetPCBToDemoDefaults(); + _logger.Debug(retVal ? $"{_ident} Successfully set PCB settings and PCB calibrations to default" : + $"{_ident} PCB settings and PCB calibrations setup to default failed!"); + return retVal; + } + + ///// + ///// Wrapper to get the simulated flow setting + ///// + ///// + ///// + ///// - Initial + ///// + //public Boolean GetSimulatedFlowOn() + //{ + // if (_magFluxRequestProtocol == null) return false; + // var retVal = _magFluxRequestProtocol.IsSimulatedFlowActive(); + // _logger.Debug(retVal ? $"{_ident} Simulated flow active read back returns: true" : + // $"{_ident} Read back simulated flow status failed!"); + // return retVal; + //} + + ///// + ///// Wrapper to set the simulated flow setting + ///// + ///// true to ignore state + ///// + ///// + ///// - Initial + ///// + //public Boolean SetSimulatedFlowActive(Boolean on) + //{ + // if (_magFluxRequestProtocol == null) return false; + // var retVal = _magFluxRequestProtocol.SetSimulatedFlowActive(on); + // _logger.Debug(retVal ? $"{_ident} Simulated flow active set to: {on}" : + // $"{_ident} Simulated flow active setup failed!"); + // return retVal; + //} + + ///// + ///// Wrapper to get the ignore empty pipe mode status + ///// + ///// + ///// + ///// - Initial + ///// + //public Boolean GetIgnoreEmptyPipeStatus() + //{ + // if (_magFluxRequestProtocol == null) return false; + // var retVal = _magFluxRequestProtocol.IgnoreFailOnEmptyPipeOnHealthy(); + // _logger.Debug(retVal ? $"{_ident} Ignore empty pipe status read back returns: {retVal}" : + // $"{_ident} Read back empty pipe status failed!"); + // return retVal; + //} + + ///// + ///// Wrapper to set the ignore empty pipe mode + ///// + ///// true to ignore state + ///// + ///// + ///// - Initial + ///// + //public Boolean SetIgnoreEmptyPipeStatus(Boolean on) + //{ + // if (_magFluxRequestProtocol == null) return false; + // var retVal = _magFluxRequestProtocol.IgnoreFailOnEmptyPipeOnHealthy(on); + // _logger.Debug(retVal ? $"{_ident} Ignore empty pipe status adjusted to: {on}" : + // $"{_ident} Setup empty pipe status request failed!"); + // return retVal; + //} + + /// + /// Wrapper to get the empty pipe bits + /// + /// + /// + /// + /// - Initial + /// + public Boolean GetEmptyPipeControl(out Int32 epd_cntl_bits) + { + epd_cntl_bits = 0; + if (_magFluxRequestProtocol == null) return false; + var retVal = _magFluxRequestProtocol.GetEmptyPipeControl(out epd_cntl_bits); + _logger.Debug(retVal ? $"{_ident} Empty pipe control bits: 0x{epd_cntl_bits:X1}" : + $"{_ident} Empty pipe control bits request failed!"); + return retVal; + } + + /// + /// Wrapper to get the board calibration value + /// + /// + /// + /// + /// - Initial + /// + public Boolean GetElectrodeBoardCorrectionFactor(out Single value_out) + { + value_out = 0f; + if (_magFluxRequestProtocol == null) return false; + var retVal = _magFluxRequestProtocol.GetElectrodeBoardCorrectionFactor(out value_out); + _logger.Debug(retVal ? $"{_ident} Board calibration: {value_out:F4}" : + $"{_ident} SensorSerialNo request failed!"); + return retVal; + } + + /// + /// Wrapper to get the sensor serial number + /// + /// + /// + /// + /// - Initial + /// + public Boolean GetSensorSerialNo(out String sensorSerialNo) + { + sensorSerialNo = "?"; + if (_magFluxRequestProtocol == null) return false; + var retVal = _magFluxRequestProtocol.GetSensorSerialNo(out sensorSerialNo); + _logger.Debug(retVal ? $"{_ident} SensorSerialNo: {sensorSerialNo}" : + $"{_ident} SensorSerialNo request failed!"); + return retVal; + } + + /// + /// Wrapper to get the PcbId /// /// /// - /// + /// /// - Initial /// public Boolean GetPcbId(out String pcbId) { pcbId = "?"; if (_magFluxRequestProtocol == null) return false; - var retVal = _magFluxRequestProtocol.GetSensorSerialNo(out pcbId); - _logger.Debug(retVal ? $"{_ident} PcbId (SensorSerialNo): {pcbId}" : - $"{_ident} PcbId (SensorSerialNo) request failed!"); + var retVal = _magFluxRequestProtocol.GetBoardSerialNo(out pcbId); + _logger.Debug(retVal ? $"{_ident} PcbId: {pcbId}" : + $"{_ident} PcbId request failed!"); return retVal; } + /// - /// Wrapper to set the PcbId which equals the sensor serial number + /// Wrapper to set the sensor serial number /// - /// + /// /// /// /// - Initial /// - public Boolean SetPcbId(UInt32 pcbId) + public Boolean SetSensorSerialNo(UInt32 sensorSerialNo) { if (_magFluxRequestProtocol == null) return false; - var retVal = _magFluxRequestProtocol.SetSensorSerialNo(pcbId); - _logger.Debug(retVal ? $"{_ident} Set PcbId (SensorSerialNo): {pcbId}" : - $"{_ident} Set PcbId (SensorSerialNo) request failed!"); + var retVal = _magFluxRequestProtocol.SetSensorSerialNo(sensorSerialNo); + _logger.Debug(retVal ? $"{_ident} Set SensorSerialNo: {sensorSerialNo}" : + $"{_ident} Set SensorSerialNo request failed!"); return retVal; } + /// /// Wrapper to get unique id referenced as PCBID /// @@ -161,7 +305,8 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol pcbId = "?"; if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.GetUniqueId(out pcbId); - _logger.Debug(retVal ? $"{_ident} UniqueId: {pcbId}" : $"{_ident} UniqueId request failed!"); + _logger.Debug(retVal ? $"{_ident} UniqueId: {pcbId}" : + $"{_ident} UniqueId request failed!"); return retVal; } @@ -178,9 +323,11 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol fwVersion = "?"; if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.GetFirmwareVersion(out fwVersion); - _logger.Debug(retVal ? $"{_ident} FW Version: {fwVersion}" : $"{_ident} FW Version request failed!"); + _logger.Debug(retVal ? $"{_ident} FW Version: {fwVersion}" : + $"{_ident} FW Version request failed!"); return retVal; } + /// /// Wrapper to get FW Build Date /// @@ -194,7 +341,8 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol fwBuildDate = "?"; if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.GetFwBuildDate(out fwBuildDate); - _logger.Debug(retVal ? $"{_ident} FW Build Date: {fwBuildDate}" : $"{_ident} FW Build Date request failed!"); + _logger.Debug(retVal ? $"{_ident} FW Build Date: {fwBuildDate}" : + $"{_ident} FW Build Date request failed!"); return retVal; } @@ -211,7 +359,26 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol fwGitHash = "?"; if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.GetFwGitHash(out fwGitHash); - _logger.Debug(retVal ? $"{_ident} FW GIT Hash: {fwGitHash}" : $"{_ident} FW GIT Hash request failed!"); + _logger.Debug(retVal ? $"{_ident} FW GIT Hash: {fwGitHash}" : + $"{_ident} FW GIT Hash request failed!"); + return retVal; + } + + /// + /// Wrapper to get API register version of MagFlux + /// + /// + /// + /// + /// - Initial + /// + public Boolean GetApiRegisterVersion(out String apiRegisterVersion) + { + apiRegisterVersion = "?"; + if (_magFluxRequestProtocol == null) return false; + var retVal = _magFluxRequestProtocol.GetAPIRegisterVersion(out apiRegisterVersion); + _logger.Debug(retVal ? $"{_ident} MagFlux API Register Version: {apiRegisterVersion}" : + $"{_ident} MagFlux API Register Version request failed!"); return retVal; } @@ -233,7 +400,8 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol meterSize = 0; if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.GetDn_mm(out meterSize); - _logger.Debug(retVal ? $"{_ident} MeterSize DN: {meterSize}" : $"{_ident} MeterSize request failed!"); + _logger.Debug(retVal ? $"{_ident} MeterSize DN: {meterSize}" : + $"{_ident} MeterSize request failed!"); return retVal; } @@ -249,7 +417,8 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol { if (_magFluxRequestProtocol == null) return false; var retVal = _magFluxRequestProtocol.SetDn_mm(meterSize); - _logger.Debug(retVal ? $"{_ident} Set MeterSize DN: {meterSize}" : $"{_ident} Set MeterSize failed!"); + _logger.Debug(retVal ? $"{_ident} Set MeterSize DN: {meterSize}" : + $"{_ident} Set MeterSize failed!"); return retVal; } @@ -386,11 +555,18 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol /// /// - Initial /// + /// + /// - Corrected logic, if !IsConnected = connection is closed + /// public Boolean CloseConnection() { if (_magFluxRequestProtocol == null) return false; - var retVal = _magFluxRequestProtocol.CloseConnection(); - _logger.Debug(retVal ? $"{_ident} Connection closed" : $"{_ident} Close connection request failed!"); + MagFluxAPI.CloseAllConnections(); + + Thread.Sleep(100); + var retVal = _magFluxRequestProtocol.IsConnected(); + _logger.Debug(!retVal ? $"{_ident} Connection is closed" : + $"{_ident} Close connection request failed!"); return retVal; } } diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.csproj b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.csproj index 6255094c..53469aa6 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.csproj +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.csproj @@ -31,9 +31,15 @@ 4 + + ..\..\MagFluxApi\magflux_api.dll + ..\..\..\..\..\packages\NLog.5.2.2\lib\net46\NLog.dll + + ..\..\MagFluxApi\shared_code.dll + @@ -53,10 +59,6 @@ - - {F14940F8-3C86-4BB7-A915-B021E4B3052D} - modbus_master_csharp - {4B88B0D3-E791-4774-9521-EABEACDC420E} Logging diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/Properties/AssemblyInfo.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/Properties/AssemblyInfo.cs index 41621a5d..066a6f1c 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/Properties/AssemblyInfo.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Xylem")] [assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Copyright © Xylem 2023")] +[assembly: AssemblyCopyright("Copyright © Xylem 2023..2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,4 +33,3 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingDecoder.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingDecoder.cs index 23e054a8..05a8b9c3 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingDecoder.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingDecoder.cs @@ -50,7 +50,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol private MagFluxRecord _dataMagFluxRec; private readonly Boolean _ignoreCorruptedData; - private String _pcbIdMask; + private String _sensorIdMask; private String _uniqueIdMask; /// @@ -72,19 +72,21 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol /// /// Set decoding mask for streaming protocol, wipes out all not matching records: - /// - PcbIdMask equals the sensor serial no + /// - SensorIdMask, /// - UniqueIdMask /// - /// + /// /// /// true if decoding was successful and data has been validated /// /// - Initial. /// - public void SetDecodingMask(String pcbIdMask, String uniqueIdMask) + /// + /// - Changed from PcbId to SensorId. + /// + public void SetDecodingMask(String sensorIdMask, String uniqueIdMask) { - // the pcbId equals the sensorSn - _pcbIdMask = pcbIdMask; + _sensorIdMask = sensorIdMask; _uniqueIdMask = uniqueIdMask; } /// @@ -98,6 +100,9 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol /// /// - Introduced reverse volume. /// + /// + /// - Changed from PcbId to SensorId. + /// public Boolean DecodeMsg(String rawMsg) { var rawRecordIsValid = false; @@ -146,11 +151,14 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol switch (rawMsgFields[0]) { case "@l": + //protocol @m starts with all contents of protocol @l and contains additional fields + //which needn't to be decoded as those are used for DEBUG + case "@m": if (rawRecordIsValid || !_ignoreCorruptedData) { DecodeProtocolL(ref _dataMagFluxRec, rawMsgFields); if (string.Equals(_uniqueIdMask, _dataMagFluxRec.UniqueId) && - string.Equals(_pcbIdMask, _dataMagFluxRec.SensorId)) + string.Equals(_sensorIdMask, _dataMagFluxRec.SensorId)) { DataMagFlux = _dataMagFluxRec; _dataMagFluxRec.IsValid = rawRecordIsValid; diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingProtocol.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingProtocol.cs index cb15fbae..97bd1ef7 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingProtocol.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/StreamingProtocol/StreamingProtocol.cs @@ -19,7 +19,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol /// private StreamingDecoder _streamingDecode; private readonly Boolean _ignoreCorruptedData; - private String _pcbIdMask; + private String _sensorIdMask; private String _uniqueIdMask; /// @@ -30,16 +30,18 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol /// - PcbIdMask equals the sensor serial no /// - UniqueIdMask /// - /// + /// /// /// true if decoding was successful and data has been validated /// /// - Initial. /// - public void SetDecodingMask(String pcbIdMask, String uniqueIdMask) + /// + /// - Changed from PcbId to SensorId. + /// + public void SetDecodingMask(String sensorIdMask, String uniqueIdMask) { - // the pcbId equals the sensorSn - _pcbIdMask = pcbIdMask; + _sensorIdMask = sensorIdMask; _uniqueIdMask = uniqueIdMask; } /// @@ -49,7 +51,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol //Data decoding _streamingDecode = new StreamingDecoder(_ignoreCorruptedData); - _streamingDecode.SetDecodingMask(_pcbIdMask, _uniqueIdMask); + _streamingDecode.SetDecodingMask(_sensorIdMask, _uniqueIdMask); _streamingDecode.DecodeMsg(data); //Event for new data diff --git a/Common/Hardware/WaterMeter/OmniPlus/Common.Hardware.WaterMeter.OmniPlus.Features/SystemParameters.cs b/Common/Hardware/WaterMeter/OmniPlus/Common.Hardware.WaterMeter.OmniPlus.Features/SystemParameters.cs index 06b7968c..d2d67b28 100644 --- a/Common/Hardware/WaterMeter/OmniPlus/Common.Hardware.WaterMeter.OmniPlus.Features/SystemParameters.cs +++ b/Common/Hardware/WaterMeter/OmniPlus/Common.Hardware.WaterMeter.OmniPlus.Features/SystemParameters.cs @@ -62,11 +62,29 @@ { this.IsValid = true; - var firmwareTokens = this.VersionAndType - ?.Value + var versionAndType = this.VersionAndType?.Value; + var firmwareTokens = versionAndType ?.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[2]; + this.IsValid = firmwareTokens.Length == 3; + + if (!this.IsValid) + { + this.ValidationMessage = $"Fehlender FW-Versionsparameter! - {versionAndType}"; + + return; + } + + this.IsValid = firmwareTokens[2].CompareTo("R0.3.19") >= 0; + + if (!this.IsValid) + { + this.ValidationMessage = $"FW-Version {firmwareTokens[2]} ist zu alt!"; + + return; + } + var versionString = string.Empty; if (firmwareTokens?.Length > 0 && firmwareTokens[0]?.Length > 0) @@ -78,7 +96,7 @@ if (!this.IsValid) { - this.ValidationMessage = $"{this.VersionAndType.Value} ist kleiner als 1.23"; + this.ValidationMessage = $"{firmwareTokens[0]} ist kleiner als R1.23"; return; } @@ -105,17 +123,19 @@ if (!this.IsValid) { - if (3190 > volts) + var _volts = volts / 1000.0; + + if (3.19 > _volts) { - this.ValidationMessage = $"Zu wenig baterie spannung: {volts / 1000.0}."; + this.ValidationMessage = $"Zu wenig baterie spannung: {_volts}."; } - else if (3750 < volts) + else if (3.75 < _volts) { - this.ValidationMessage = $"Zu fiel baterie spannung: {volts / 1000.0}."; + this.ValidationMessage = $"Zu fiel baterie spannung: {_volts}."; } else { - this.ValidationMessage = $"Die byterie spannung ist nicht in ordnung: {volts / 1000.0}."; + this.ValidationMessage = $"Die byterie spannung ist nicht in ordnung: {_volts}."; } return; diff --git a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache index d110f5fc..8865d283 100644 --- a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache +++ b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -c43c40a030005a8f189e6179faf40a6d42bfef5c +89102b0142e574de38a9f47d370f3334e5e6c268 diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/DebugCmd.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/DebugCmd.cs index 9d8d6272..760d8d0e 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/DebugCmd.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/DebugCmd.cs @@ -2,22 +2,13 @@ { using System; - public class DebugCmd + public class DebugCmd : Pam { - protected readonly Byte[] bytes; - - protected DebugCmd(Byte code) - { - this.bytes = new Byte[2]; - this.bytes[1] = code; - } - - private DebugCmd(Byte[] bytes) => this.bytes = bytes; + protected DebugCmd(Byte code) : base(3, GetDebug) + => this.bytes[2] = code; public static implicit operator Byte[] (DebugCmd cmd) => cmd.bytes; - public static implicit operator DebugCmd(Byte[] bytes) => new DebugCmd(bytes); - /// /// Change from Production Mode to Shipment Mode. 1 = Shipment /// diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/OpticalTelegram.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/OpticalTelegram.cs index b540b091..4e4138b6 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/OpticalTelegram.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/OpticalTelegram.cs @@ -10,8 +10,8 @@ public Byte Minutes { - get => this.bytes[0]; - set => this.bytes[0] = value; + get => this.bytes[1]; + set => this.bytes[1] = value; } } } diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetAlarms.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetAlarms.cs index ca68323b..b850458d 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetAlarms.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetAlarms.cs @@ -5,7 +5,5 @@ public SetAlarms() : base(2, DebugCmd.SetAlarms) { } - - public static implicit operator DebugCmd(SetAlarms alarms) => alarms.bytes; } } diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetMetrologyParameters.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetMetrologyParameters.cs index 36826b32..3c108db6 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetMetrologyParameters.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister.Features/SetMetrologyParameters.cs @@ -6,12 +6,12 @@ public class SetMetrologyParameters : Pam { - private readonly Byte[] bitsFromByte11; + private Byte[] bitsFromByte11; public SetMetrologyParameters() : base(18, MetrologyParameters) => this.bitsFromByte11 = new Byte[8]; - public Byte PamLength => (Byte)(this.bytes.Length - 1); + public Byte PamLength => this.bytes[1]; public Int32 Vpp { @@ -31,42 +31,54 @@ set => this.bytes[10] = value; } - public Single FactoryCalibration + public Byte FactoryCalibration { - get => this.bytes[11] / 10F; - set => this.bytes[11] = (Byte)(value * 10); + get => this.bytes[11]; + set => this.bytes[11] = value; } - + + public Byte P11 + { + get => this.bitsFromByte11.ToByte(); + set => this.bitsFromByte11 = value.GetBits(); + } + public MeterUnits Units { get { var bits = new Byte[8]; - bits[0] = this.bitsFromByte11[4]; - bits[1] = this.bitsFromByte11[3]; - bits[2] = this.bitsFromByte11[2]; - bits[3] = this.bitsFromByte11[1]; bits[4] = this.bitsFromByte11[0]; + bits[3] = this.bitsFromByte11[1]; + bits[2] = this.bitsFromByte11[2]; + bits[1] = this.bitsFromByte11[3]; + bits[0] = this.bitsFromByte11[4]; - return (MeterUnits)bits.ToByte(0, 5); + return (MeterUnits)bits.ToByte(); } set { var bits = ((Byte)value).GetBits(); - this.bitsFromByte11[4] = bits[0]; - this.bitsFromByte11[3] = bits[1]; - this.bitsFromByte11[2] = bits[2]; - this.bitsFromByte11[1] = bits[3]; this.bitsFromByte11[0] = bits[4]; + this.bitsFromByte11[1] = bits[3]; + this.bitsFromByte11[2] = bits[2]; + this.bitsFromByte11[3] = bits[1]; + this.bitsFromByte11[4] = bits[0]; } } public DecimalPointLocations DecimalPoint { get => (DecimalPointLocations)this.bitsFromByte11[6]; - set => this.bitsFromByte11[6] = (Byte)value; + set + { + var x = (Byte)value; + + this.bitsFromByte11[6] = (Byte)(x >> 5 & 1); + this.bitsFromByte11[5] = (Byte)(x >> 6 & 1); + } } /// @@ -88,20 +100,16 @@ set => this.bytes[13] = value; } - public UInt32 VppLED + public Int32 VppLED { - get => this.bytes.ToUInt32BigEndian(14); + get => this.bytes.ToInt32BigEndian(14); set => value.ToBigEndianBytes().CopyTo(this.bytes, 14); } protected override Byte[] ToByteArray() { - var bytes11 = new Byte[8]; - - Array.Copy(this.bitsFromByte11, 0, bytes11, 0, 8); - Array.Reverse(bytes11); - - this.bytes[12] = bytes11.ToByte(); + this.bytes[12] = this.bitsFromByte11.ToByte(); + this.bytes[1] = 0x10; return base.ToByteArray(); } diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Common.Hardware.WaterMeter.eRegister.csproj b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Common.Hardware.WaterMeter.eRegister.csproj index 814ebfee..56b20a09 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Common.Hardware.WaterMeter.eRegister.csproj +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Common.Hardware.WaterMeter.eRegister.csproj @@ -50,31 +50,37 @@ + - - - - - + + + + + - - - - - - + + + + + + + - + {05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3} Common.Utils.Extensions - + + {F408DE9E-01E6-4CFF-AE79-B572B0674FA2} + Common.Hardware.Interfaces.Ports.SirtBroadcaster + + {B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD} - Common.Hardware.Interfaces.Ports.SIRT + Common.Hardware.Interfaces.Ports.Sirt {9AE071C0-DB12-4E09-A3C7-43F6DCD518D6} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ACKN.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/ACKN.cs similarity index 90% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ACKN.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/ACKN.cs index 31c7ade4..65ebc112 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ACKN.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/ACKN.cs @@ -1,6 +1,6 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { - using Common.Hardware.Interfaces.Ports.SIRT.Responses; + using Common.Hardware.Interfaces.Ports.Sirt.Responses; using System; diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/AppCode.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/AppCode.cs similarity index 79% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/AppCode.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/AppCode.cs index 70408be7..59afbf64 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/AppCode.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/AppCode.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { public enum AppCode { diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/BUP.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/BUP.cs similarity index 91% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/BUP.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/BUP.cs index 9dd2f454..b0efd4a6 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/BUP.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/BUP.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { using Common.Hardware.WaterMeter.eRegister.Features; using Common.Utils.Extensions; diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Debug.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/DEBUG.cs similarity index 74% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Debug.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/DEBUG.cs index 7efa45d6..4713762a 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Debug.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/DEBUG.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { using Common.Utils.Extensions; @@ -12,14 +12,13 @@ this.DebugType = payload[index++]; this.MeterType = payload[index++]; - this.RadioFirmwareVersion = payload[index++].ToString(); - this.FirmwareVersion = payload[index++].ToString(); + this.RadioFirmwareVersion = this.VersionString(payload[index++], payload[index++]); this.MetrologyFirmwareVersion = this.VersionString(payload[index++], payload[index++]); this.HardwareVersion = payload[index++].ToString(); this.FactoryState = payload[index++]; this.PCBID = payload.ToUInt32BigEndian((index += 4) - 4); this.BoardTemperature = payload[index++]; - this.BatteryVoltage = payload.ToUInt16BigEndian((index += 2) - 2); + this.BatteryVoltage = 2 + payload.ToUInt16BigEndian((index += 2) - 2) / 64D; this.WakeupInterval = payload[index++]; this.PowerLevelSensusRF = payload[index++]; this.PowerLevelFlexNet = payload[index++]; @@ -69,7 +68,10 @@ public Byte BoardTemperature { get; } - public UInt16 BatteryVoltage { get; } + /// + /// Min: 3.565 + /// + public Double BatteryVoltage { get; } public Byte WakeupInterval { get; } @@ -111,19 +113,37 @@ /// Bits 8-11 – Minor Version /// Bits 0-7 – Patch Version /// - private String VersionString(Byte param, Byte patch) + private String VersionString(Byte patch, Byte param) { - var bits = param.GetBits(); - var _major = new Byte[8]; - var _minor = new Byte[8]; + var bits = param.GetBits().Reverse(); + var type = bits[7] == 0 ? 'B' : 'R'; - Array.Copy(bits, 0, _major, 0, 4); - Array.Copy(bits, 4, _minor, 0, 3); - - var major = _major.ToByte(); - var minor = _minor.ToByte(); + var majorBits = new Byte[8]; + majorBits[0] = bits[6]; + majorBits[1] = bits[5]; + majorBits[2] = bits[4]; - return $"{bits[7]}.{major}.{minor}.{patch}"; + var major = 0; + + for (var i = 0; i < 8; i++) + { + major |= majorBits[i] << i; + } + + var minorBits = new Byte[8]; + majorBits[0] = bits[3]; + majorBits[1] = bits[2]; + majorBits[2] = bits[1]; + majorBits[3] = bits[0]; + + var minor = 0; + + for (var i = 0; i < 8; i++) + { + minor |= minorBits[i] << i; + } + + return $"{type}{major}.{minor}.{patch}"; } } } diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Epoch20000101.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Epoch20000101.cs similarity index 95% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Epoch20000101.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Epoch20000101.cs index 0779bd95..323dc8fa 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Epoch20000101.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Epoch20000101.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { using System; diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Lat.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/LAT.cs similarity index 70% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Lat.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/LAT.cs index 99212f42..f145565e 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Lat.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/LAT.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { using System; diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/MeterUnits.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/MeterUnits.cs similarity index 61% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/MeterUnits.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/MeterUnits.cs index b03594f8..c21fc1a7 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/MeterUnits.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/MeterUnits.cs @@ -1,7 +1,8 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { public enum MeterUnits { + NA = 0, m3 = 19, CF = 35, GAL = 24, diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Payload.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Payload.cs similarity index 87% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Payload.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Payload.cs index 85d5232d..ea01852e 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Payload.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/Payload.cs @@ -1,4 +1,4 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { using Common.Utils.Extensions; @@ -6,7 +6,7 @@ public abstract class Payload { - private readonly String bytes; + protected readonly String bytes; protected Payload(Byte[] payload) { diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/SEMI.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/SEMI.cs similarity index 94% rename from Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/SEMI.cs rename to Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/SEMI.cs index 3f1ea888..367cd60f 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/SEMI.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Data/SEMI.cs @@ -1,5 +1,6 @@ -namespace Common.Hardware.WaterMeter.eRegister +namespace Common.Hardware.WaterMeter.eRegister.Data { + using Common.Hardware.Interfaces.Ports.SirtBroadcaster; using Common.Utils.Extensions; using System; @@ -12,7 +13,7 @@ var index = 11; this.PAMStatus = new PAMStatus(payload[index++]); - this.RSSI = this.CalculateRSSI(payload[index++], mhz); + this.RSSI = CalculateRSSI(payload[index++], mhz); this.MeterType = payload[index++]; this.TransmissionInterval = payload.ToUInt16BigEndian((index += 2) - 2); this.LATInterval = payload[index++]; @@ -26,7 +27,7 @@ this.AlarmActiveInformation = payload[index++]; this.LeakageDetectionParameters = payload[index++]; this.BrokenPipeDetectionParameters = payload[index++]; - this.BatteryRemaining = payload.ToUInt16BigEndian((index += 2) - 2); + this.BatteryRemaining = payload.ToUInt16BigEndian((index += 2) - 2) / (4D * 365); this.BatteryEndDetected = payload.ToUInt16BigEndian((index += 2) - 2); this.MaximumFlow = payload.ToUInt16BigEndian((index += 2) - 2); this.TimeOfMaximumFlow = payload.ToUInt16BigEndian((index += 2) - 2); @@ -98,7 +99,7 @@ public Byte BrokenPipeDetectionParameters { get; } - public UInt16 BatteryRemaining { get; } + public Double BatteryRemaining { get; } public UInt16 BatteryEndDetected { get; } @@ -148,7 +149,7 @@ public Byte MeterSize { get; } - private String CalculateRSSI(Byte value, UInt16 mhz) + public static String CalculateRSSI(Byte value, UInt16 mhz) { var dbm = 0D; var per = 0D; @@ -177,7 +178,7 @@ per = 0; } - return $"{dbm:0.00}dBm ({per:0.00}%)"; + return $"{dbm:0}dBm ({per:0.0}%)"; } } } diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Endpoint.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Endpoint.cs deleted file mode 100644 index 0a9d44cb..00000000 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/Endpoint.cs +++ /dev/null @@ -1,289 +0,0 @@ -namespace Common.Hardware.WaterMeter.eRegister -{ - using Common.Hardware.Interfaces.Ports.SIRT; - using Common.Hardware.WaterMeter.eRegister.Features; - - using NLog; - - using System; - using System.Collections.Generic; - using System.Linq; - - public class Endpoint - { - private readonly ILogger logger; - private readonly Queue commands; - - private Int32 remeiningTasks; - private EndpointTask checksTask; - - public Endpoint(ILogger logger) - { - this.logger = logger; - this.commands = new Queue(); - } - - public event Action Done; - - public Int32 Slot { get; internal set; } - - public UInt32 Address { get; set; } - - public UInt32 FinalAddress { get; set; } - - public Int32 SerialNo { get; set; } - - public String HexKey { get; set; } - - public DEBUG DEBUG { get; private set; } - - public SEMI SEMI { get; private set; } - - public LAT LAT { get; private set; } - - public void AddHexCommand(String command) - { - if (String.IsNullOrWhiteSpace(command)) - { - return; - } - - command = command - .Replace("0x", "") - .Replace("h", "") - .Replace(";", "") - .Replace(",", "") - .Replace("-", "") - .Replace(" ", "") - .Trim(); - - if (command.Length % 2 != 0) - { - return; - } - - Boolean TryParse(Char _char, out Int32 _byte) - { - _byte = 0; - - if ('0' <= _char && _char <= '9') - { - _byte = _char - '0'; - } - else if ('A' <= _char && _char <= 'F') - { - _byte = 16 - ('F' - _char) - 1; - } - else - { - return false; - } - - return true; - } - - var length = command.Length; - var bytes = new Byte[length / 2]; - - for (Int32 c = 0, b = 0; c < length; c += 2, b++) - { - if (TryParse(command[c], out var b1) && TryParse(command[c + 1], out var b2)) - { - bytes[b] = (Byte)(b1 * 16 + b2); - } - else - { - this.logger.Error($"Invalid hex char: {command}"); - - bytes = null; - - break; - } - } - - if (bytes != null) - { - this.commands.Enqueue(bytes); - } - } - - public EndpointTask InitForInspection() - { - this.remeiningTasks++; - - var task = new EndpointTask - { - Address = this.Address, - WakeUpCmd = true, - DelPamSemi = true, - Payload = new ChangeWakeUp - { - Mode = WakeUpMode.StayAwake - } - .Append(new ChangeLATWindows - { - N = 0 - }) - .Append(new WMBusMode - { - WMBusEnabled = true, - InstallationModeEnabled = true, - EncryptionEnabled = true, - }) - .Append(new ChangeTransmission - { - LatWindowIntervalCount = 0, - LatTXIntervalSeconds = 3 - }) - .Append(new ProvidePin - { - AuthLevel = AuthLevel.II - }) - }; - task.Done += this.Task_Done; - task.TRXLogging += this.Task_TRXLogging; - - return task; - } - - internal EndpointTask RunCommand() - { - if (this.commands.Count > 0) - { - this.remeiningTasks++; - - var task = new EndpointTask - { - Address = this.Address, - WakeUpCmd = true, - DelPamSemi = true, - Payload = this.commands.Dequeue() - }; - task.Done += this.Task_Done; - task.TRXLogging += this.Task_TRXLogging; - - return task; - } - - return null; - } - - public EndpointTask SetupForInspection() - { - this.remeiningTasks++; - - var task = new EndpointTask - { - Address = this.Address, - WakeUpCmd = true, - DelPamSemi = true, - Payload = new SetMetrologyParameters - { - DecimalPoint = DecimalPointLocations.Three, - FactoryCalibration = 0, - MeterSize = 37, - OffsetFactor = 0, - OffsetTime = 5, - Units = Features.MeterUnits.CubicMeters, - UseCandIRules = true, - Vpp = 40960000, - VppLED = 218843648 - } - .Append(new ProvidePin - { - AuthLevel = AuthLevel.III - }) - }; - task.Done += this.Task_Done; - task.TRXLogging += this.Task_TRXLogging; - - return task; - } - - public EndpointTask SetDisplay111111111() - { - this.remeiningTasks++; - - var task = new EndpointTask - { - Address = this.Address, - WakeUpCmd = true, - DelPamSemi = true, - Payload = new ChangeMeterReading - { - Value = 111_111_111 - } - .Append(new ProvidePin - { - AuthLevel = AuthLevel.III - }) - }; - task.Done += this.Task_Done; - task.TRXLogging += this.Task_TRXLogging; - - return task; - } - - public EndpointTask StartLED() - { - this.remeiningTasks++; - - var task = new EndpointTask - { - Address = this.Address, - WakeUpCmd = true, - DelPamSemi = true, - Payload = new GetDebug - { - Cmd = new OpticalTelegram - { - Minutes = 1, - } - } - .Append(new ProvidePin - { - AuthLevel = AuthLevel.III - }) - }; - task.Done += this.Task_Done; - task.TRXLogging += this.Task_TRXLogging; - - return task; - } - - public EndpointTask DoChecks() - { - this.checksTask = new EndpointTask(); - - return this.checksTask; - } - - private void Task_TRXLogging(Byte[] bytes) => this.logger?.Debug($"{this.Slot}|{BitConverter.ToString(bytes)}"); - - private void Task_Done(SIRTTask task) - { - this.remeiningTasks--; - - if (this.remeiningTasks <= 0) - { - if (this.checksTask != null && task is EndpointTask endpointTask) - { - this.LAT = endpointTask.LATS.LastOrDefault(); - this.DEBUG = endpointTask.DEBUGS.LastOrDefault(); - this.SEMI = endpointTask.SEMIS.LastOrDefault(); - - var batteryVoltage = 2 + (this.DEBUG?.BatteryVoltage ?? 1) / 64F >= 3.565; - var batteryRemaining = 2 + (this.SEMI?.BatteryRemaining ?? 54669) <= 54668; - var rebootCount = (this.DEBUG?.RebootCount ?? Byte.MaxValue) <= 2; - - if (batteryVoltage && batteryRemaining && rebootCount) - { - this.checksTask.NotifyCompleted(); - } - } - - this.Done?.Invoke(0); - } - } - } -} \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/EndpointTask.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/EndpointTask.cs deleted file mode 100644 index 169370f5..00000000 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/EndpointTask.cs +++ /dev/null @@ -1,127 +0,0 @@ -namespace Common.Hardware.WaterMeter.eRegister -{ - using Common.Hardware.Interfaces.Ports.SIRT; - using Common.Hardware.Interfaces.Ports.SIRT.Responses; - using Common.Utils.Extensions; - - using System; - using System.Collections.Generic; - using System.Linq; - - public class EndpointTask : WritePamTask - { - private Byte[] key; - - public EndpointTask() : base(5) - { - this.Done += _ => this.NotifyCompleted(); - base.Cancelled += _ => this.NotifyCancelled(); - } - - public event Action Completed; - public new event Action Cancelled; - public event Action Received; - - public override UInt32 Address => base.Address; - - public String KEY - { - get => BitConverter.ToString(this.key); - set => this.key = value.GetBytes(); - } - - public ICollection ACKNS { get; private set; } = new List(); - - public ICollection LATS { get; private set; } = new List(); - - public ICollection DEBUGS { get; private set; } = new List(); - - public ICollection SEMIS { get; } = new List(); - - public ICollection BUPS { get; } = new List(); - - public String FirstPamId => $"PAM {this.request.Payload.FirstOrDefault()}"; - - protected override Boolean FromAirReceived(FromAirResponse response) - { - var payload = response.Payload; - var length = response.Payload.Length; - var succeeded = false; - - if (length == 13) - { - var bup = new LAT(payload); - - if (bup.AppCode == AppCode.LAT) - { - this.LATS.Add(bup); - - if (this.request.Payload[0] == 0x35) - { - var oldAddress = this.Address; - var newAddress = this.request.Payload.ToUInt32BigEndian(1); - - if (oldAddress != newAddress) - { - this.NotifyAddressChanged(oldAddress, newAddress); - } - } - - this.Received?.Invoke($"LAT({this.LATS.Count})"); - } - else - { - this.BUPS.Add(bup); - - this.Received?.Invoke($"BUP({this.BUPS.Count})"); - } - } - else if (length == 52) - { - this.DEBUGS.Add(new DEBUG(payload)); - - this.Received?.Invoke($"DEBUG({this.DEBUGS.Count})"); - } - else if (length == 91) - { - this.SEMIS.Add(new SEMI(payload, response.MHz)); - - this.Received?.Invoke($"SEMI({this.SEMIS.Count})"); - - succeeded = true; - } - else - { - // TODO: unrecognized response received.!? - } - - this.NotifyTRX(response); - - /// If SEMI received, task is done - return succeeded; - } - - protected override Boolean AcknOrAnswerReceived(AcknOrAnswerResponse response) - { - this.ACKNS.Add(new ACKN(response)); - - this.Received?.Invoke($"LAT({this.ACKNS.Count})"); - this.NotifyTRX(response); - - return base.AcknOrAnswerReceived(response); - } - - protected override Byte[] GetRequestBytes() - { - var bytes = base.GetRequestBytes(); - - this.NotifyTRX(bytes); - - return bytes; - } - - internal void NotifyCompleted() => this.Completed?.Invoke(); - - internal new void NotifyCancelled() => this.Cancelled?.Invoke(); - } -} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/JustTask.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/JustTask.cs new file mode 100644 index 00000000..acf8a493 --- /dev/null +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/JustTask.cs @@ -0,0 +1,33 @@ +namespace Common.Hardware.WaterMeter.eRegister +{ + using System; + using System.Linq; + + public class JustTask + { + public event Action OnProgress; + + public Int32 Slotno { get; internal set; } + + public Int32 Rowno { get; internal set; } + + public String Label { get; protected set; } + + public TaskState State { get; protected set; } = TaskState.None; + + public Func> TaskHandler { get; internal set; } + + public Action ProgressHandler + { + get => (Action)this.OnProgress?.GetInvocationList()?.FirstOrDefault(); + set => this.OnProgress += value; + } + + public void Execute(ParameterSet parameterSet) + { + var result = this.TaskHandler?.Invoke(parameterSet); + + this.OnProgress?.Invoke(this.Slotno, this.Rowno, result.Item1, result.Item2); + } + } +} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/PAMStatus.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/PAMStatus.cs deleted file mode 100644 index 63cd01fe..00000000 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/PAMStatus.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Common.Hardware.WaterMeter.eRegister -{ - using Common.Utils.Extensions; - - using System; - - public class PAMStatus - { - private readonly Byte[] bits; - - public PAMStatus(Byte _byte) - => this.bits = _byte.GetBits(); - - public Boolean CMD_UNKNOWN => this.bits[0] == 1; - - public Boolean WRONG_AUTH => this.bits[1] == 1; - - public Boolean EXPIRED_AUTH => this.bits[2] == 1; - - public Boolean MIXED_TYPES => this.bits[3] == 1; - - public Boolean OUT_OF_RANGE => this.bits[4] == 1; - } -} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ParameterSet.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ParameterSet.cs new file mode 100644 index 00000000..bdaa0ca6 --- /dev/null +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ParameterSet.cs @@ -0,0 +1,113 @@ +namespace Common.Hardware.WaterMeter.eRegister +{ + using Common.Hardware.Interfaces.Ports.Sirt; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; + using Common.Hardware.WaterMeter.eRegister.Features; + using Common.Utils.Extensions; + + using System; + + public class ParameterSet + { + public Int32 SharedId { get; set; } + + public Int32 Psno { get; set; } + + public Int32 Slotno { get; set; } + + public Int32 Serialno { get; set; } + + public Boolean IsSealed { get; set; } + + public Byte[] RadioKey { get; set; } + + public UInt32 RadioAddress { get; set; } + + public UInt32 FinalAddress { get; set; } + + public Byte[] Parameters { get; set; } + + internal ProgrammingTask BuildWupTxLatMBusTask() + => new ProgrammingTask + { + Cmd = JustSirtMessage.W_PAM, + P1 = new P811 + { + DelPamSemi = true, + WakeUpCmd = true + }, + Address = this.RadioAddress, + Data = new Byte[] // Multipam commands + { + 0x00, 0x00, // WUP stay awake + 0x02, 0x00, // LAT window interval + 0x05, 0x07, // MBus status + 0x10, 0x00, 0x03, // TX interval + 0x43, 0x02, 0x14, 0x0E, 0x80, 0x40, // Pin level II + }, + EncryptionKey = this.IsSealed ? this.RadioKey : null + }; + + internal ProgrammingTask BuildTestParametersTask() + => new ProgrammingTask + { + Cmd = JustSirtMessage.W_PAM, + P1 = new P811 + { + DelPamSemi = true + }, + Address = this.RadioAddress, + Data = new SetMetrologyParameters + { + Vpp = this.Parameters.Int32BigEndian(3), + OffsetFactor = this.Parameters.Int32BigEndian(7), + OffsetTime = this.Parameters.Byte(11), + FactoryCalibration = this.Parameters.Byte(12), + P11 = this.Parameters.Byte(13), + MeterSize = this.Parameters.Byte(14), + VppLED = this.Parameters.Int32BigEndian(15), + } + .Append(new ProvidePin + { + AuthLevel = Features.AuthLevel.III + }), + EncryptionKey = this.IsSealed ? this.RadioKey : null + }; + + internal ProgrammingTask BuildSetupDisplayTask() + => new ProgrammingTask + { + Cmd = JustSirtMessage.W_PAM, + P1 = new P811 + { + DelPamSemi = true + }, + Address = this.RadioAddress, + Data = new Byte[] + { + 0x30, 0x06, 0x9F, 0x6B, 0xC7, // Display: 111111111 + 0x43, 0x03, 0x63, 0x93, 0x73, 0x22 // Pin level III + }, + EncryptionKey = this.IsSealed ? this.RadioKey : null + }; + + internal ProgrammingTask BuildOptoOnTask() + => new ProgrammingTask + { + Cmd = JustSirtMessage.W_PAM, + P1 = new P811 + { + DelPamSemi = true + }, + Address = this.RadioAddress, + Data = new OpticalTelegram + { + Minutes = 1 // TODO: Get opto value + }.Append(new ProvidePin + { + AuthLevel = Features.AuthLevel.III + }), + EncryptionKey = this.IsSealed ? this.RadioKey : null + }; + } +} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingBatch.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingBatch.cs index 4189e653..b211e86c 100644 --- a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingBatch.cs +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingBatch.cs @@ -1,7 +1,6 @@ namespace Common.Hardware.WaterMeter.eRegister { - using Common.Hardware.Interfaces.Ports; - using Common.Hardware.Interfaces.Ports.SIRT; + using Common.Hardware.Interfaces.Ports.SirtBroadcaster; using NLog; using NLog.Config; @@ -9,126 +8,436 @@ using System; using System.Collections.Generic; - using System.Linq; using System.Threading; public class ProgrammingBatch { - private readonly ILogger logger; - private readonly SIRTBroadcaster broadcaster; - private readonly IDictionary endpoints; + private readonly Dictionary programmingParameters + = new Dictionary(); + private readonly Dictionary> programmingTasks + = new Dictionary>(); + private readonly Dictionary> eregisterTasks + = new Dictionary>(); + private readonly Dictionary> completedTasks + = new Dictionary>(); + private readonly ILogger logger = CreateNLogger("SIRT"); + private JustSirtBroadcaster broadcaster; + private Int32 rssiRow; - private Int32 tasksDone; + public event Action OnProgress; - public ProgrammingBatch(String portName, Int32 rwTimeout = 3000) + public void AddOrReplace(ParameterSet parameterSet) + => this.programmingParameters[parameterSet.Slotno] = parameterSet; + + public void InitializeCalibration() { - this.logger = CreateNLogger("SIRT"); - this.endpoints = new Dictionary(); - this.broadcaster = new SIRTBroadcaster(new SerialPortSettings + this.programmingTasks.Clear(); + this.eregisterTasks.Clear(); + + this.OnProgress?.Invoke(0, 0, $"Einbauplatz", TaskState.Disabled); + + for (var x = 1; x < 11; x++) { - BaudRate = SerialPortBaudRate.X115200, - DataBits = SerialPortDataBits.X8, - Parity = SerialPortParity.None, - PortName = portName, - StopBits = SerialPortStopBits.One, - RWTimeout = rwTimeout + this.OnProgress?.Invoke(x, 0, $"{x}", TaskState.Disabled); + } + + var rowno = 1; + + this.OnProgress?.Invoke(0, rowno++, $"Seriennr", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Radio Adresse", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Finale Adresse", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"RSSI", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"WUP-TX-LAT-MBus", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Parametersatz", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Anzeige-111111111", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Opto ein", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"MBus status = 7", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Batteriespannung (Volts)", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Batterielaufzeit (Jahre)", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"FW Version", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Reboots <= 2", TaskState.Disabled); + + foreach (var kvp in this.programmingParameters) + { + var slotno = kvp.Key; + var parameterSet = kvp.Value; + + rowno = 1; + + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.Serialno}", TaskState.Disabled); + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.RadioAddress}", TaskState.Disabled); + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.FinalAddress}", TaskState.Disabled); + this.OnProgress?.Invoke(slotno, rowno++, $"0dBm (0%)", TaskState.Disabled); + this.rssiRow = rowno - 1; + + if (!this.programmingTasks.ContainsKey(slotno)) + { + this.programmingTasks[slotno] = new Queue(); + } + + var tasks = this.programmingTasks[slotno]; + + var task1 = parameterSet.BuildWupTxLatMBusTask(); + task1.OnProgress += this.Task_OnProgress; + task1.Slotno = slotno; + task1.Rowno = rowno++; + tasks.Enqueue(task1); + + var task2 = parameterSet.BuildTestParametersTask(); + task2.OnProgress += this.Task_OnProgress; + task2.Slotno = slotno; + task2.Rowno = rowno++; + tasks.Enqueue(task2); + + var task3 = parameterSet.BuildSetupDisplayTask(); + task3.OnProgress += this.Task_OnProgress; + task3.Slotno = slotno; + task3.Rowno = rowno++; + tasks.Enqueue(task3); + + var task4 = parameterSet.BuildOptoOnTask(); + task4.OnProgress += this.Task_OnProgress; + task4.Slotno = slotno; + task4.Rowno = rowno++; + tasks.Enqueue(task4); + + if (!this.eregisterTasks.ContainsKey(slotno)) + { + this.eregisterTasks[slotno] = new Queue(); + } + + var etasks = this.eregisterTasks[slotno]; + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckMBusStatus, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckBatteryVoltage, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckBatteryRemaining, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckRadioFWVersion, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckReboots, + ProgressHandler = this.Task_OnProgress + }); + } + } + + public void InitializeCalibration(Int32 slotno) + { + var parameterSet = this.programmingParameters[slotno]; + var rowno = 1; + + this.OnProgress?.Invoke(0, rowno++, $"Seriennr", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Radio Adresse", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Finale Adresse", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"WUP-TX-LAT-MBus", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Parametersatz", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Anzeige-111111111", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Opto ein", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"MBus status = 7", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Batteriespannung (Volts)", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Batterielaufzeit (Jahre)", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"FW Version", TaskState.Disabled); + this.OnProgress?.Invoke(0, rowno++, $"Reboots <= 2", TaskState.Disabled); + + rowno = 1; + + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.Serialno}", TaskState.Disabled); + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.RadioAddress}", TaskState.Disabled); + this.OnProgress?.Invoke(slotno, rowno++, $"{parameterSet.FinalAddress}", TaskState.Disabled); + + this.programmingTasks[slotno] = new Queue(); + var tasks = this.programmingTasks[slotno]; + + var task1 = parameterSet.BuildWupTxLatMBusTask(); + task1.OnProgress += this.Task_OnProgress; + task1.Slotno = slotno; + task1.Rowno = rowno++; + tasks.Enqueue(task1); + + var task2 = parameterSet.BuildTestParametersTask(); + task2.OnProgress += this.Task_OnProgress; + task2.Slotno = slotno; + task2.Rowno = rowno++; + tasks.Enqueue(task2); + + var task3 = parameterSet.BuildSetupDisplayTask(); + task3.OnProgress += this.Task_OnProgress; + task3.Slotno = slotno; + task3.Rowno = rowno++; + tasks.Enqueue(task3); + + var task4 = parameterSet.BuildOptoOnTask(); + task4.OnProgress += this.Task_OnProgress; + task4.Slotno = slotno; + task4.Rowno = rowno++; + tasks.Enqueue(task4); + + this.eregisterTasks[slotno] = new Queue(); + var etasks = this.eregisterTasks[slotno]; + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckMBusStatus, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckBatteryVoltage, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckBatteryRemaining, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckRadioFWVersion, + ProgressHandler = this.Task_OnProgress + }); + + etasks.Enqueue(new JustTask + { + Slotno = slotno, + Rowno = rowno++, + TaskHandler = task4.CheckReboots, + ProgressHandler = this.Task_OnProgress }); } - public event Action Done; - - public event Action Activated + public void Run() { - add => this.broadcaster.Activated += value; - remove => this.broadcaster.Activated -= value; - } + var tasks = default(List); + var allDone = true; - public void Add(Int32 slotno, Int32 serialno, UInt32 address) - { - this.endpoints[slotno] = new Endpoint(this.logger) - { - Slot = slotno, - SerialNo = serialno, - Address = address - }; - this.endpoints[slotno].Done += this.Endpoint_Done; - } - - public void AddHexCommand(Int32 slotno, String command) - { - if (this.endpoints.ContainsKey(slotno)) - { - this.endpoints[slotno].AddHexCommand(command); - } - } - - public void ActivateSIRT() => this.broadcaster.Open(); - - public void DeactivateSIRT() => this.broadcaster.Close(); - - public IEnumerable Slots() => this.endpoints.Values.Select(x => x.Slot); - - public IEnumerable SerialNumbers() => this.endpoints.Values.Select(x => x.SerialNo); - - public IEnumerable RadioAddresses() => this.endpoints.Values.Select(x => x.Address); - - public IEnumerable InitForInspection() => this.endpoints.Values.Select(x => this.Run(x.InitForInspection)); - - public IEnumerable SetupForInspection() => this.endpoints.Values.Select(x => this.Run(x.SetupForInspection)); - - public IEnumerable SetDisplay111111111() => this.endpoints.Values.Select(x => this.Run(x.SetDisplay111111111)); - - public IEnumerable StartLED() => this.endpoints.Values.Select(x => this.Run(x.StartLED)); - - public IEnumerable DoChecks() => this.endpoints.Values.Select(x => x.DoChecks()); - - public IEnumerable> RunCommands() - { do { - var commands = this.endpoints.Values.Select(x => x.RunCommand()).ToArray(); + tasks = new List(); - foreach (var command in commands) + foreach (var queue in this.programmingTasks.Values) { - if (command != null) + if (queue.Count > 0) { - this.Run(() => command); + tasks.Add(queue.Dequeue()); } } - if (commands.Any(x => x is null)) + do { - break; - } - else + allDone = true; + + foreach (var task in tasks) + { + if (task.TaskStatus != JustTaskStatus.Completed) + { + this.broadcaster.TryRun(task); + + Thread.Sleep(100); + + allDone = false; + } + } + + Thread.Sleep(100); + + } while (!allDone); + + foreach (var task in tasks) { - yield return commands; + var slotno = task.Slotno; + + if (!this.completedTasks.ContainsKey(slotno)) + { + this.completedTasks[slotno] = new Queue(); + } + + this.completedTasks[slotno].Enqueue(task); } - } while (true); - } + } while (tasks.Count > 0); - private EndpointTask Run(Func taskHandler) - { - var task = taskHandler(); - - this.broadcaster.Add(task); - - return task; - } - - private void Endpoint_Done(Int32 remainingTasks) - { - this.tasksDone++; - - Thread.Sleep(1000); - - if (this.tasksDone == this.endpoints.Count) + foreach (var kvp in this.completedTasks) { - this.Done?.Invoke(0); + foreach (var task in kvp.Value) + { + task.Refresh(); + } + } + + var countTasks = this.eregisterTasks[1].Count; + + for (var c = 0; c < countTasks; c++) + { + foreach (var kvp in this.eregisterTasks) + { + var slotno = kvp.Key; + var parameterSet = this.programmingParameters[slotno]; + var eregisterTask = kvp.Value.Dequeue(); + + eregisterTask.Execute(parameterSet); + kvp.Value.Enqueue(eregisterTask); + } } } + public void Run(Int32 slotno) + { + this.completedTasks[slotno] = new Queue(); + + var queue = this.programmingTasks[slotno]; + var awaiter = new ManualResetEventSlim(); + + while (queue.Count > 0) + { + var task = queue.Dequeue(); + + while (true) + { + if (this.broadcaster.TryRun(task) == JustTaskStatus.Sent) + { + task.Cancelled += _ => awaiter.Set(); + task.Completed += _ => awaiter.Set(); + + awaiter.Wait(); + awaiter.Reset(); + } + + if (task.TaskStatus == JustTaskStatus.Completed) + { + break; + } + + Thread.Sleep(100); + } + + this.completedTasks[slotno].Enqueue(task); + } + + foreach (var kvp in this.completedTasks) + { + foreach (var task in kvp.Value) + { + task.Refresh(); + } + } + + var countTasks = this.eregisterTasks[1].Count; + var eregisterTasks = this.eregisterTasks[slotno]; + var eregisterTasksCount = eregisterTasks.Count; + var parameterSet = this.programmingParameters[slotno]; + + for (var row = 0; row < eregisterTasksCount; row++) + { + var eregisterTask = eregisterTasks.Dequeue(); + + eregisterTask.Execute(parameterSet); + eregisterTasks.Enqueue(eregisterTask); + } + } + + public void Run(ProgrammingTask task) + { + var status = this.broadcaster.TryRun(task); + var awaiter = new ManualResetEventSlim(); + + while (status != JustTaskStatus.Sent) + { + awaiter.Wait(1000); + awaiter.Reset(); + + status = this.broadcaster.TryRun(task); + } + } + + public Boolean StartOnCOMPort(String portName) + { + var activated = false; + + for (var i = 0; i < 10; i++) + { + this.Stop(); + + this.broadcaster = new JustSirtBroadcaster(portName); + this.broadcaster.Logging += this.logger.Debug; + + if (this.broadcaster.TryActivate()) + { + activated = true; + + break; + } + + Thread.Sleep(1000); + } + + return activated; + } + + public void Stop() + { + if (this.broadcaster != null) + { + this.broadcaster.TryDeactivate(); + this.programmingParameters.Clear(); + this.programmingTasks.Clear(); + + this.broadcaster = null; + } + } + + private void Task_OnProgress(ProgrammingTask task) + { + this.OnProgress?.Invoke(task.Slotno, task.Rowno, task.Label, task.State); + + if (!String.IsNullOrWhiteSpace(task.RSSI)) + { + this.OnProgress?.Invoke(task.Slotno, this.rssiRow, task.RSSI, TaskState.Disabled); + } + } + + private void Task_OnProgress(Int32 slot, Int32 rowno, String label, TaskState state) + => this.OnProgress?.Invoke(slot, rowno, label, state); + private static ILogger CreateNLogger(string name) { LogManager.Configuration = new LoggingConfiguration(); diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingTask.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingTask.cs new file mode 100644 index 00000000..55d0266b --- /dev/null +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/ProgrammingTask.cs @@ -0,0 +1,326 @@ +namespace Common.Hardware.WaterMeter.eRegister +{ + using Common.Hardware.Interfaces.Ports.Sirt; + using Common.Hardware.Interfaces.Ports.Sirt.Parameters; + using Common.Hardware.Interfaces.Ports.SirtBroadcaster; + using Common.Hardware.WaterMeter.eRegister.Data; + + using System; + using System.Collections.Generic; + using System.Linq; + + public class ProgrammingTask : JustSirtTask + { + private const String PENDING = nameof(PENDING); + + private readonly ICollection lats = new List(); + private readonly ICollection bups = new List(); + private readonly ICollection debugs = new List(); + private readonly ICollection semis = new List(); + + public event Action OnProgress; + + public Byte[] EncryptionKey { get; set; } + + public Int32 Slotno { get; internal set; } + + public Int32 Rowno { get; internal set; } + + public String Label { get; private set; } + + public String RSSI { get; private set; } + + public TaskState State { get; private set; } = TaskState.None; + + public override void PrepareForRun() + { + this.OnProgress?.Invoke(this); + + base.PrepareForRun(); + } + + public override void ReceiveMessage(JustSirtMessage response, Int32 mhz) + { + if (this.EncryptionKey != null && this.EncryptionKey.Length == 16) + { + this.DecryptResponse(response); + } + + if (this.State != TaskState.Success && response.Cmd == JustSirtMessage.FROMAIR) + { + var label = this.Label; + var state = this.State; + var data = response.Data; + var type = data[0]; + + if (type == JustSirtMessage.SEMI) + { + var semi = new SEMI(data, (UInt16)mhz); + label = semi.PAMStatus.ToString(); + + if (semi.PAMStatus == PAMStatus.OK) + { + state = TaskState.Success; + this.TaskStatus = JustTaskStatus.Completed; + } + else + { + state = TaskState.Error; + this.TaskStatus = JustTaskStatus.Cancelled; + } + + this.semis.Add(semi); + } + else if (type == JustSirtMessage.BUP) + { + label = nameof(JustSirtMessage.BUP); + state = TaskState.Warning; + + this.bups.Add(new BUP(data)); + } + else if (type == JustSirtMessage.LAT) + { + label = nameof(JustSirtMessage.LAT); + state = TaskState.Warning; + + this.lats.Add(new LAT(data)); + } + else if (type == JustSirtMessage.DEBUG) + { + label = nameof(JustSirtMessage.DEBUG); + state = TaskState.Warning; + + this.debugs.Add(new DEBUG(data)); + } + + this.Label = label; + this.State = state; + this.RSSI = SEMI.CalculateRSSI(response.P2, (UInt16)mhz); + } + + this.OnProgress?.Invoke(this); + base.ReceiveMessage(response, mhz); + } + + public override Byte[] ToByteArray() + { + if (this.EncryptionKey != null && this.EncryptionKey.Length == 16) + { + this.EncryptRequest(); + } + + return base.ToByteArray(); + } + + internal void Refresh() + { + var semi = this.semis.LastOrDefault(); + + if (semi != null) + { + this.Label = semi.PAMStatus.ToString(); + + if (semi.PAMStatus == PAMStatus.OK) + { + this.State = TaskState.Success; + } + else + { + this.State = TaskState.Error; + } + } + else if (this.LastPayload != null) + { + var last = new JustSirtMessage(this.LastPayload); + P11 p11 = last.P1; + + if (p11.LenOverflow) + { + this.Label = "LEN OVERFLOW"; + this.State = TaskState.Error; + } + else if (!p11.SrcChannel && p11.InvalidMod1) + { + this.Label = "MOD 1 CRC ERROR"; + this.State = TaskState.Error; + } + else if (p11.SrcChannel && p11.InvalidMod2) + { + this.Label = "MOD 2 CRC ERROR"; + this.State = TaskState.Error; + } + else + { + this.Label = nameof(PAMStatus.OK); + this.State = TaskState.Success; + } + } + else + { + this.Label = "NA"; + this.State = TaskState.Error; + } + + this.OnProgress?.Invoke(this); + } + + internal Tuple CheckMBusStatus(ParameterSet parameterSet) + { + var label = $"{this.semis.LastOrDefault()?.MBusStatus} OK"; + + return new Tuple(label, TaskState.Success); + } + + internal Tuple CheckBatteryVoltage(ParameterSet parameterSet) + { + var label = $"{this.debugs.LastOrDefault()?.BatteryVoltage:0.00} OK"; + + return new Tuple(label, TaskState.Success); + } + + internal Tuple CheckBatteryRemaining(ParameterSet parameterSet) + { + var label = $"{this.semis.LastOrDefault()?.BatteryRemaining:0.0} OK"; + + return new Tuple(label, TaskState.Success); + } + + internal Tuple CheckRadioFWVersion(ParameterSet parameterSet) + { + var label = $"{this.debugs.LastOrDefault()?.RadioFirmwareVersion} OK"; + + return new Tuple(label, TaskState.Success); + } + + internal Tuple CheckMetrologyFWVersion(ParameterSet arg) + { + var label = $"{this.debugs.LastOrDefault()?.MetrologyFirmwareVersion} OK"; + + return new Tuple(label, TaskState.Success); + } + + internal Tuple CheckReboots(ParameterSet parameterSet) + { + var label = $"{this.debugs.LastOrDefault()?.RebootCount} OK"; + + return new Tuple(label, TaskState.Success); + } + + private void DecryptResponse(JustSirtMessage response) + { + var data = response.Data; + var length = data.Length; + + if (length < 13) + { + return; + } + + var bytes = new Byte[length]; + var hex = BitConverter.ToString(bytes); + + Array.Copy(data, 0, bytes, 0, length); + + var token = bytes[1]; + + for (var x = 6; x < length; x++) + { + token += (Byte)(bytes[x - (token & 0x3) - 1] >> ((token >> 6) & 0x1)); + + bytes[x] ^= this.EncryptionKey[(token >> 2) & 0x0F]; + + if (token >= 0x80) + { + bytes[x] = (Byte)~bytes[x]; + } + } + + var crc = this.CalculateCRC(bytes, 5, length - 2); + + if (crc == 0 || crc == UInt16.MaxValue) + { + response.Data = bytes; + } + } + + private void EncryptRequest() + { + var data = this.Data; + var dataLength = data.Length; + var telegramLength = dataLength + 2; + var telegram = new Byte[telegramLength]; + + Array.Copy(data, 0, telegram, 0, dataLength); + + var telegramForCRCLength = telegramLength + 4; + var telegramForCRC = new Byte[telegramForCRCLength]; + var address = this.Address; + + telegramForCRC[0] = (Byte)(address >> 24); + telegramForCRC[1] = (Byte)(address >> 16); + telegramForCRC[2] = (Byte)(address >> 8); + telegramForCRC[3] = (Byte)(address >> 0); + + Array.Copy(telegram, 0, telegramForCRC, 4, telegramLength); + + var telegramCRC = this.CalculateCRC(telegramForCRC, 1, telegramForCRCLength - 2); + + telegram[telegramLength - 2] = (Byte)(telegramCRC >> 8); + telegram[telegramLength - 1] = (Byte)(telegramCRC >> 0); + + var reference = address; + var token = (Byte)0xFF; + + for (var i = 0; i < telegramLength; i++) + { + token += (Byte)(((reference >> ((token & 0x3) << 3)) & 0xFF) >> ((token >> 6) & 1)); + + reference = reference << 8; + reference += telegram[i]; + + telegram[i] ^= this.EncryptionKey[(token >> 2) & 0x0F]; + + if (token >= 0x80) + { + telegram[i] = (Byte)~telegram[i]; + } + } + + this.Data = telegram; + } + + private UInt16 CalculateCRC(Byte[] data, Int32 start, Int32 length) + { + var crc = (UInt16)0xFFFF; + var dataLength = data?.Length ?? 0; + + if (start + length > dataLength) + { + return crc; + } + + for (var b = start; b < length; b++) + { + var _byte = data[b]; + var token = (UInt16)((_byte << 8) & 0xFF00); + + for (var i = 0; i < 8; i++) + { + if (0x8000 == ((crc ^ token) & 0x8000)) + { + crc <<= 1; + crc ^= 0x1021; + } + else + { + crc <<= 1; + } + + token <<= 1; + } + } + + return crc; + } + } +} diff --git a/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/TaskState.cs b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/TaskState.cs new file mode 100644 index 00000000..e06d6018 --- /dev/null +++ b/Common/Hardware/WaterMeter/eRegister/Common.Hardware.WaterMeter.eRegister/TaskState.cs @@ -0,0 +1,11 @@ +namespace Common.Hardware.WaterMeter.eRegister +{ + public enum TaskState + { + Disabled, + None, + Success, + Warning, + Error + } +} \ No newline at end of file diff --git a/Common/Logic/Common.Logic.Extensions.SQL/SQLReader.cs b/Common/Logic/Common.Logic.Extensions.SQL/SQLReader.cs index fca11316..1a19eaf5 100644 --- a/Common/Logic/Common.Logic.Extensions.SQL/SQLReader.cs +++ b/Common/Logic/Common.Logic.Extensions.SQL/SQLReader.cs @@ -4,6 +4,7 @@ using System; using System.Data.SqlClient; + using System.Diagnostics; public class SQLReader : ISQLReader, IDisposable { @@ -34,9 +35,35 @@ type = typeof(T); } - readedValue = Convert.ChangeType(readedValue, type); + var tryParse = true; - if (readedValue is T expectedValue) + if (tryParse) + { + try + { + readedValue = Convert.ChangeType(readedValue, type); + tryParse = false; + } + catch (Exception e) + { + Debug.Print(e.ToString()); + } + } + + if (tryParse) + { + try + { + readedValue = Enum.Parse(type, $"{readedValue}", true); + tryParse = false; + } + catch (Exception e) + { + Debug.Print(e.ToString()); + } + } + + if (!tryParse && readedValue is T expectedValue) { value = expectedValue; } diff --git a/Common/OmniPlus/InspectionUI.Plugins.Omni/TestBatch.cs b/Common/OmniPlus/InspectionUI.Plugins.Omni/TestBatch.cs index 0bf773c6..37ca2e05 100644 --- a/Common/OmniPlus/InspectionUI.Plugins.Omni/TestBatch.cs +++ b/Common/OmniPlus/InspectionUI.Plugins.Omni/TestBatch.cs @@ -8,15 +8,10 @@ using System; using System.Collections.Generic; + using System.Text; using System.Threading; using System.Threading.Tasks; - /// - /// if $(ConfigurationName) == Development rmdir "Z:\Programme_Sensus\plugins\omni" /s - /// if $(ConfigurationName) == Development mkdir "Z:\Programme_Sensus\plugins\omni" /s - /// if $(ConfigurationName) == Development xcopy $(TargetDir) "Z:\Programme_Sensus\plugins\omni" /s /y - /// - [TestBatch("OMNI+ Prüfung")] public partial class TestBatch : TestBatchBase { @@ -85,7 +80,7 @@ var testPointsCount = testPoints.Count; var layout = this.testBench.Layout; var columnsCount = this.SetColumnDefinitions(testPointsCount, layout); - this.info = this.remoteControl.GetInfo(); + this.info = new InfoMessage(); // this.remoteControl.GetInfo(); this.SetTestHead(layout, columnsCount); this.SetOrderHead(inspectionOrder, layout, columnsCount); @@ -271,6 +266,18 @@ } }) .Wait(); + + var stringBuilder = new StringBuilder(); + + foreach (var meter in this.uimeters) + { + if (meter.IsInvalid) + { + stringBuilder.AppendLine(meter.Messages); + } + } + + this.testBench.Notify(stringBuilder.ToString()); } private void SetTestMeters(Int32 testPointsCount, IGrid layout) diff --git a/Common/OmniPlus/InspectionUI.Plugins.Omni/UIMeter.cs b/Common/OmniPlus/InspectionUI.Plugins.Omni/UIMeter.cs index 385ebe90..be1fe674 100644 --- a/Common/OmniPlus/InspectionUI.Plugins.Omni/UIMeter.cs +++ b/Common/OmniPlus/InspectionUI.Plugins.Omni/UIMeter.cs @@ -38,7 +38,7 @@ set => this[1].Text = value; } - public String Messages => this.meter.Messages; + public String Messages => $"{this.Slot} {this.meter.Messages}"; protected Int32 currentTPCellIndex; @@ -48,6 +48,8 @@ set => this.currentTPCellIndex = value; } + public Boolean IsInvalid => !this.meter.IsActive && !String.IsNullOrWhiteSpace(this.meter.Messages); + public Task ConnectAsync(CancellationToken cancellationToken) { void Connect(Object state) @@ -72,6 +74,11 @@ } }; } + else if (!meter.IsActive && !String.IsNullOrWhiteSpace(meter.Messages)) + { + this[1].Background = TestBatch.Brushes.Red; + this[1].Foreground = TestBatch.Brushes.White; + } uimeter.Pcb = meter.Pcb; } diff --git a/Common/OmniPlus/InspectionUI.RemoteControl/RemoteConnection.cs b/Common/OmniPlus/InspectionUI.RemoteControl/RemoteConnection.cs index 1bc0ce2e..50d034ad 100644 --- a/Common/OmniPlus/InspectionUI.RemoteControl/RemoteConnection.cs +++ b/Common/OmniPlus/InspectionUI.RemoteControl/RemoteConnection.cs @@ -11,15 +11,13 @@ using Microsoft.AspNet.SignalR.Client; - // xcopy "$(TargetDir)*.dll" "\\sla12file\Auftrag\Programme_Sensus\Pruefstation2000\TLB\Remote control" /Y - [ClassInterface(ClassInterfaceType.None)] [ComSourceInterfaces(typeof(IRemoteConnectionEvents))] [Guid("FB571D10-F46A-4B32-B1B1-6E7DCE362CC1")] [ComVisible(true)] public class RemoteConnection : IRemoteConnection { - const string LogFile = @".\signalR.txt"; + private const string LogFile = @".\signalR.txt"; private readonly ICollection disposables = new List(); diff --git a/Common/OmniPlus/InspectionUI/App.config b/Common/OmniPlus/InspectionUI/App.config index b86b950d..cd98da8d 100644 --- a/Common/OmniPlus/InspectionUI/App.config +++ b/Common/OmniPlus/InspectionUI/App.config @@ -4,10 +4,9 @@ - - - - + + + diff --git a/Common/OmniPlus/InspectionUI/App.xaml b/Common/OmniPlus/InspectionUI/App.xaml index 30938e9e..1d3170bf 100644 --- a/Common/OmniPlus/InspectionUI/App.xaml +++ b/Common/OmniPlus/InspectionUI/App.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Converters="clr-namespace:InspectionUI.Converters" - StartupUri="eRegister/Init.xaml" > + StartupUri="MainWindow.xaml" > diff --git a/Common/OmniPlus/InspectionUI/InspectionUI.csproj b/Common/OmniPlus/InspectionUI/InspectionUI.csproj index fc585af5..46e5dcda 100644 --- a/Common/OmniPlus/InspectionUI/InspectionUI.csproj +++ b/Common/OmniPlus/InspectionUI/InspectionUI.csproj @@ -72,17 +72,6 @@ MSBuild:Compile Designer - - Init.xaml - - - RunCommans.xaml - - - - - - ItemsGrid.xaml @@ -111,16 +100,8 @@ - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - + + Designer MSBuild:Compile diff --git a/Common/OmniPlus/InspectionUI/ItemsGrid.xaml.cs b/Common/OmniPlus/InspectionUI/ItemsGrid.xaml.cs index f3a54f97..278e1936 100644 --- a/Common/OmniPlus/InspectionUI/ItemsGrid.xaml.cs +++ b/Common/OmniPlus/InspectionUI/ItemsGrid.xaml.cs @@ -1,5 +1,6 @@ namespace InspectionUI { + using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; @@ -45,52 +46,55 @@ private void ReorderItems(object sender, PropertyChangedEventArgs e) { - this.Children.Clear(); - this.RowDefinitions.Clear(); - this.ColumnDefinitions.Clear(); - - var row = 0; - var col = 0; - - foreach (var rowItem in this.ItemsSource) + this.Dispatcher.Invoke(new Action(() => { - this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) }); + this.Children.Clear(); + this.RowDefinitions.Clear(); + this.ColumnDefinitions.Clear(); - foreach (var cell in rowItem) + var row = 0; + var col = 0; + + foreach (var rowItem in this.ItemsSource) { - if (row == 0) - { - if (cell is ItemsGridCellVM header) - { - for (int i = 0; i < header.ColSpan; i++) - { - var width = header.Width <= 0 - ? GridLength.Auto - : new GridLength(header.Width, GridUnitType.Star); + this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) }); - this.ColumnDefinitions.Add(new ColumnDefinition { Width = width }); + foreach (var cell in rowItem) + { + if (row == 0) + { + if (cell is ItemsGridCellVM header) + { + for (int i = 0; i < header.ColSpan; i++) + { + var width = header.Width <= 0 + ? GridLength.Auto + : new GridLength(header.Width, GridUnitType.Star); + + this.ColumnDefinitions.Add(new ColumnDefinition { Width = width }); + } } } + + cell.Col = col; + cell.Row = row; + + var cellContent = new ContentControl { Content = cell }; + + Grid.SetRow(cellContent, row); + Grid.SetRowSpan(cellContent, cell.RowSpan); + Grid.SetColumn(cellContent, col); + Grid.SetColumnSpan(cellContent, cell.ColSpan); + + this.Children.Add(cellContent); + + col += cell.ColSpan; } - cell.Col = col; - cell.Row = row; - - var cellContent = new ContentControl { Content = cell }; - - Grid.SetRow(cellContent, row); - Grid.SetRowSpan(cellContent, cell.RowSpan); - Grid.SetColumn(cellContent, col); - Grid.SetColumnSpan(cellContent, cell.ColSpan); - - this.Children.Add(cellContent); - - col += cell.ColSpan; + col = 0; + row++; } - - col = 0; - row++; - } + })); } } } diff --git a/Common/OmniPlus/InspectionUI/VM.cs b/Common/OmniPlus/InspectionUI/ViewModels/VM.cs similarity index 100% rename from Common/OmniPlus/InspectionUI/VM.cs rename to Common/OmniPlus/InspectionUI/ViewModels/VM.cs diff --git a/Common/OmniPlus/InspectionUI/VM[T].cs b/Common/OmniPlus/InspectionUI/ViewModels/VM[T].cs similarity index 100% rename from Common/OmniPlus/InspectionUI/VM[T].cs rename to Common/OmniPlus/InspectionUI/ViewModels/VM[T].cs diff --git a/Common/OmniPlus/InspectionUI/eRegister/Init.xaml b/Common/OmniPlus/InspectionUI/eRegister/Init.xaml deleted file mode 100644 index 3e6077d2..00000000 --- a/Common/OmniPlus/InspectionUI/eRegister/Init.xaml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// - private void saveRssiToDb(SaveDataClass SaveData) + private Int64 saveRssiToDb(SaveDataClass SaveData) { - var sql = new StringBuilder(); + var sqlConnection = SQLConnection.CreateSQLConnection(GlobalConfig.connectionString.Value); - sql.AppendLine($" Update [Cordonel_Radio_RSSI_History] Set IsLast = 0 WHERE [RadioAdress] = {SaveData.RadioAdress}"); - using (SqlCommand sqlcommand = new SqlCommand(sql.ToString(), connection)) - { - sqlcommand.ExecuteNonQuery(); - } + sqlConnection + .CreateCommand($@" + UPDATE Cordonel_Radio_RSSI_History + SET IsLast = 0 + WHERE RadioAdress = @{nameof(SaveData.RadioAdress)}") + .SetParameter(nameof(SaveData.RadioAdress), (Int64)SaveData.RadioAdress) + .ExecuteNonQuery(); - - sql = new StringBuilder(); - sql.AppendLine($" Insert into [Cordonel_Radio_RSSI_History] "); - sql.AppendLine($" ([RadioAdress],[RSSI_PAM],[RSSI_SEMI],[LimitId],[Result]) VALUES ( "); - sql.AppendLine($" {SaveData.RadioAdress},"); - sql.AppendLine($" {SaveData.RSSI_PAM},"); - sql.AppendLine($" {SaveData.RSSI_SEMI},"); - sql.AppendLine($" {SaveData.LimitId},"); - sql.AppendLine($" {SaveData.Result}"); - sql.AppendLine($" )"); - - using (SqlCommand sqlcommand = new SqlCommand(sql.ToString(), connection)) - { - sqlcommand.ExecuteNonQuery(); - } + return sqlConnection + .CreateCommand($@" + INSERT INTO Cordonel_Radio_RSSI_History + ( RadioAdress + , RSSI_PAM + , RSSI_SEMI + , Datum + , LimitId + , Result) + OUTPUT inserted.id + VALUES (@{nameof(SaveData.RadioAdress)} + , @{nameof(SaveData.RSSI_PAM)} + , @{nameof(SaveData.RSSI_SEMI)} + , CURRENT_TIMESTAMP + , @{nameof(SaveData.LimitId)} + , @{nameof(SaveData.Result)})") + .SetParameter(nameof(SaveData.RadioAdress), (Int64)SaveData.RadioAdress) + .SetParameter(nameof(SaveData.RSSI_PAM), SaveData.RSSI_PAM) + .SetParameter(nameof(SaveData.RSSI_SEMI), SaveData.RSSI_SEMI) + .SetParameter(nameof(SaveData.LimitId), SaveData.LimitId) + .SetParameter(nameof(SaveData.Result), SaveData.Result) + .ExecuteScalar(x => x.GetValue(0)); } - } } diff --git a/Common/Service/MeterProcessState/Controllers/TestBenchController.cs b/Common/Service/MeterProcessState/Controllers/TestBenchController.cs index 76cb8147..6885f443 100644 --- a/Common/Service/MeterProcessState/Controllers/TestBenchController.cs +++ b/Common/Service/MeterProcessState/Controllers/TestBenchController.cs @@ -223,7 +223,7 @@ return this.BadRequest("Invalid data."); } - + [Route("GetTestResults"), HttpGet] public IHttpActionResult GetTestResults(int SerialNr, int TestRunNr) @@ -357,22 +357,22 @@ { } - + + } + + return this.Content(HttpStatusCode.OK, tr); } + } - return this.Content(HttpStatusCode.OK, tr); + public class CordonelCalibration + { + public int PcbId { get; set; } + + public int TestRunNr { get; set; } + + public double Offset { get; set; } } } - - public class CordonelCalibration - { - public int PcbId { get; set; } - - public int TestRunNr { get; set; } - - public double Offset { get; set; } - } -} } diff --git a/Common/SoftwareAccessHelper/LocalWebRequest.cs b/Common/SoftwareAccessHelper/LocalWebRequest.cs index fb15f337..7f42fae3 100644 --- a/Common/SoftwareAccessHelper/LocalWebRequest.cs +++ b/Common/SoftwareAccessHelper/LocalWebRequest.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.IO; using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; namespace Xylem.Common.Logic.SoftwareAccessHelper { @@ -118,7 +120,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper var request = new RestRequest(Method.POST); ServicePointManager.Expect100Continue = false; - + request.AddHeader("Content-Type", "multipart/form-data"); @@ -126,7 +128,8 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper request.Files.Add(new FileParameter { Name = "file", - Writer = (s) => { + Writer = (s) => + { var stream = new MemoryStream(content); stream.CopyTo(s); stream.Dispose(); @@ -166,19 +169,20 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper { var client = new RestClient(url); - // WebRequest.DefaultWebProxy = null; + // WebRequest.DefaultWebProxy = null; var request = new RestRequest(Method.POST); ServicePointManager.Expect100Continue = false; - + request.AddHeader("Content-Type", "multipart/form-data"); request.Files.Add(new FileParameter { Name = "file", - Writer = (s) => { + Writer = (s) => + { var stream = new MemoryStream(content); stream.CopyTo(s); stream.Dispose(); @@ -264,6 +268,45 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper } + + /// + /// Post Request Async + /// + /// + /// - Initial. + /// + /// + /// + /// + /// + /// + public static String PostRequestAsync(String url, Double timeoutMs, out HttpStatusCode httpStatus, Object json = null) + { + try + { + var httpClient = new HttpClient(); + + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + httpClient.Timeout = TimeSpan.FromMilliseconds(timeoutMs); + + var postedJson = JsonConvert.SerializeObject(json, Formatting.Indented); + var postedBody = new StringContent(postedJson); + postedBody.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json"); + var posted = httpClient + .PostAsync(url, postedBody) + .Result; + + httpStatus = posted.StatusCode; + return posted.Content.ReadAsStringAsync().Result; + } + catch (Exception error) + { + httpStatus = HttpStatusCode.ServiceUnavailable; + return error.Message; + } + } + + /// /// Web request with asynchronous operation /// @@ -272,18 +315,19 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper /// /// /// - public static IRestResponse PostRequestAndGetResponseAsync(String url, Int32? timeoutMs = null, Object json = null, + public static IRestResponse PostRequestAndGetResponseAsync(String url, Int32? timeoutMs = null, Object json = null, Dictionary header = null) { try { var client = new RestClient(url); + client.AddDefaultHeader("Accept", "application/json"); //WebRequest.DefaultWebProxy = null; ServicePointManager.Expect100Continue = false; var request = new RestRequest(Method.POST); - + if (header != null) { foreach (var item in header) @@ -294,10 +338,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper } } - } - - request.AddHeader("Content-Type", "application/json"); request.AddHeader("Accept", "application/json"); @@ -308,8 +349,6 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper var r = client.ExecuteAsPost(request, Method.POST.ToString()); return r; - - } catch (Exception error) { @@ -318,9 +357,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper StatusCode = HttpStatusCode.InternalServerError, Content = error.ToString() }; - } - } #region HTTP String extensions @@ -367,6 +404,70 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper } #endregion HTTP Object extensions + /// + /// Web request + /// + /// + /// + /// + /// + /// + public static String DeleteRequest(String url, Int32? timeoutMs = null, Dictionary header = null, Boolean isRetry = false) + { + Int32 temp; + var ret = DeleteRequestWithError(url, out temp, timeoutMs, header, isRetry); + if (temp != 200) + { + throw new ApplicationException($"WebRequest Status {temp}"); + } + return ret; + } + + /// + /// Web request with asynchronous operation, error code response + /// + /// + /// + /// + /// + /// + /// + public static String DeleteRequestWithError(String url, out Int32 errorCode, Int32? timeoutMs = null, Dictionary header = null, Boolean isRetry = false) + { + var client = new RestClient(url); + var request = new RestRequest(Method.DELETE); + ServicePointManager.Expect100Continue = false; + if (!timeoutMs.HasValue) + { + timeoutMs = 800; + } + + request.Timeout = timeoutMs.Value; + + if (header != null) + { + foreach (var item in header) + { + if (item.Key != "Accept") + { + request.AddHeader(item.Key, item.Value); + } + } + } + request.AddHeader("Accept", "application/json"); + + var r = client.Execute(request); + errorCode = r.StatusCode.GetHashCode(); + if (r.StatusCode == HttpStatusCode.OK) + { + return r.Content; + } + + if (r.StatusCode != 0) + return r.Content; + + return !isRetry ? DeleteRequest(url, timeoutMs, header, true) : r.Content; + } /// /// Web request /// @@ -378,7 +479,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper public static String GetRequest(String url, Int32? timeoutMs = null, Dictionary header = null, Boolean isRetry = false) { Int32 temp; - var ret = GetRequestWithError(url, out temp, timeoutMs, header, isRetry); + var ret = GetRequestWithError(url, out temp, timeoutMs, header, isRetry); if (temp != 200) { throw new ApplicationException($"WebRequest Status {temp}"); @@ -399,7 +500,6 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper { var client = new RestClient(url); - //WebRequest.DefaultWebProxy = null; var request = new RestRequest(Method.GET); ServicePointManager.Expect100Continue = false; if (!timeoutMs.HasValue) @@ -430,17 +530,10 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper return r.Content; } - if (r.StatusCode != 0) return r.Content; + if (r.StatusCode != 0) + return r.Content; - // Changed logic as it seems to be an endless loop THW 25-Mar-2021 - //if (presult.Status == IPStatus.Success || !isRetry) - if (!isRetry) - { - return GetRequest(url, timeoutMs, header, true); - } - // Removed throwing of exception as the caller cannot evaluate the result THW 25-Mar-2021 - //throw new ApplicationException($"Timeout { r.StatusDescription} {Environment.NewLine} PingState: {presult.Status} {Environment.NewLine} RoundtripTime: {presult.RoundtripTime} "); - return r.Content; + return !isRetry ? GetRequest(url, timeoutMs, header, true) : r.Content; } private static HttpResponse AsJson(this Method method, String url, Action headersHandler = null, Object model = null, Int32? timeoutMs = null) @@ -472,7 +565,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper } ServicePointManager.Expect100Continue = false; - + var response = client.Execute(request); httpResponse.HttpStatusCode = response.StatusCode; diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/App.config b/Common/Ui/Common.UI.SIRTBroadcaster/App.config deleted file mode 100644 index 6551dddf..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/App.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml b/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml deleted file mode 100644 index 6f249b31..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml.cs b/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml.cs deleted file mode 100644 index 81ab4403..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/App.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Common.UI.SIRTBroadcaster -{ - using System; - using System.Windows; - - public partial class App : Application - { - private static Boolean activatedForFirstTime; - - public static event Action Exited; - public static event Action Started; - - public static void Invoke(Action action) => Current?.Dispatcher?.Invoke(action); - - protected override void OnActivated(EventArgs e) - { - base.OnActivated(e); - - if (!activatedForFirstTime) - { - activatedForFirstTime = true; - - Started?.Invoke(); - } - } - - protected override void OnExit(ExitEventArgs e) - { - Exited?.Invoke(); - - base.OnExit(e); - } - } -} diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/Common.UI.SIRTBroadcaster.csproj b/Common/Ui/Common.UI.SIRTBroadcaster/Common.UI.SIRTBroadcaster.csproj deleted file mode 100644 index 75043f30..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/Common.UI.SIRTBroadcaster.csproj +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Debug - AnyCPU - {8D3B1C46-B23E-46CC-9B59-24E34DE60510} - WinExe - Common.UI.SIRTBroadcaster - Common.UI.SIRTBroadcaster - v4.0 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - IDE0003;IDE0049; - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll - - - ..\..\packages\NLog.5.3.2\lib\net35\NLog.dll - - - - - - - - - - - 4.0 - - - - - - - - MSBuild:Compile - Designer - - - InitInspectionWindow.xaml - - - - - - - - - - - - - - - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - MainWindow.xaml - Code - - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - {b23bfaf9-08ae-4311-8c08-fb2bb49ea2ad} - Common.Hardware.Interfaces.Ports.SIRT - - - {9ae071c0-db12-4e09-a3c7-43f6dcd518d6} - Common.Hardware.Interfaces.Ports - - - {E19C1694-132E-477C-86CB-8E146D5F59B0} - Common.Hardware.WaterMeter.eRegister.Features - - - {4E8BB839-D40A-488C-88CE-F21811F1F476} - Common.Hardware.WaterMeter.eRegister - - - {05f0ccaf-9f2b-45f9-a7f8-12f29ad182f3} - Common.Utils.Extensions - - - - \ No newline at end of file diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml b/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml deleted file mode 100644 index 6ced5c2e..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml.cs b/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml.cs deleted file mode 100644 index 14944a74..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/InitInspectionWindow.xaml.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Common.UI.SIRTBroadcaster -{ - using Common.Hardware.WaterMeter.eRegister; - using Common.UI.SIRTBroadcaster.ViewModels; - - using System.Windows; - - public partial class InitInspectionWindow : Window - { - public InitInspectionWindow() - { - this.InitializeComponent(); - - App.Started += this.App_Started; - } - - private void App_Started() - { - if (this.DataContext is InitInspectionVM inspection) - { - inspection.Shutdown += App.Current.Shutdown; - inspection.StartProgramming(); - } - } - } -} diff --git a/Common/Ui/Common.UI.SIRTBroadcaster/MainWindow.xaml b/Common/Ui/Common.UI.SIRTBroadcaster/MainWindow.xaml deleted file mode 100644 index d5adcd04..00000000 --- a/Common/Ui/Common.UI.SIRTBroadcaster/MainWindow.xaml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -166,8 +174,17 @@ fs_value.value = text; if (!text) { fs_error.innerText = `Keine ergebnisse gefunden für PcbId: ${pcbid}.`; + } else { + fetch(`@this.Url.Action("SHA256", "Search")?value=${fs_value.value}`) + .then(response => response.text()) + .then(text => document.getElementById('hash_value').value = text) + .catch(x => { + loader.style.display = 'none'; + console.log(x); + }); + + openModal(); } - openModal(); }) .catch(x => { loader.style.display = 'none'; @@ -175,8 +192,8 @@ }); } - function copyToClipboard() { - navigator.clipboard.writeText(fs_value.value); + function copyToClipboard(inputId) { + navigator.clipboard.writeText(document.getElementById(inputId).value); } diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Create.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Create.cshtml index bfb44b16..4d00b9a5 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Create.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Create.cshtml @@ -1,4 +1,5 @@ @using LaaProductionWeb.App_Infrastructure +@using LaaProductionWeb.Resources @model LaaProduction.Data.Cordonel.Models.CordonelSpecialRequirement @@ -13,7 +14,7 @@ @Html.HiddenFor(x => x.MeterSize) }
@@ -207,8 +208,8 @@
diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Index.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Index.cshtml index f5644f33..f769278a 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Index.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Index.cshtml @@ -1,14 +1,16 @@ -@model List +@using LaaProductionWeb.Resources + +@model List
@@ -61,7 +63,7 @@ @section scripts { - + } \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Pcbids.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Pcbids.cshtml index 8ef82bca..792a4126 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Pcbids.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Pcbids.cshtml @@ -1,12 +1,14 @@ -@model List +@using LaaProductionWeb.Resources + +@model List @if (Model.Count > 0) { - + } else { - + } @foreach (var pcb in Model) diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/ProductionOrders.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/ProductionOrders.cshtml index d02b4367..cb9de5fe 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/ProductionOrders.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/ProductionOrders.cshtml @@ -1,4 +1,6 @@ -@model List +@using LaaProductionWeb.Resources + +@model List @if (Model != null) { @@ -8,15 +10,15 @@ @po.FertigungsauftragNr
-
Auftragnr/Pos
+
@UITranslations.Auftrag_Position_Label
@po.AuftragNr/@po.PositionNr
-
Identnr.
+
@UITranslations.Identnr_Label
@po.IdentNr
-
Region
+
@UITranslations.Region_Label
@po.Region - @po.Size (@po.Key)
diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/TrContent.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/TrContent.cshtml index 91b4e2c7..00f1662a 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/TrContent.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/TrContent.cshtml @@ -24,11 +24,11 @@
diff --git a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Update.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Update.cshtml index 3a57a615..babd0f79 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Update.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/SpecialRequirements/Update.cshtml @@ -1,4 +1,5 @@ @using LaaProductionWeb.App_Infrastructure +@using LaaProductionWeb.Resources @model LaaProduction.Data.Cordonel.Models.CordonelSpecialRequirement @@ -193,8 +194,8 @@ diff --git a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Index.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Index.cshtml index 5e1b1a96..859bb1dd 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Index.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Index.cshtml @@ -1,16 +1,18 @@ -@model List +@using LaaProductionWeb.Resources + +@model List
- Standard requirements - + @UITranslations.StandardRequirements_Title +
@if (Model.SkipRadioCheck == true) { - + } else { - + }
- @{ + @{ var model = new LaaProduction.Data.Cordonel.Models.CordonelStandardRequirement(); } diff --git a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/TrContent.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/TrContent.cshtml index 858a2289..4ab52a7e 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/TrContent.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/TrContent.cshtml @@ -21,11 +21,11 @@ diff --git a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Update.cshtml b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Update.cshtml index ab9cb23e..50b03eda 100644 --- a/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Update.cshtml +++ b/LaaProductionWeb/LaaProductionWeb/Views/StandardRequirements/Update.cshtml @@ -1,11 +1,12 @@ @using LaaProductionWeb.App_Infrastructure +@using LaaProductionWeb.Resources @model LaaProduction.Data.Cordonel.Models.CordonelStandardRequirement \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb/packages.config b/LaaProductionWeb/LaaProductionWeb/packages.config index 7ca02a24..6ea26504 100644 --- a/LaaProductionWeb/LaaProductionWeb/packages.config +++ b/LaaProductionWeb/LaaProductionWeb/packages.config @@ -2,8 +2,6 @@ - - diff --git a/LaaProductionWeb/PendingEmails/PendingEmails.csproj b/LaaProductionWeb/PendingEmails/PendingEmails.csproj index 0ff6e366..c0f8755e 100644 --- a/LaaProductionWeb/PendingEmails/PendingEmails.csproj +++ b/LaaProductionWeb/PendingEmails/PendingEmails.csproj @@ -8,7 +8,7 @@ Exe PendingEmails PendingEmails - v4.8 + v4.8.1 512 true @@ -36,11 +36,26 @@ false + + ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.8.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.1\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + @@ -53,6 +68,11 @@ + + + del "$(TargetDir)*.pdb" +del "$(TargetDir)*.xml" + \ No newline at end of file diff --git a/LaaProductionWeb/PendingEmails/app.config b/LaaProductionWeb/PendingEmails/app.config index f9833da5..2451b347 100644 --- a/LaaProductionWeb/PendingEmails/app.config +++ b/LaaProductionWeb/PendingEmails/app.config @@ -1,12 +1,16 @@  - + + + + + diff --git a/LaaProductionWeb/PendingEmails/packages.config b/LaaProductionWeb/PendingEmails/packages.config new file mode 100644 index 00000000..3a79596e --- /dev/null +++ b/LaaProductionWeb/PendingEmails/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LaaProductionWeb/RoutesBuilder/RoutesBuilder.csproj b/LaaProductionWeb/RoutesBuilder/RoutesBuilder.csproj index 040dbec4..86fa2739 100644 --- a/LaaProductionWeb/RoutesBuilder/RoutesBuilder.csproj +++ b/LaaProductionWeb/RoutesBuilder/RoutesBuilder.csproj @@ -38,10 +38,25 @@ + + ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.8.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.1\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + @@ -54,6 +69,11 @@ + + + del "$(TargetDir)*.pdb" +del "$(TargetDir)*.xml" + \ No newline at end of file diff --git a/LaaProductionWeb/RoutesBuilder/app.config b/LaaProductionWeb/RoutesBuilder/app.config index 09b11bde..c0529168 100644 --- a/LaaProductionWeb/RoutesBuilder/app.config +++ b/LaaProductionWeb/RoutesBuilder/app.config @@ -5,7 +5,7 @@ - + diff --git a/LaaProductionWeb/RoutesBuilder/packages.config b/LaaProductionWeb/RoutesBuilder/packages.config new file mode 100644 index 00000000..3a79596e --- /dev/null +++ b/LaaProductionWeb/RoutesBuilder/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LaaProductionWeb/laapackages b/LaaProductionWeb/laapackages new file mode 160000 index 00000000..68fbd355 --- /dev/null +++ b/LaaProductionWeb/laapackages @@ -0,0 +1 @@ +Subproject commit 68fbd355efcc23a66c45f13bc94cf7448f38a16b
- - Special requirements + + @UITranslations.SpecialRequirements_Title
@Html.DisplayNameFor(_ => model.Version) @if (Model.SkipRadioCheck == true) { - + } else { - + }