This commit is contained in:
Roland Drabesch 2024-09-17 09:33:06 +02:00
commit ffbd85d2c6
388 changed files with 8942 additions and 28168 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "LaaProductionWeb/LaaPackages"]
path = LaaProductionWeb/LaaPackages
url = https://slm.sms-esaap.com/la_operations/laapackages.git

View File

@ -15,4 +15,3 @@ using System.Reflection;
[assembly: AssemblyVersion("2.6.10.*")]
[assembly: AssemblyFileVersion("2.6.10.0")]

View File

@ -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}

View File

@ -55,6 +55,14 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SirtBroadcaster\Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj">
<Project>{F408DE9E-01E6-4CFF-AE79-B572B0674FA2}</Project>
<Name>Common.Hardware.Interfaces.Ports.SirtBroadcaster</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.Sirt.csproj">
<Project>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</Project>
<Name>Common.Hardware.Interfaces.Ports.Sirt</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\Interfaces\Ports\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj">
<Project>{9ae071c0-db12-4e09-a3c7-43f6dcd518d6}</Project>
<Name>Common.Hardware.Interfaces.Ports</Name>
@ -87,21 +95,10 @@
<Project>{F8D84B9A-0FCF-4083-B067-8C39B7314152}</Project>
<Name>OmniPlus</Name>
</ProjectReference>
<ProjectReference Include="..\Ui\Common.UI.SIRTBroadcaster\Common.UI.SIRTBroadcaster.csproj">
<Project>{8D3B1C46-B23E-46CC-9B59-24E34DE60510}</Project>
<Name>Common.UI.SIRTBroadcaster</Name>
</ProjectReference>
<ProjectReference Include="..\Ui\Common.UI.WPFConnector\Common.UI.WPFConnector.csproj">
<Project>{37E4BF89-44AE-4133-BE0B-8355F791A79D}</Project>
<Name>Common.UI.WPFConnector</Name>
</ProjectReference>
<ProjectReference Include="..\Utils\Common.Utils.Extensions\Common.Utils.Extensions.csproj">
<Project>{05f0ccaf-9f2b-45f9-a7f8-12f29ad182f3}</Project>
<Name>Common.Utils.Extensions</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -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);
}
/// <summary>
/// 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
/// </summary>
//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

View File

@ -9,6 +9,11 @@ namespace Xylem.Common.CommonCore.Configuration
/// </summary>
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
/// <summary>
/// GET: test specification for water meter with pressure sensor.
/// </summary>
@ -325,6 +330,16 @@ namespace Xylem.Common.CommonCore.Configuration
return ConfigurationManager.AppSettings["DownloadDbDataAtEolServiceUrl"] ??
DefaultDbDataAtEolServiceUrl;
}
/// <summary>
/// Get EOL data for sentinel
/// </summary>
/// <returns></returns>
public static String EolDataForSentinelServiceUrl()
{
return ConfigurationManager.AppSettings["EolDataForSentinelServiceUrl"] ??
DefaultEolDataForSentinelServiceUrl;
}
/// <summary>
/// Get all Cordonel safes description files.
/// </summary>
@ -383,10 +398,10 @@ namespace Xylem.Common.CommonCore.Configuration
/// - Required life time for shipping line.
/// </summary>
/// <returns></returns>
public static String GetProductionSkipAndLifeTimeInfoServiceUrl()
public static String GetCordonelRequirementInfoServiceUrl()
{
return ConfigurationManager.AppSettings["GetProductionSkipAndLifeTimeInfoUrl"] ??
DefaultGetProductionSkipAndLifeTimeInfoUrl;
return ConfigurationManager.AppSettings["GetCordonelRequirementInfoServiceUrl"] ??
DefaultGetCordonelRequirementInfoUrl;
}
/// <summary>
@ -462,7 +477,7 @@ namespace Xylem.Common.CommonCore.Configuration
/// <summary>
/// FW-Update report doanload as string
/// FW-Update report download as string
/// </summary>
/// <returns></returns>
public static String DownloadFwUpdateReportServiceUrl()

View File

@ -7,8 +7,8 @@
<ProjectGuid>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Common.Hardware.Interfaces.Ports.SIRT</RootNamespace>
<AssemblyName>Common.Hardware.Interfaces.Ports.SIRT</AssemblyName>
<RootNamespace>Common.Hardware.Interfaces.Ports.Sirt</RootNamespace>
<AssemblyName>Common.Hardware.Interfaces.Ports.Sirt</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
@ -41,6 +41,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="JustSirtMessage.cs" />
<Compile Include="JustSirtProxy.cs" />
<Compile Include="Parameters\AuthLevel.cs" />
<Compile Include="Parameters\BluetoothOperating.cs" />
<Compile Include="Parameters\ByteExtensions.cs" />

View File

@ -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;
}
}
}

View File

@ -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<Byte> 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<Byte>();
this.timer = new Timer();
}
public event Action<JustSirtMessage> MessageReceived;
public Boolean IsOpen => this.serialPort.IsOpen;
public event Action<String> 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));
}
}
}

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
public enum OperatingModes
{

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT.Parameters
namespace Common.Hardware.Interfaces.Ports.Sirt.Parameters
{
using System;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
namespace Common.Hardware.Interfaces.Ports.Sirt
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
namespace Common.Hardware.Interfaces.Ports.Sirt
{
using System;

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
namespace Common.Hardware.Interfaces.Ports.Sirt
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.Interfaces.Ports.SIRT
namespace Common.Hardware.Interfaces.Ports.Sirt
{
using System;

View File

@ -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;

View File

@ -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 }
};
}

View File

@ -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
{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -4,16 +4,18 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{37E4BF89-44AE-4133-BE0B-8355F791A79D}</ProjectGuid>
<ProjectGuid>{F408DE9E-01E6-4CFF-AE79-B572B0674FA2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Common.UI.WPFConnector</RootNamespace>
<AssemblyName>Common.UI.WPFConnector</AssemblyName>
<RootNamespace>Common.Hardware.Interfaces.Ports.SirtBroadcaster</RootNamespace>
<AssemblyName>Common.Hardware.Interfaces.Ports.SirtBroadcaster</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@ -24,6 +26,7 @@
<NoWarn>IDE0003;IDE0049;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
@ -31,8 +34,10 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@ -40,20 +45,31 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="EregisterConnector.cs" />
<Compile Include="JustSirtBroadcaster.cs" />
<Compile Include="JustSirtTask.cs" />
<Compile Include="JustTaskStatus.cs" />
<Compile Include="Parameters\BluetoothOperating.cs" />
<Compile Include="Parameters\ByteExtensions.cs" />
<Compile Include="Parameters\OperatingModes.cs" />
<Compile Include="Parameters\P11.cs" />
<Compile Include="Parameters\P12.cs" />
<Compile Include="Parameters\P811.cs" />
<Compile Include="Parameters\PAMStatus.cs" />
<Compile Include="Parameters\PamTimeout.cs" />
<Compile Include="Parameters\RFModuleOperating.cs" />
<Compile Include="Parameters\SirtOperating.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Hardware\WaterMeter\eRegister\Common.Hardware.WaterMeter.eRegister\Common.Hardware.WaterMeter.eRegister.csproj">
<Project>{4E8BB839-D40A-488C-88CE-F21811F1F476}</Project>
<Name>Common.Hardware.WaterMeter.eRegister</Name>
<ProjectReference Include="..\..\..\..\Utils\Common.Utils.Extensions\Common.Utils.Extensions.csproj">
<Project>{05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}</Project>
<Name>Common.Utils.Extensions</Name>
</ProjectReference>
<ProjectReference Include="..\Common.UI.WPF\Common.UI.WPF.csproj">
<Project>{f7316525-ff8e-4651-ba67-3c9b948d1e91}</Project>
<Name>Common.UI.WPF</Name>
<ProjectReference Include="..\Common.Hardware.Interfaces.Ports.Sirt\Common.Hardware.Interfaces.Ports.Sirt.csproj">
<Project>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</Project>
<Name>Common.Hardware.Interfaces.Ports.Sirt</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -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<UInt32, JustSirtTask> runningTasks
= new ConcurrentDictionary<UInt32, JustSirtTask>();
private readonly JustSirtProxy proxy;
public JustSirtBroadcaster(String portName)
{
this.proxy = new JustSirtProxy(portName);
this.proxy.MessageReceived += this.Proxy_MessageReceived;
}
public event Action<String> 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 _);
}
}
}

View File

@ -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<JustSirtMessage> responses = new ConcurrentStack<JustSirtMessage>();
public event Action<JustSirtTask> Completed;
public event Action<JustSirtTask> 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
};
}
}

View File

@ -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,
}
}

View File

@ -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;
/// <summary>
/// 0 -> Transparent Mode at 115k2 Baud 8,n,1
/// </summary>
public Boolean BtOpMode
{
get => this.bits[0] == 1;
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>after "TIME_OFF" is elapsed without any command via Bluetooth, Bluetooth interface will be switched off</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal operation</description>
/// </item>
/// </list>
/// </summary>
public Boolean BtPwrSave
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>BT module will be switched off</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal operation</description>
/// </item>
/// </list>
/// </summary>
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());
}
}

View File

@ -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;
}
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,178 @@
namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters
{
using System;
/// <summary>
/// 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:
/// </summary>
public class P11
{
private readonly Byte[] bits;
public P11() => this.bits = new Byte[8];
private P11(Byte[] bits) => this.bits = bits;
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>RF-Module2 is source</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>RF-Module1 is source</description>
/// </item>
/// </list>
/// <para>only valid if both RF-Module programmed for Sensus RF</para>
/// </summary>
public Boolean SrcChannel
{
get => this.bits[0] == 1;
set => this.bits[0] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>both RF module data are valid</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>only one RF module data is valid</description>
/// </item>
/// </list>
/// <para>only valid if both RF-Module programmed for Sensus RF</para>
/// </summary>
public Boolean BothValid
{
get => this.bits[1] == 1;
set => this.bits[1] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>RF-Module1 data is invalid</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>RF-Module1 data is valid</description>
/// </item>
/// </list>
/// <para>i.e. radio checksum is wrong ...</para>
/// </summary>
public Boolean InvalidMod1
{
get => this.bits[2] == 1;
set => this.bits[2] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>RF-Module2 data is invalid</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>RF-Module2 data is valid</description>
/// </item>
/// </list>
/// <para>i.e. radio checksum is wrong ...</para>
/// </summary>
public Boolean InvalidMod2
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>invalid -> module detects length > 128</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>all ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean LenOverflow
{
get => this.bits[4] == 1;
set => this.bits[4] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>will look at PAM / RAC Pool</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>no attention for PAM / RAC</description>
/// </item>
/// </list>
/// </summary>
public Boolean Attention
{
get => this.bits[5] == 1;
set => this.bits[5] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>
/// <para>If .modeSensus = 0 wireless M-busMode -> T1 - Mode</para>
/// <para>If .modeSensus = 1 SensusRF -> receive at f2</para>
/// </description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>
/// <para>If .modeSensus = 0 wireless M-busMode -> S1 - Mode</para>
/// <para>If .modeSensus = 1 SensusRF -> receive at f1</para>
/// </description>
/// </item>
/// </list>
/// </summary>
public Boolean ModeRF
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>Sensus RF Mode</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>wireless M-Bus Mode</description>
/// </item>
/// </list>
/// </summary>
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());
}
}

View File

@ -0,0 +1,170 @@
namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters
{
using System;
/// <summary>
/// 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.
/// </summary>
public class P12
{
private readonly Byte[] bits;
public P12() => this.bits = new Byte[8];
private P12(Byte[] bits) => this.bits = bits;
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>requested buffer is full or not available</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean BufFull
{
get => this.bits[0] == 1;
set => this.bits[0] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>operating system is busy</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean OsBusy
{
get => this.bits[1] == 1;
set => this.bits[1] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>wrong CRC recognized</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean WrongCRC
{
get => this.bits[2] == 1;
set => this.bits[2] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>command cannot be executed</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean CmdNotExecuted
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>telegram or command Byte unknown</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean CmdUnknown
{
get => this.bits[4] == 1;
set => this.bits[4] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>no such entry found</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean NoEntry
{
get => this.bits[5] == 1;
set => this.bits[5] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>unknown fixed byte</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Ok</description>
/// </item>
/// </list>
/// </summary>
public Boolean ByteUnknown
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>address was 0xFFFFFFFF</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal address</description>
/// </item>
/// </list>
/// </summary>
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());
}
}

View File

@ -0,0 +1,241 @@
namespace Common.Hardware.Interfaces.Ports.SirtBroadcaster.Parameters
{
using System;
/// <summary>
/// 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.
/// <para>There is an public priority within the bits which are described at next table:</para>
/// <list type="table">
/// <listheader>
/// <term>7</term>
/// <term>6</term>
/// <term>5</term>
/// <term>4</term>
/// <term>3</term>
/// <term>2</term>
/// <term>1</term>
/// <term>0</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>1</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <description>delete all entries from pool, regardless of address</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>1</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <description>delete entry with this radio address from pool</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>0</term>
/// <term>1</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <description>write entry with this radio address to pool and delete after transmit</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>1</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <description>write entry with this radio address to pool and delete after SEMI received</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>1</term>
/// <term>X</term>
/// <term>X</term>
/// <term>X</term>
/// <description>write entry with this radio address to pool and leave entry at pool</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>1</term>
/// <term>X</term>
/// <term>0/1</term>
/// <description>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</description>
/// </item>
/// <item>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>0</term>
/// <term>X</term>
/// <term>X</term>
/// <description>write entry with this radio address to pool and delete after timeOutPam is elapsed</description>
/// </item>
/// </list>
/// </summary>
public class P811
{
private readonly Byte[] bits;
public P811() => this.bits = new Byte[8];
private P811(Byte[] bits) => this.bits = bits;
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>module 2 is Wakeup Transmitter</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>module 1 is Wakeup Transmitter</description>
/// </item>
/// </list>
/// </summary>
public Boolean WakeUpModul
{
get => this.bits[0] == 1;
set => this.bits[0] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>first transmit Wakeup Sequence and afterwards normal PAM</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal PAM</description>
/// </item>
/// </list>
/// </summary>
public Boolean WakeUpCmd
{
get => this.bits[2] == 1;
set => this.bits[2] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>ignore timeout register for automatic delete of PAM</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>do nothing special</description>
/// </item>
/// </list>
/// </summary>
public Boolean IgnoreTimeout
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>delete entry from PAM pool after SEMI receipt</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>do nothing after SEMI receipt</description>
/// </item>
/// </list>
/// </summary>
public Boolean DelPamSemi
{
get => this.bits[4] == 1;
set => this.bits[4] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>delete entry from PAM pool after PAM transmit</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>do nothing after PAM transmit</description>
/// </item>
/// </list>
/// </summary>
public Boolean DelPamTx
{
get => this.bits[5] == 1;
set => this.bits[5] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>delete from PAM pool</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>write to PAM pool</description>
/// </item>
/// </list>
/// </summary>
public Boolean DelPamAdr
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>delete all entries from PAM pool</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>do nothing special</description>
/// </item>
/// </list>
/// </summary>
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());
}
}

View File

@ -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();
}
}

View File

@ -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;
/// <summary>
/// <list>
/// <item>
/// <term>value == 0</term>
/// <description>PAM will never automatically deleted</description>
/// </item>
/// <item>
/// <term>value != 0</term>
/// <description>duration after a PAM will be automatically deleted out of PAM-Pool, if no other rule deletes entry before</description>
/// </item>
/// </list>
/// <para>Several bits at parameter P81-1 or P81-2 may delete entry at PAM-Pool before 5 minutes elapsed. </para>
/// </summary>
public Byte Minutes { get; set; }
public static implicit operator Byte(PamTimeout param)
=> param.Minutes;
public static implicit operator PamTimeout(Byte _byte)
=> new PamTimeout(_byte);
}
}

View File

@ -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;
/// <summary>
/// 0 -> Transparent Mode at 115k2 Baud 8,n,1
/// </summary>
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);
}
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>external antenna</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>internal antenna</description>
/// </item>
/// </list>
/// </summary>
public Boolean Antenna
{
get => this.bits[4] == 1;
set => this.bits[4] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>Module not powered</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>Module powered</description>
/// </item>
/// </list>
/// </summary>
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());
}
}

View File

@ -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;
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>Bluetooth is output for non-requested messages</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>USB port is output for non-requested messages</description>
/// </item>
/// </list>
/// <para>non requested messages are received radio payloads if a radio module is switched on</para>
/// </summary>
public Boolean DataBtOut
{
get => this.bits[0] == 1;
set => this.bits[0] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>: if both RF-Modules are set to SensusRF Mode, both payloads of RF-Modules will be send out </description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>if both RF-Modules are set to SensusRF Mode, the channel with higher RSSI Level will be send out</description>
/// </item>
/// </list>
/// <para>for test purposes both receiver outputs can be shown - but remember Double traffic rate on Bluetoothor USB-output</para>
/// </summary>
public Boolean BothChsOut
{
get => this.bits[1] == 1;
set => this.bits[1] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>also payloads with incorrect radio-CRC will send out!</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal operation</description>
/// </item>
/// </list>
/// <para>may be only interesting for test purposes </para>
/// </summary>
public Boolean IgnoreCRC
{
get => this.bits[2] == 1;
set => this.bits[2] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>don't switch Power path off if going to USB Suspend and drawing more current as allowed</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>switch Power path off if going to USB Suspend</description>
/// </item>
/// </list>
/// <para>New at Version 1.0.0.6</para>
/// </summary>
public Boolean IgnoreUSBrules
{
get => this.bits[3] == 1;
set => this.bits[3] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>after "TIME_OFF" is elapsed without any command to SIRT, SIRT will be switched off</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal operation</description>
/// </item>
/// </list>
/// <para>timeout starts at beginning, if any command or communication to and from SIRT is initiated</para>
/// </summary>
public Boolean SirtPwrSave
{
get => this.bits[6] == 1;
set => this.bits[6] = (Byte)(value ? 1 : 0);
}
/// <summary>
/// <list>
/// <item>
/// <term>true</term>
/// <description>SIRT will be switched off {like push off button}</description>
/// </item>
/// <item>
/// <term>false</term>
/// <description>normal operation</description>
/// </item>
/// </list>
/// <para>
/// 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
/// </para>
/// </summary>
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());
}
}

View File

@ -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:
//

View File

@ -42,6 +42,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="IrdaSerialPort.cs" />
<Compile Include="JustSerialPort.cs" />
<Compile Include="SerialPortBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SerialPortBaudRate.cs" />

View File

@ -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<String, SerialPort> serialPorts
= new ConcurrentDictionary<String, SerialPort>();
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<String> 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);
}
}
}
}
}
}

View File

@ -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)
{

View File

@ -88,8 +88,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// </summary>
private static readonly List<String> _excludedFromCompareParameters = new List<String>
{
"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
};

View File

@ -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<GenesisStatus>(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

View File

@ -212,9 +212,6 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\..\.shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="DataTypes\Calibration.cs" />
<Compile Include="EventArguments\MagFluxFlowDataEventArgs.cs" />
<Compile Include="EventArguments\RequestResponseDataEventArgs.cs" />

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes
{

View File

@ -14,17 +14,17 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.MeasurementRecor
/// <summary>
/// Sensor Id of MagFlux
/// </summary>
public String SensorId;
public String SensorId { set; get; }
/// <summary>
/// Serial number of MagFlux
/// </summary>
public String UniqueId;
public String UniqueId { set; get; }
/// <summary>
/// Status of sensor and electronics
/// </summary>
public UInt32 StatusBits;
public UInt32 StatusBits { set; get; }
/// <summary>
/// String delimiter to separate elements in ToString() routine

View File

@ -1,7 +1,9 @@
using System;
using System.Xml;
// Ignore Spelling: lps
namespace XYLEM.Device
using System;
using XYLEM.Base;
namespace XYLEM
{
/// <summary>
/// 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)
{

View File

@ -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<CalibrationPoints>, IEquatable<CalibrationPoints>
@ -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)
{

View File

@ -0,0 +1,67 @@
using System;
using System.IO.Ports;
using XYLEM.Base.Config;
using XYLEM.Communication;
namespace XYLEM
{
/// <summary>
/// Command interface for MagFlux 6200
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft
/// </summary>
internal interface IMagFlux : IMagFluxRequestProtocol
{
#region When sharing same serial port
/// <summary>
/// Connect when using same serial port
/// </summary>
/// <param name="id"></param>
/// <param name="md_com"></param>
/// <returns></returns>
Boolean Connect(UInt16 id, ModbusCom md_com);
/// <summary>
/// Get current device com settings
/// </summary>
/// <returns></returns>
SerialPortSettingClass GetComSetting();
/// <summary>
/// Current modbus device device ID / address
/// </summary>
UInt16 Device_ID { get; }
#endregion
#region For stand alone use without sharing same serial port
#endregion
/// <summary>
/// Make communication connection to Meter
/// !!NOTE!! Only one meter is supported for each com port
/// </summary>
/// <param name="comport">Like "COM1"</param>
/// <param name="id">>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</param>
/// <returns>true on okay or false on error</returns>
Boolean Connect(string comport, UInt16 id = 1);
/// <summary>
/// Make communication connection to Meter with a specific communication setup
/// !!NOTE!! Only one meter is supported for each com port
/// </summary>
/// <param name="comport">>Like "COM1"</param>
/// <param name="id">>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</param>
/// <param name="baudRate">Like 9600 (default on RS485)</param>
/// <param name="parity">Like Parity.Even (default on RS485)</param>
/// <returns></returns>
Boolean Connect(string comport, UInt16 id, UInt32 baudRate, Parity parity);
/// <summary>
/// Close communication connection to Meter
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean CloseConnection();
}
}

View File

@ -0,0 +1,40 @@
using System.IO.Ports;
using XYLEM.Device;
namespace XYLEM
{
public interface IMagFluxAPI
{
/// <summary>
/// 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
///
/// </summary>
/// <param name="comport">Like "COM1"</param>
/// <param name="id">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</param>
/// <param name="log_path">folder path for where to log file should be saved</param>
/// <param name="runAs">RUN_TYPE.Normal with connection to serial port, if not set</param>
/// <returns>Return a MagFlux device or "null" if failing connect</returns>
IMagFluxRequestProtocol Connect(string comport, ushort id = 1, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal);
/// <summary>
/// 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
///
/// </summary>
/// <param name="comport">>Like "COM1"</param>
/// <param name="id">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</param>
/// <param name="baudRate">Like 9600 (default on RS485)</param>
/// <param name="parity">Like Parity.Even (default on RS485)</param>
/// <param name="log_path">folder path for where to log file should be saved</param>
/// <param name="runAs">RUN_TYPE.Normal with connection to serial port, if not set</param>
/// <returns>Return a MagFlux device or "null" if failing connect</returns>
/// <exception cref="InvalidDataException"> if the configuration is not valid</exception>
IMagFluxRequestProtocol Connect(string comport, ushort id, uint baudRate, Parity parity, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal);
}
}

View File

@ -0,0 +1,374 @@
using System;
using System.Collections.Generic;
using XYLEM.Base;
namespace XYLEM
{
/// <summary>
/// Command interface for MagFlux
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft
/// </summary>
public interface IMagFluxRequestProtocol
{
/// <summary>
/// Is connected
/// </summary>
/// <returns>true if yes</returns>
Boolean IsConnected();
/// <summary>
/// Get current device Modbus ID / Device Address
/// </summary>
/// <param name="value_out">1-246</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDeviceID(out int value_out);
/// <summary>
/// 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
/// </summary>
/// <param name="id_to_check"></param>
/// <returns>Return True if no device was responding on ID</returns>
Boolean IsDeviceID_Free(uint id_to_check);
/// <summary>
/// Set current device Modbus ID / Device Address
/// </summary>
/// <param name="value_out">1-246 (Don't use device ID 247, it is a MJK broad cast)</param>
/// <returns>true on okay or false on error</returns>
/// 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);
/// <summary>
/// Get printout of communication counters
/// </summary>
/// <returns></returns>
string GetComCounters();
/// <summary>
/// Set location for where log data can saved.
/// </summary>
/// <param name="path">path for where to log file should be saved</param>
/// <param name="filename">set a custom log file name without extension (ex. "UserCustomLogFile") or null if use default</param>
/// <returns>true on okay or false on error</returns>
Boolean SetLogLocation(String path, string filename = null);
/// <summary>
/// Open saved log file
/// </summary>
void OpenLogFile();
/// <summary>
/// Get latest log added to log file while this program was running
/// </summary>
/// <param name="from">How long to go back after log messages, if Null then standard 1 minute</param>
/// <returns>"Lasted" Log messages Queue After last connection</returns>
List<LogMessage> GetLatestLogs(DateTime? from = null);
/// <summary>
/// Unique-ID for the MagFlux electronics
/// </summary>
/// <param name="value_out">a hex decimal string 0x1234ABCDEF or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetUniqueId(out string value_out);
/// <summary>
/// MagFlux metrology board serial number
/// More info on:
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers
/// </summary>
/// <param name="value_out">a serial number ex. 510360.00000105W46Y23 or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetBoardSerialNo(out string value_out);
/// <summary>
/// MagFlux metrology board serial number
/// More info on:
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers
/// </summary>
/// <param name="new_serial_number">a serial number ex. 510360.00000105W46Y23</param>
/// <returns>true on okay or false on error</returns>
Boolean SetBoardSerialNo(string new_serial_number);
/// <summary>
/// Get the firmware version
/// </summary>
/// <param name="value_out">like 1.2.4 (MAJOR.MINOR.REVISION)</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFirmwareVersion(out string value_out);
/// <summary>
/// Get Current device register version
/// </summary>
/// <param name="value_out">like "51" or on connecting error "?", "0", "-1" </param>
/// <returns>true on okay or false on error</returns>
Boolean GetRegisterVersion(out string value_out);
/// <summary>
/// Get Current communication register version used by the interface
/// </summary>
/// <param name="value_out">like "51" or on error "?", "0", "-1" </param>
/// <returns>true on okay or false on error</returns>
Boolean GetAPIRegisterVersion(out string value_out);
/// <summary>
/// Get the firmware build date
/// </summary>
/// <param name="value_out">like 2022/12/24 13:00:00 or 2022-12-24 13:45:10</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwBuildDate(out string value_out);
/// <summary>
/// Git Hash to Unique identify firmware
/// </summary>
/// <param name="value_out">like 0xABCDE123</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwGitHash(out string value_out);
/// <summary>
/// Get Device runtime after Last reset
/// </summary>
/// <param name="value_out">Time since last device reset in seconds</param>
/// <returns></returns>
Boolean GetRuntimeAfterLastReset_sec(out UInt32 value_out);
/// <summary>
/// Flow rate calibrated
/// </summary>
/// <param name="value_out"> Actual flow rate [l/s] </param>
/// <returns>true on okay or false on error</returns>
Boolean GetFlowRate_lps(out Single value_out);
/// <summary>
/// !!! 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.
/// </summary>
/// <param name="value_lps">The fixed flow to force MagFlux to output [l/s] </param>
/// <returns>true on okay or false on error</returns>
Boolean SetSimulatedFlow_lps(double value_lps);
/// <summary>
/// Get the correction factor from board "1.0000" is default none calibration board
/// </summary>
/// <param name="value_out"></param>
/// <returns>true on okay or false on error</returns>
Boolean GetElectrodeBoardCorrectionFactor(out Single value_out);
/// <summary>
/// Get Empty pipe control bits
/// Bit0="EPD disabled", 1="Enabled w. Flags only", 2="EPD enabled full"
/// </summary>
/// <param name="epd_cntl_bits">empty pipe control bits</param>
/// <returns>true on okay or false on error</returns>
Boolean GetEmptyPipeControl(out Int32 epd_cntl_bits);
/// <summary>
/// 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
/// </summary>
/// <returns>Default is currently True and will be set True on each connect (In the future when Empty pipe works it will be default false)</returns>
Boolean GetIgnoreFailOnEmptyPipeOnHealthy();
/// <summary>
/// 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
/// </summary>
/// <param name="doIgnore">True to ignore empty pipe warning</param>
void SetIgnoreFailOnEmptyPipeOnHealthy(Boolean doIgnore);
/// <summary>
/// !!! 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
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean SetPCBToDemoDefaults();
/// <summary>
/// Is the fixed test flow active
/// Used for getting a fixed simulated flow from MagFlux
/// </summary>
/// <returns>true if ON</returns>
Boolean IsSimulatedFlowActive();
/// <summary>
/// Turn on/off fixed test flow output from MagFlux
/// Used for getting a fixed simulated flow from MagFlux
/// </summary>
/// <param name="testFlowOn"></param>
/// <returns>true on okay or false on error</returns>
Boolean SetSimulatedFlowActive(Boolean testFlowOn);
/// <summary>
/// Total forward volume (Positive flow volume totalizator)
/// </summary>
/// <param name="value_out">volume in in liter [l]</param>
/// <returns>true on okay or false on error</returns>
Boolean GetForwardVolume_l(out Double value_out);
/// <summary>
/// Total backward volume (Reversed or negative flow volume totalizator)
/// </summary>
/// <param name="value_out"></param>
/// <returns>true on okay or false on error</returns>
Boolean GetBackwardVolume_l(out Double value_out);
/// <summary>
/// Get the general sensor information
/// </summary>
/// <param name="value_out">sensor information</param>
/// <returns>true on okay or false on error</returns>
Boolean GetSensorInfo(out SensorInfo value_out);
/// <summary>
/// MagFlux Sensor serial number
/// </summary>
/// <param name="value_out">a decimal serial number ex. 12345678 or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetSensorSerialNo(out string value_out);
/// <summary>
/// Set MagFlux Sensor serial number
/// </summary>
/// <param name="new_serial_number"></param>
/// <returns>true on okay or false on error</returns>
Boolean SetSensorSerialNo(UInt64 new_serial_number);
/// <summary>
/// MagFlux Sensor nominal DN size in millimeters
/// </summary>
/// <param name="dn_mm_out">DN size in [mm] is -1 on error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDn_mm(out Int32 dn_mm_out);
/// <summary>
/// Set Sensor nominal DN size in millimeters
/// </summary>
/// <param name="new_dn_mm">DN size in [mm] ex 50 is 50mm or DN50</param>
/// <returns>true on okay or false on error</returns>
Boolean SetDn_mm(UInt16 new_dn_mm);
/// <summary>
/// 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"
/// </summary>
/// <param name="flangeType_out">Flange type number</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFlangeType(out Int32 flangeType_out);
/// <summary>
/// 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"
/// </summary>
/// <param name="new_flangeType">Flange type number</param>
/// <returns>true on okay or false on error</returns>
Boolean SetFlangeType(UInt16 new_flangeType);
/// <summary>
/// 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.
/// </summary>
/// <param name="pls_vol_ml">A pulse volume in [ml] (milliliter)</param>
/// <returns>true on okay or false on error</returns>
Boolean GetVolumePerPulse_ml(out UInt32 pls_vol_ml);
/// <summary>
/// Set what volume per pulse for both forward and reverse counter is
/// </summary>
/// <param name="pls_vol_ml">A pulse volume in [ml] (milliliter)</param>
/// <returns>true on okay or false on error</returns>
Boolean SetVolumePerPulse_ml(UInt32 pls_vol_ml);
/// <summary>
/// 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.
/// </summary>
/// <param name="pls_Ton_ms">A pulse turn on time in ms (millisecond) Note setting to 0 will result in pulse time be as fast as device support</param>
/// <returns>true on okay or false on error</returns>
Boolean GetPulseOutput_Ton_ms(out UInt16 pls_Ton_ms);
/// <summary>
/// Set what pulse turn on time for both forward and reverse counter is
/// </summary>
/// <param name="pls_vol_ml">A pulse turn on time in ms (millisecond)</param>
/// <returns>true on okay or false on error</returns>
Boolean SetPulseOutput_Ton_ms(UInt16 pls_Ton_ms);
/// <summary>
/// Check if there is problem with the DUT
/// use <see cref="GetDeviceErrorMessages"/>" to get a list of error messages for debug problems
/// </summary>
/// <returns>>true if device operates correctly</returns>
Boolean GetDeviceHealthy();
/// <summary>
/// get a list of error messages for debug problem
/// </summary>
/// <param name="status_list_out">Will return a empty list if there is no messages to return</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDeviceErrorMessages(out List<string> status_list_out);
/// <summary>
/// This function prepares the DUT for the calibration.
///
/// ATTENTION:
/// This function needs to be called before the calibration process starts any flow of water.
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean PrepareDeviceForCalibration();
/// <summary>
/// This function will abort started or failed calibration to bring DUT back to normal calibration state
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean AbortDeviceForCalibration();
/// <summary>
/// The maximum calibration points that is supported by the device
/// </summary>
/// <returns>number of points possible to get and set in device</returns>
int GetCalibrationPointsMax();
/// <summary>
/// Get list of calibration points saved in DUT
/// </summary>
/// <param name="values_read">The calibrations points from device</param>
/// <returns>true on okay or false on error</returns>
Boolean GetCalibrationPoints(out CalibrationPoints values_read);
/// <summary>
/// set calibration in DUT.
/// Remember to run <see cref="PrepareDeviceForCalibration"/> before the calibration process is started.
/// </summary>
/// <param name="new_calibration_points">A list of calibration points to write to DUT</param>
/// <returns>true on okay or false on error</returns>
Boolean SetCalibrationPoints(CalibrationPoints new_calibration_points);
}
}

View File

@ -0,0 +1,90 @@
using System;
namespace XYLEM
{
public class SensorInfo
{
/// <summary>
///Sensor serial number ex. 0x1234ABCDEF or 0 as unknown / not defined
/// </summary>
public UInt64 SerialNumber { get; private set; }
/// <summary>
/// MagFlux Sensor nominal DN size in millimeters
/// </summary>
public Int32 DN_mm { get; private set; }
/// <summary>
/// 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"
/// </summary>
public Int32 FlangeType { get; private set; }
/// <summary>
/// Calibration method was used. 0 is default, for calibration on flow rig for 5 min per point
/// </summary>
public Int32 CalibrationVersion { get; private set; }
/// <summary>
/// Sampling scheme code used by front end measurement. //NL// 0=32/40, 1=20/40
/// </summary>
public Int32 SamplingSchemeCode { get; private set; }
/// <summary>
/// Coil driver frequency, 0 = 0.625Hz, 1= 1.25Hz, 2 = 2.5Hz, 3 = 5Hz, 4 = 10Hz,
/// </summary>
public Int32 CoilDriverFrequencyConfig { get; private set; }
/// <summary>
/// Number of calibration points
/// The same as calling "Calibration.Get_number_of_calibrations()"
/// </summary>
public Int32 NumberOfCalibrations { get; private set; }
/// <summary>
/// List of calibration points saved in DUT
/// </summary>
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;
}
}
}

View File

@ -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
{

View File

@ -57,5 +57,15 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Interfaces\Ports\PortCore\PortCore.csproj">
<Project>{2E139F63-B6FE-4EA9-A098-85364FE9B26C}</Project>
<Name>PortCore</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Interfaces\Protocols\TransmitProtocol\TransmitProtocol.csproj">
<Project>{63E0AC5E-B7C8-4363-A2FE-BE489E648FF0}</Project>
<Name>TransmitProtocol</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -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")]

View File

@ -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<String> GetInfoOfAllErrorStates()
{
var errorStateInfos = (from state in _stateContainer where state.State
!= State.Okay select state.Info).ToList();
!= State.Okay select state.Info).ToList();
return errorStateInfos;
}

View File

@ -5,7 +5,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.Consts
/// <summary>
/// Concatenation between final test state and text
/// </summary>
struct StateStruct
internal struct StateStruct
{
/// <summary>
/// Assign state information tas text for state

View File

@ -106,7 +106,42 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore
} = "?";
/// <summary>
/// Represent pcb serial number
/// Represent MagFlux API Version
/// </summary>
public String MagFluxRegisterApiVersion
{
get;
private set;
} = "?";
/// <summary>
/// Represent sensor serial number
/// </summary>
public String SensorSerialNo
{
get; private set;
}
/// <summary>
/// Represents Empty Pipe Detection control bits
/// Bit0="EPD disabled", 1="Enabled w. Flags only", 2="EPD enabled full"
/// </summary>
public Int32 EpdControlBits
{
get; private set;
}
/// <summary>
/// Represent pcb calibration
/// </summary>
public Single BoardCalib
{
get; private set;
}
/// <summary>
/// Represent pcb identification
/// </summary>
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();
}
///// <summary>
///// Turn on/off fixed test flow output from MagFlux
///// Used for getting a fixed simulated flow from MagFlux
///// </summary>
///// <param name="testFlowOn"></param>
///// <returns>true on okay or false on error</returns>
//public Boolean SetSimulatedFlowActive(Boolean testFlowOn)
//{
// _logger.Info($"Slot:{Slot} - Set test flow");
// return RequestProtocol.SetSimulatedFlowActive(on);
//}
///// <summary>
///// Is the fixed test flow active
///// Used for getting a fixed simulated flow from MagFlux
///// </summary>
///// <returns>true if ON</returns>
//public Boolean IsSimulatedFlowActive()
//{
// _logger.Info($"Slot:{Slot} - Get test flow setting");
// return RequestProtocol.IsSimulatedFlowActive();
//};
/// <summary>
/// Set PCB settings and PCB calibrations to default.
/// </summary>
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;
}
/// <summary>
/// Set a new meter size to MagFlux
/// </summary>
@ -1031,14 +1117,14 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore
}
/// <summary>
/// Set a new pcbId to MagFlux
/// Set a new sensor serial number to MagFlux
/// </summary>
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();
}
/// <inheritdoc />
/// <inheritdoc />
public void SetLcdText(Boolean release, Byte[] textInHex)
{
throw new NotImplementedException();

View File

@ -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")]

View File

@ -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")]

View File

@ -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<Calibration> _calibPointsCmPerH;
/// <inheritdoc />
/// <remarks date="2024-Aug-12" author="T.Wiedebusch">
/// - MagFluxApi
/// </remarks>
public RequestProtocol(String ident) : base(ident)
{
_ident = ident;
_magFluxRequestProtocol = new MagFlux6200();
_magFluxApi = new MagFluxAPI();
_calibPointsCmPerH = new List<Calibration>();
_logger = NLogHelper.CreateOrGetMultiLogger(_ident, "", "RequestProtocol", "MeterBase", "MeterBase");
_logger = NLogHelper.CreateOrGetMultiLogger(_ident, "", "RequestProtocol", "MeterBase",
"MeterBase");
}
/// <inheritdoc/>>
/// <remarks date="2024-Aug-12" author="T.Wiedebusch">
/// - MagFluxApi
/// </remarks>
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();
}
/// <summary>
/// Wrapper to connect MagFlux
/// </summary>
/// <returns></returns>
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to connect MagFlux
/// </summary>
@ -77,13 +71,23 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// - Initial
/// </remarks>
/// <remarks date="2024-Aug-12" author="T.Wiedebusch">
/// - MagFluxApi
/// </remarks>
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
}
/// <summary>
/// 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
/// </summary>
/// <returns></returns>
/// <remarks date="2024-Aug-20" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
///// <summary>
///// Wrapper to get the simulated flow setting
///// </summary>
///// <returns></returns>
///// <remarks date="2024-Aug-23" author="T.Wiedebusch">
///// - Initial
///// </remarks>
//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;
//}
///// <summary>
///// Wrapper to set the simulated flow setting
///// </summary>
///// <param name="on">true to ignore state</param>
///// <returns></returns>
///// <remarks date="2024-Aug-23" author="T.Wiedebusch">
///// - Initial
///// </remarks>
//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;
//}
///// <summary>
///// Wrapper to get the ignore empty pipe mode status
///// </summary>
///// <returns></returns>
///// <remarks date="2024-Aug-23" author="T.Wiedebusch">
///// - Initial
///// </remarks>
//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;
//}
///// <summary>
///// Wrapper to set the ignore empty pipe mode
///// </summary>
///// <param name="on">true to ignore state</param>
///// <returns></returns>
///// <remarks date="2024-Aug-23" author="T.Wiedebusch">
///// - Initial
///// </remarks>
//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;
//}
/// <summary>
/// Wrapper to get the empty pipe bits
/// </summary>
/// <param name="epd_cntl_bits"></param>
/// <returns></returns>
/// <remarks date="2024-Aug-20" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to get the board calibration value
/// </summary>
/// <param name="value_out"></param>
/// <returns></returns>
/// <remarks date="2024-Aug-20" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to get the sensor serial number
/// </summary>
/// <param name="sensorSerialNo"></param>
/// <returns></returns>
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to get the PcbId
/// </summary>
/// <param name="pcbId"></param>
/// <returns></returns>
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// <remarks date="2024-Aug-15" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to set the PcbId which equals the sensor serial number
/// Wrapper to set the sensor serial number
/// </summary>
/// <param name="pcbId"></param>
/// <param name="sensorSerialNo"></param>
/// <returns></returns>
/// <remarks date="2023-Nov-02" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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;
}
/// <summary>
/// Wrapper to get unique id referenced as PCBID
/// </summary>
@ -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;
}
/// <summary>
/// Wrapper to get FW Build Date
/// </summary>
@ -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;
}
/// <summary>
/// Wrapper to get API register version of MagFlux
/// </summary>
/// <param name="apiRegisterVersion"></param>
/// <returns></returns>
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// - Initial
/// </remarks>
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
/// <remarks date="2023-Mai-04" author="T.Wiedebusch">
/// - Initial
/// </remarks>
/// <remarks date="2024-Aug-26" author="T.Wiedebusch">
/// - Corrected logic, if !IsConnected = connection is closed
/// </remarks>
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;
}
}

View File

@ -31,9 +31,15 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="magflux_api">
<HintPath>..\..\MagFluxApi\magflux_api.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\packages\NLog.5.2.2\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="shared_code">
<HintPath>..\..\MagFluxApi\shared_code.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
@ -53,10 +59,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\modbus_master_csharp\modbus_master_csharp.csproj">
<Project>{F14940F8-3C86-4BB7-A915-B021E4B3052D}</Project>
<Name>modbus_master_csharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\Utils\Logging\Logging.csproj">
<Project>{4B88B0D3-E791-4774-9521-EABEACDC420E}</Project>
<Name>Logging</Name>

View File

@ -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")]

View File

@ -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;
/// <summary>
@ -72,19 +72,21 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol
/// <summary>
/// Set decoding mask for streaming protocol, wipes out all not matching records:
/// - PcbIdMask equals the sensor serial no
/// - SensorIdMask,
/// - UniqueIdMask
/// </summary>
/// <param name="pcbIdMask"></param>
/// <param name="sensorIdMask"></param>
/// <param name="uniqueIdMask"></param>
/// <returns>true if decoding was successful and data has been validated</returns>
/// <remarks date="2023-Mai-30" author="T.Wiedebusch">
/// - Initial.
/// </remarks>
public void SetDecodingMask(String pcbIdMask, String uniqueIdMask)
/// <remarks date="2024-Aug-19" author="T.Wiedebusch">
/// - Changed from PcbId to SensorId.
/// </remarks>
public void SetDecodingMask(String sensorIdMask, String uniqueIdMask)
{
// the pcbId equals the sensorSn
_pcbIdMask = pcbIdMask;
_sensorIdMask = sensorIdMask;
_uniqueIdMask = uniqueIdMask;
}
/// <summary>
@ -98,6 +100,9 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol
/// <remarks date="2023-May-25" author="T.Wiedebusch">
/// - Introduced reverse volume.
/// </remarks>
/// <remarks date="2024-Aug-19" author="T.Wiedebusch">
/// - Changed from PcbId to SensorId.
/// </remarks>
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;

View File

@ -19,7 +19,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol
/// </summary>
private StreamingDecoder _streamingDecode;
private readonly Boolean _ignoreCorruptedData;
private String _pcbIdMask;
private String _sensorIdMask;
private String _uniqueIdMask;
/// <inheritdoc />
@ -30,16 +30,18 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.StreamingProtocol
/// - PcbIdMask equals the sensor serial no
/// - UniqueIdMask
/// </summary>
/// <param name="pcbIdMask"></param>
/// <param name="sensorIdMask"></param>
/// <param name="uniqueIdMask"></param>
/// <returns>true if decoding was successful and data has been validated</returns>
/// <remarks date="2023-Mai-30" author="T.Wiedebusch">
/// - Initial.
/// </remarks>
public void SetDecodingMask(String pcbIdMask, String uniqueIdMask)
/// <remarks date="2024-Aug-19" author="T.Wiedebusch">
/// - Changed from PcbId to SensorId.
/// </remarks>
public void SetDecodingMask(String sensorIdMask, String uniqueIdMask)
{
// the pcbId equals the sensorSn
_pcbIdMask = pcbIdMask;
_sensorIdMask = sensorIdMask;
_uniqueIdMask = uniqueIdMask;
}
/// <inheritdoc />
@ -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

View File

@ -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;

View File

@ -1 +1 @@
c43c40a030005a8f189e6179faf40a6d42bfef5c
89102b0142e574de38a9f47d370f3334e5e6c268

View File

@ -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);
/// <summary>
/// Change from Production Mode to Shipment Mode. 1 = Shipment
/// </summary>

View File

@ -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;
}
}
}

View File

@ -5,7 +5,5 @@
public SetAlarms() : base(2, DebugCmd.SetAlarms)
{
}
public static implicit operator DebugCmd(SetAlarms alarms) => alarms.bytes;
}
}

View File

@ -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);
}
}
/// <summary>
@ -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();
}

View File

@ -50,31 +50,37 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="ACKN.cs" />
<Compile Include="AppCode.cs" />
<Compile Include="BUP.cs" />
<Compile Include="DEBUG.cs" />
<Compile Include="Endpoint.cs" />
<Compile Include="Data\ACKN.cs" />
<Compile Include="Data\AppCode.cs" />
<Compile Include="Data\BUP.cs" />
<Compile Include="Data\DEBUG.cs" />
<Compile Include="ParameterSet.cs" />
<Compile Include="ProgrammingBatch.cs" />
<Compile Include="EndpointTask.cs" />
<Compile Include="Epoch20000101.cs" />
<Compile Include="LAT.cs" />
<Compile Include="MeterUnits.cs" />
<Compile Include="PAMStatus.cs" />
<Compile Include="Payload.cs" />
<Compile Include="ProgrammingTask.cs" />
<Compile Include="JustTask.cs" />
<Compile Include="TaskState.cs" />
<Compile Include="Data\Epoch20000101.cs" />
<Compile Include="Data\LAT.cs" />
<Compile Include="Data\MeterUnits.cs" />
<Compile Include="Data\Payload.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SEMI.cs" />
<Compile Include="Data\SEMI.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Utils\Common.Utils.Extensions\Common.Utils.Extensions.csproj">
<Project>{05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3}</Project>
<Name>Common.Utils.Extensions</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.SIRT.csproj">
<ProjectReference Include="..\..\..\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SirtBroadcaster\Common.Hardware.Interfaces.Ports.SirtBroadcaster.csproj">
<Project>{F408DE9E-01E6-4CFF-AE79-B572B0674FA2}</Project>
<Name>Common.Hardware.Interfaces.Ports.SirtBroadcaster</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Interfaces\Ports\Common.Hardware.Interfaces.Ports.SIRT\Common.Hardware.Interfaces.Ports.Sirt.csproj">
<Project>{B23BFAF9-08AE-4311-8C08-FB2BB49EA2AD}</Project>
<Name>Common.Hardware.Interfaces.Ports.SIRT</Name>
<Name>Common.Hardware.Interfaces.Ports.Sirt</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Interfaces\Ports\Common.Hardware.Interfaces.Ports\Common.Hardware.Interfaces.Ports.csproj">
<Project>{9AE071C0-DB12-4E09-A3C7-43F6DCD518D6}</Project>

View File

@ -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;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.WaterMeter.eRegister
namespace Common.Hardware.WaterMeter.eRegister.Data
{
public enum AppCode
{

View File

@ -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;

View File

@ -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; }
/// <summary>
/// Min: 3.565
/// </summary>
public Double BatteryVoltage { get; }
public Byte WakeupInterval { get; }
@ -111,19 +113,37 @@
/// Bits 8-11 Minor Version
/// Bits 0-7 Patch Version
/// </summary>
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}";
}
}
}

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.WaterMeter.eRegister
namespace Common.Hardware.WaterMeter.eRegister.Data
{
using System;

View File

@ -1,4 +1,4 @@
namespace Common.Hardware.WaterMeter.eRegister
namespace Common.Hardware.WaterMeter.eRegister.Data
{
using System;

View File

@ -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,

View File

@ -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)
{

View File

@ -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}%)";
}
}
}

View File

@ -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<Byte[]> commands;
private Int32 remeiningTasks;
private EndpointTask checksTask;
public Endpoint(ILogger logger)
{
this.logger = logger;
this.commands = new Queue<Byte[]>();
}
public event Action<Int32> 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);
}
}
}
}

View File

@ -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<String> Received;
public override UInt32 Address => base.Address;
public String KEY
{
get => BitConverter.ToString(this.key);
set => this.key = value.GetBytes();
}
public ICollection<ACKN> ACKNS { get; private set; } = new List<ACKN>();
public ICollection<LAT> LATS { get; private set; } = new List<LAT>();
public ICollection<DEBUG> DEBUGS { get; private set; } = new List<DEBUG>();
public ICollection<SEMI> SEMIS { get; } = new List<SEMI>();
public ICollection<BUP> BUPS { get; } = new List<BUP>();
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();
}
}

View File

@ -0,0 +1,33 @@
namespace Common.Hardware.WaterMeter.eRegister
{
using System;
using System.Linq;
public class JustTask
{
public event Action<Int32, Int32, String, TaskState> 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<ParameterSet, Tuple<String, TaskState>> TaskHandler { get; internal set; }
public Action<Int32, Int32, String, TaskState> ProgressHandler
{
get => (Action<Int32, Int32, String, TaskState>)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);
}
}
}

Some files were not shown because too many files have changed in this diff Show More