omni progress
This commit is contained in:
+7
-211
@@ -171,27 +171,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataPackages", "Hardware\Wa
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolCore", "Hardware\Interfaces\Protocols\ProtocolCore\ProtocolCore.csproj", "{8BDD2789-96D4-43EA-AAD7-0F49D0347998}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SIRTBroadcaster.Abstraction", "SIRTBroadcaster.Abstraction\SIRTBroadcaster.Abstraction.csproj", "{C27BA66C-C3A7-48A2-A644-CBA77E28E531}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SIRTBroadcaster.Client", "SIRTBroadcaster.Client\SIRTBroadcaster.Client.csproj", "{4221F992-599E-498C-A409-6D1E70E0A6F9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SIRT", "SIRT", "{AF973E0E-2B44-4F1A-B1E7-77C8B4F30579}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SIRTBroadcaster.Host", "SIRTBroadcaster.Host\SIRTBroadcaster.Host.csproj", "{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaProduction", "LaaProduction\LaaProduction.csproj", "{FD30EB7A-7809-4E62-9374-791D31877D6D}"
|
||||
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", "{D1CAF04E-407D-4F01-B588-54815EA88B0D}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OmniPlus", "OmniPlus", "{68323534-4337-4E3A-89BC-11D8BB55343A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NamedPipes", "..\..\..\..\Desktop\OmniPlus\NamedPipes\NamedPipes.csproj", "{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NamedPipes", "NamedPipes\NamedPipes.csproj", "{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus", "..\..\..\..\Desktop\OmniPlus\OmniPlus\OmniPlus.csproj", "{F8D84B9A-0FCF-4083-B067-8C39B7314152}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus", "OmniPlus\OmniPlus.csproj", "{F8D84B9A-0FCF-4083-B067-8C39B7314152}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus.UI", "..\..\..\..\Desktop\OmniPlus\OmniPlus.UI\OmniPlus.UI.csproj", "{6518211A-E83F-4171-97C4-A61FCF66D6E0}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus.UI", "OmniPlus.UI\OmniPlus.UI.csproj", "{6518211A-E83F-4171-97C4-A61FCF66D6E0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
@@ -3939,198 +3931,6 @@ Global
|
||||
{8BDD2789-96D4-43EA-AAD7-0F49D0347998}.XP32bit|x64.Build.0 = XP32bit|x64
|
||||
{8BDD2789-96D4-43EA-AAD7-0F49D0347998}.XP32bit|x86.ActiveCfg = XP32bit|x86
|
||||
{8BDD2789-96D4-43EA-AAD7-0F49D0347998}.XP32bit|x86.Build.0 = XP32bit|x86
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.COM|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.PerformTest|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.ReleaseTest|x86.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|Any CPU.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|x64.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|x64.Build.0 = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|x86.ActiveCfg = Release|Any CPU
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531}.XP32bit|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.COM|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.PerformTest|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.ReleaseTest|x86.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|Any CPU.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|x64.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|x64.Build.0 = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|x86.ActiveCfg = Release|Any CPU
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9}.XP32bit|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.COM|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.PerformTest|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.ReleaseTest|x86.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|x64.Build.0 = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}.XP32bit|x86.Build.0 = Release|Any CPU
|
||||
{FD30EB7A-7809-4E62-9374-791D31877D6D}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD30EB7A-7809-4E62-9374-791D31877D6D}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD30EB7A-7809-4E62-9374-791D31877D6D}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
@@ -4592,16 +4392,12 @@ Global
|
||||
{D6B81C60-2763-4C4D-989F-90822F53B01A} = {94579693-7AC6-4FF0-B540-1F3780E1BCFA}
|
||||
{BA17D20E-0CEB-4B27-9772-2392BD750ED5} = {C9393A97-C0BB-4D59-A879-B572BE04CE15}
|
||||
{8BDD2789-96D4-43EA-AAD7-0F49D0347998} = {EC10DAFE-88CF-42D5-99E7-D247938B6430}
|
||||
{C27BA66C-C3A7-48A2-A644-CBA77E28E531} = {AF973E0E-2B44-4F1A-B1E7-77C8B4F30579}
|
||||
{4221F992-599E-498C-A409-6D1E70E0A6F9} = {AF973E0E-2B44-4F1A-B1E7-77C8B4F30579}
|
||||
{AF973E0E-2B44-4F1A-B1E7-77C8B4F30579} = {99B23EE9-CE50-4924-A055-C39EFA038721}
|
||||
{A9D1A99D-6E55-4394-86AD-B5C53E9225EB} = {AF973E0E-2B44-4F1A-B1E7-77C8B4F30579}
|
||||
{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}
|
||||
{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19} = {D1CAF04E-407D-4F01-B588-54815EA88B0D}
|
||||
{F8D84B9A-0FCF-4083-B067-8C39B7314152} = {D1CAF04E-407D-4F01-B588-54815EA88B0D}
|
||||
{6518211A-E83F-4171-97C4-A61FCF66D6E0} = {D1CAF04E-407D-4F01-B588-54815EA88B0D}
|
||||
{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19} = {68323534-4337-4E3A-89BC-11D8BB55343A}
|
||||
{F8D84B9A-0FCF-4083-B067-8C39B7314152} = {68323534-4337-4E3A-89BC-11D8BB55343A}
|
||||
{6518211A-E83F-4171-97C4-A61FCF66D6E0} = {68323534-4337-4E3A-89BC-11D8BB55343A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Pipes;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace NamedPipes
|
||||
{
|
||||
public abstract class NamedPipe
|
||||
{
|
||||
protected const string PIPE_NAME = "NamedPipes";
|
||||
protected const byte FLOW_REQUEST = 1;
|
||||
protected const byte DATA_REQUEST = 2;
|
||||
protected const byte MSG_LENGTH = 9;
|
||||
|
||||
protected PipeStream pipe;
|
||||
|
||||
private readonly BackgroundWorker worker;
|
||||
|
||||
public NamedPipe()
|
||||
{
|
||||
this.worker = new BackgroundWorker();
|
||||
this.worker.DoWork += this.Run;
|
||||
}
|
||||
|
||||
public event Action Connected;
|
||||
public event Action Disconnected;
|
||||
public event Action<double> DataRequest;
|
||||
public event Action<double> FlowRequest;
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
this.pipe?.Dispose();
|
||||
this.worker?.Dispose();
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
=> this.worker.RunWorkerAsync();
|
||||
|
||||
public double RequestReference()
|
||||
{
|
||||
var completed = false;
|
||||
var reference = 0D;
|
||||
var timeout = 60_000;
|
||||
var delay = 1000;
|
||||
|
||||
void DataRequested(double val)
|
||||
{
|
||||
completed = true;
|
||||
reference = val;
|
||||
}
|
||||
|
||||
this.DataRequest += DataRequested;
|
||||
|
||||
this.SendMessage(reference, DATA_REQUEST);
|
||||
|
||||
while (!completed && timeout > 0)
|
||||
{
|
||||
Thread.Sleep(delay);
|
||||
|
||||
timeout -= delay;
|
||||
}
|
||||
|
||||
this.FlowRequest -= DataRequested;
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
public void RequestFlowRate(double value)
|
||||
{
|
||||
var completed = false;
|
||||
var timeout = 60_000;
|
||||
var delay = 1000;
|
||||
|
||||
void FlowRequested(double _) => completed = true;
|
||||
|
||||
this.FlowRequest += FlowRequested;
|
||||
|
||||
this.SendMessage(value, FLOW_REQUEST);
|
||||
|
||||
while (!completed && timeout > 0)
|
||||
{
|
||||
Thread.Sleep(delay);
|
||||
|
||||
timeout -= delay;
|
||||
}
|
||||
|
||||
this.FlowRequest -= FlowRequested;
|
||||
}
|
||||
|
||||
protected void SendMessage(double value, byte endpoint)
|
||||
{
|
||||
if (this.pipe.IsConnected)
|
||||
{
|
||||
var message = new byte[MSG_LENGTH];
|
||||
message[0] = endpoint;
|
||||
|
||||
BitConverter
|
||||
.GetBytes(value)
|
||||
.CopyTo(message, 1);
|
||||
|
||||
this.pipe.Write(message, 0, message.Length);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Run(object sender, DoWorkEventArgs args)
|
||||
{
|
||||
this.Connected?.Invoke();
|
||||
|
||||
var buffer = new byte[byte.MaxValue];
|
||||
|
||||
while (this.pipe.IsConnected)
|
||||
{
|
||||
var asyncResult = this.pipe.BeginRead(buffer, 0, byte.MaxValue, this.EndRead, buffer);
|
||||
|
||||
if (asyncResult.AsyncWaitHandle.WaitOne())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.pipe.IsConnected)
|
||||
{
|
||||
this.Disconnected?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
if (this.pipe.IsConnected && asyncResult.AsyncState is byte[] buffer)
|
||||
{
|
||||
var readLength = this.pipe.EndRead(asyncResult);
|
||||
|
||||
if (readLength > 0 && buffer.Length >= readLength)
|
||||
{
|
||||
var value = BitConverter.ToDouble(buffer, 1);
|
||||
|
||||
switch (buffer[0])
|
||||
{
|
||||
case FLOW_REQUEST: this.FlowRequest?.Invoke(value); break;
|
||||
case DATA_REQUEST: this.DataRequest?.Invoke(value); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Pipes;
|
||||
|
||||
namespace NamedPipes
|
||||
{
|
||||
public class NamedPipeClient : NamedPipe
|
||||
{
|
||||
protected override void Run(object sender, DoWorkEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pipe = new NamedPipeClientStream(
|
||||
serverName: ".",
|
||||
pipeName: PIPE_NAME,
|
||||
direction: PipeDirection.InOut,
|
||||
options: PipeOptions.Asynchronous);
|
||||
this.pipe = pipe;
|
||||
|
||||
pipe.Connect();
|
||||
base.Run(sender, args);
|
||||
}
|
||||
catch
|
||||
{
|
||||
base.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Pipes;
|
||||
|
||||
namespace NamedPipes
|
||||
{
|
||||
public class NamedPipeServer : NamedPipe
|
||||
{
|
||||
protected override void Run(object sender, DoWorkEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pipe = new NamedPipeServerStream(
|
||||
pipeName: PIPE_NAME,
|
||||
maxNumberOfServerInstances: 1,
|
||||
direction: PipeDirection.InOut,
|
||||
transmissionMode: PipeTransmissionMode.Byte,
|
||||
options: PipeOptions.Asynchronous);
|
||||
this.pipe = pipe;
|
||||
|
||||
pipe.WaitForConnection();
|
||||
base.Run(sender, args);
|
||||
}
|
||||
catch
|
||||
{
|
||||
base.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-19
@@ -4,11 +4,11 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C27BA66C-C3A7-48A2-A644-CBA77E28E531}</ProjectGuid>
|
||||
<ProjectGuid>{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SIRTBroadcaster.Abstraction</RootNamespace>
|
||||
<AssemblyName>SIRTBroadcaster.Abstraction</AssemblyName>
|
||||
<RootNamespace>NamedPipes</RootNamespace>
|
||||
<AssemblyName>NamedPipes</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
@@ -31,9 +31,6 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -44,20 +41,10 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="IMessageSender.cs" />
|
||||
<Compile Include="ISIRTBroadcaster.cs" />
|
||||
<Compile Include="ISIRTBroadcasterClient.cs" />
|
||||
<Compile Include="ISIRTBroadcasterHost.cs" />
|
||||
<Compile Include="SIRTMessage.cs" />
|
||||
<Compile Include="SIRTConnection.cs" />
|
||||
<Compile Include="SIRTModel.cs" />
|
||||
<Compile Include="NamedPipe.cs" />
|
||||
<Compile Include="NamedPipeClient.cs" />
|
||||
<Compile Include="NamedPipeServer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SIRTExtensions.cs" />
|
||||
<Compile Include="SIRTFixed.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
+3
-3
@@ -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("SIRTBroadcaster.UI")]
|
||||
[assembly: AssemblyTitle("NamedPipes")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SIRTBroadcaster.UI")]
|
||||
[assembly: AssemblyProduct("NamedPipes")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[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("2550b77d-d975-4a50-9c6a-526d4e07754d")]
|
||||
[assembly: Guid("0cc5a97f-e1cd-412b-affe-b256fdb7dc19")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="COMS" value="COM4, COM, COM, COM, COM, COM, COM, COM"/>
|
||||
<add key="OMNIDB" value="Server=SLASQL01.emea.sensus.net; Database=AuftragKopie; User ID=sa; Password=sqlserver;"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
+11
-32
@@ -4,10 +4,10 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2550B77D-D975-4A50-9C6A-526D4E07754D}</ProjectGuid>
|
||||
<ProjectGuid>{6518211A-E83F-4171-97C4-A61FCF66D6E0}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>SIRTBroadcaster.UI</RootNamespace>
|
||||
<AssemblyName>SIRTBroadcaster.UI</AssemblyName>
|
||||
<RootNamespace>OmniPlus.UI</RootNamespace>
|
||||
<AssemblyName>OmniPlus.UI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
@@ -33,9 +33,6 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -48,27 +45,18 @@
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="XylemCommonUiLegacyGenCtl">
|
||||
<HintPath>..\Ui\LegacyGenesisControl\obj\Debug\XylemCommonUiLegacyGenCtl.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainForm.cs">
|
||||
<Compile Include="OmniPlusUI.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.Designer.cs">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
<Compile Include="OmniPlusUI.Designer.cs">
|
||||
<DependentUpon>OmniPlusUI.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PruefungInitialisierung.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PruefungInitialisierung.Designer.cs">
|
||||
<DependentUpon>PruefungInitialisierung.cs</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
<EmbeddedResource Include="OmniPlusUI.resx">
|
||||
<DependentUpon>OmniPlusUI.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
@@ -79,7 +67,6 @@
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
@@ -94,17 +81,9 @@
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SIRTBroadcaster.Abstraction\SIRTBroadcaster.Abstraction.csproj">
|
||||
<Project>{c27ba66c-c3a7-48a2-a644-cba77e28e531}</Project>
|
||||
<Name>SIRTBroadcaster.Abstraction</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SIRTBroadcaster.Client\SIRTBroadcaster.Client.csproj">
|
||||
<Project>{4221F992-599E-498C-A409-6D1E70E0A6F9}</Project>
|
||||
<Name>SIRTBroadcaster.Client</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SIRTBroadcaster.Host\SIRTBroadcaster.Host.csproj">
|
||||
<Project>{a9d1a99d-6e55-4394-86ad-b5c53e9225eb}</Project>
|
||||
<Name>SIRTBroadcaster.Host</Name>
|
||||
<ProjectReference Include="..\OmniPlus\OmniPlus.csproj">
|
||||
<Project>{F8D84B9A-0FCF-4083-B067-8C39B7314152}</Project>
|
||||
<Name>OmniPlus</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
namespace OmniPlus.UI
|
||||
{
|
||||
partial class OmniPlusUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.layout = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.navbar = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.pruefungStartBTN = new System.Windows.Forms.Button();
|
||||
this.body = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.pruefungBackground = new System.ComponentModel.BackgroundWorker();
|
||||
this.layout.SuspendLayout();
|
||||
this.navbar.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// layout
|
||||
//
|
||||
this.layout.ColumnCount = 1;
|
||||
this.layout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.layout.Controls.Add(this.navbar, 0, 1);
|
||||
this.layout.Controls.Add(this.body, 0, 0);
|
||||
this.layout.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.layout.Location = new System.Drawing.Point(0, 0);
|
||||
this.layout.Name = "layout";
|
||||
this.layout.RowCount = 2;
|
||||
this.layout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.layout.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.layout.Size = new System.Drawing.Size(1055, 560);
|
||||
this.layout.TabIndex = 0;
|
||||
//
|
||||
// navbar
|
||||
//
|
||||
this.navbar.AutoSize = true;
|
||||
this.navbar.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.navbar.ColumnCount = 3;
|
||||
this.navbar.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.navbar.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.navbar.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.navbar.Controls.Add(this.pruefungStartBTN, 2, 0);
|
||||
this.navbar.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.navbar.Location = new System.Drawing.Point(0, 523);
|
||||
this.navbar.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.navbar.Name = "navbar";
|
||||
this.navbar.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.navbar.RowCount = 2;
|
||||
this.navbar.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.navbar.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.navbar.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.navbar.Size = new System.Drawing.Size(1055, 37);
|
||||
this.navbar.TabIndex = 0;
|
||||
//
|
||||
// pruefungStartBTN
|
||||
//
|
||||
this.pruefungStartBTN.AutoSize = true;
|
||||
this.pruefungStartBTN.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pruefungStartBTN.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pruefungStartBTN.Location = new System.Drawing.Point(927, 6);
|
||||
this.pruefungStartBTN.Name = "pruefungStartBTN";
|
||||
this.navbar.SetRowSpan(this.pruefungStartBTN, 2);
|
||||
this.pruefungStartBTN.Size = new System.Drawing.Size(122, 25);
|
||||
this.pruefungStartBTN.TabIndex = 0;
|
||||
this.pruefungStartBTN.Text = "Prüfung starten";
|
||||
this.pruefungStartBTN.UseVisualStyleBackColor = true;
|
||||
this.pruefungStartBTN.Click += new System.EventHandler(this.PruefungStartBTN_Click);
|
||||
//
|
||||
// body
|
||||
//
|
||||
this.body.ColumnCount = 1;
|
||||
this.body.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.body.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.body.Location = new System.Drawing.Point(0, 0);
|
||||
this.body.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.body.Name = "body";
|
||||
this.body.Padding = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.body.RowCount = 1;
|
||||
this.body.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.body.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 522F));
|
||||
this.body.Size = new System.Drawing.Size(1055, 523);
|
||||
this.body.TabIndex = 1;
|
||||
//
|
||||
// OmniPlusUI
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1055, 560);
|
||||
this.Controls.Add(this.layout);
|
||||
this.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Name = "OmniPlusUI";
|
||||
this.Text = "OMNI Plus";
|
||||
this.layout.ResumeLayout(false);
|
||||
this.layout.PerformLayout();
|
||||
this.navbar.ResumeLayout(false);
|
||||
this.navbar.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel layout;
|
||||
private System.Windows.Forms.TableLayoutPanel navbar;
|
||||
private System.Windows.Forms.TableLayoutPanel body;
|
||||
private System.Windows.Forms.Button pruefungStartBTN;
|
||||
private System.ComponentModel.BackgroundWorker pruefungBackground;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
using OmniPlus.UI.Inspection;
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OmniPlus.UI
|
||||
{
|
||||
public partial class OmniPlusUI : Form
|
||||
{
|
||||
private readonly OmniPlusConnectionsPool connectionsPool;
|
||||
|
||||
public OmniPlusUI()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
var omniDatabase = ConfigurationManager.AppSettings.Get("OMNIDB");
|
||||
this.connectionsPool = new OmniPlusConnectionsPool(omniDatabase);
|
||||
|
||||
this.HandleCreated += this.OmniPlusUI_HandleCreated;
|
||||
this.HandleDestroyed += this.OmniPlusUI_HandleDestroyed;
|
||||
}
|
||||
|
||||
private void OmniPlusUI_HandleDestroyed(object _, EventArgs _1)
|
||||
{
|
||||
this.connectionsPool.Dispose();
|
||||
|
||||
this.connectionsPool.StateChanged -= this.ConnectionsPool_StateChanged;
|
||||
this.pruefungBackground.DoWork -= this.PruefungBackground_DoWork;
|
||||
}
|
||||
|
||||
private void OmniPlusUI_HandleCreated(object _, EventArgs _1)
|
||||
{
|
||||
this.connectionsPool.StateChanged += this.ConnectionsPool_StateChanged;
|
||||
this.pruefungBackground.DoWork += this.PruefungBackground_DoWork;
|
||||
|
||||
this.InitializeBody();
|
||||
|
||||
var portNames = (ConfigurationManager
|
||||
.AppSettings
|
||||
.Get("COMS") ?? string.Empty)
|
||||
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
this.connectionsPool.InitializeInspection(portNames);
|
||||
}
|
||||
|
||||
private void PruefungStartBTN_Click(object _, EventArgs _1)
|
||||
=> this.pruefungBackground.RunWorkerAsync();
|
||||
|
||||
private void PruefungBackground_DoWork(object _, DoWorkEventArgs _1)
|
||||
{
|
||||
this.Invoke(new Action(() =>
|
||||
{
|
||||
this.Cursor = Cursors.WaitCursor;
|
||||
this.pruefungStartBTN.Enabled = false;
|
||||
}));
|
||||
|
||||
this.ClearBody();
|
||||
|
||||
this.connectionsPool.StartInspection();
|
||||
|
||||
this.Invoke(new Action(() =>
|
||||
{
|
||||
this.Cursor = Cursors.Default;
|
||||
this.pruefungStartBTN.Enabled = true;
|
||||
}));
|
||||
}
|
||||
|
||||
private void ConnectionsPool_StateChanged(int column, bool? succeeded, string header, string value)
|
||||
{
|
||||
this.body.Invoke(new Action(() =>
|
||||
{
|
||||
var headerIndex = this.GetRowIndex(header);
|
||||
var columnIndex = headerIndex + column;
|
||||
var controls = this.body.Controls;
|
||||
var controlsCount = controls.Count;
|
||||
|
||||
if (controls[headerIndex] is Label rowHeader)
|
||||
{
|
||||
rowHeader.Text = header;
|
||||
rowHeader.TextAlign = ContentAlignment.MiddleLeft;
|
||||
rowHeader.BackColor = SystemColors.ControlLight;
|
||||
rowHeader.ForeColor = SystemColors.ControlText;
|
||||
}
|
||||
|
||||
if (controls[columnIndex] is Label columnLabel)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
value = "---";
|
||||
}
|
||||
|
||||
columnLabel.Text = value;
|
||||
|
||||
columnLabel.BackColor = SystemColors.Window;
|
||||
|
||||
if (headerIndex == 0)
|
||||
{
|
||||
columnLabel.BackColor = SystemColors.ControlLight;
|
||||
}
|
||||
|
||||
columnLabel.ForeColor = SystemColors.ControlText;
|
||||
|
||||
if (headerIndex > 0 && columnIndex > 0)
|
||||
{
|
||||
if (succeeded == true)
|
||||
{
|
||||
columnLabel.ForeColor = Color.DarkGreen;
|
||||
}
|
||||
else if (succeeded == false)
|
||||
{
|
||||
columnLabel.ForeColor = Color.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
columnLabel.ForeColor = Color.Gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private int GetRowIndex(string header)
|
||||
{
|
||||
var controls = this.body.Controls;
|
||||
var controlsCount = controls.Count;
|
||||
var cols = this.body.ColumnCount;
|
||||
var rows = this.body.RowCount;
|
||||
var rowIndex = int.MinValue;
|
||||
int row;
|
||||
|
||||
for (row = 0; row < rows; row++)
|
||||
{
|
||||
var headerIndex = row * cols;
|
||||
|
||||
if (headerIndex >= controlsCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (controls[headerIndex] is Label label)
|
||||
{
|
||||
var labelText = label.Text?.Trim()?.ToLower();
|
||||
var headerText = header?.Trim()?.ToLower();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(labelText) || labelText == headerText)
|
||||
{
|
||||
rowIndex = headerIndex;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if (rowIndex == int.MinValue)
|
||||
{
|
||||
rowIndex = (rows - 1) * cols;
|
||||
}
|
||||
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
private void InitializeBody()
|
||||
{
|
||||
this.body.Invoke(new Action(() =>
|
||||
{
|
||||
var cols = 9;
|
||||
var rows = 31;
|
||||
|
||||
this.body.RowCount = 0;
|
||||
this.body.ColumnCount = 0;
|
||||
|
||||
this.body.Controls.Clear();
|
||||
this.body.RowStyles.Clear();
|
||||
this.body.ColumnStyles.Clear();
|
||||
|
||||
var bold = new Font(this.body.Font, FontStyle.Bold);
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
var firstRow = row == 0;
|
||||
|
||||
this.body.RowCount++;
|
||||
this.body.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||||
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
var firstCol = col == 0;
|
||||
var lastCol = col == cols - 1;
|
||||
|
||||
if (firstRow)
|
||||
{
|
||||
this.body.ColumnCount++;
|
||||
this.body.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, firstCol ? 100F : 65F));
|
||||
}
|
||||
|
||||
var color = firstCol || firstRow ? SystemColors.ControlLight : SystemColors.Window;
|
||||
|
||||
var label = new Label
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
Padding = new Padding(3),
|
||||
Margin = new Padding(0, 0, lastCol ? 0 : 3, 3),
|
||||
TextAlign = ContentAlignment.MiddleCenter,
|
||||
BackColor = color,
|
||||
ForeColor = color
|
||||
};
|
||||
|
||||
if (firstCol || firstRow)
|
||||
{
|
||||
label.Font = bold;
|
||||
}
|
||||
|
||||
this.body.Controls.Add(label, col, row);
|
||||
}
|
||||
}
|
||||
|
||||
this.body.RowCount++;
|
||||
this.body.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||
}));
|
||||
}
|
||||
|
||||
private void ClearBody()
|
||||
{
|
||||
this.body.Invoke(new Action(() =>
|
||||
{
|
||||
var rows = this.body.RowCount;
|
||||
var cols = this.body.ColumnCount;
|
||||
var controls = this.body.Controls;
|
||||
|
||||
for (int row = 1; row < rows; row++)
|
||||
{
|
||||
var offset = Math.Max(row - 1, 1) * cols;
|
||||
|
||||
for (int col = 1; col < cols; col++)
|
||||
{
|
||||
if (controls[offset + col] is Label label)
|
||||
{
|
||||
label.Text = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,4 +117,10 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="pruefungBackground.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>64</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OmniPlus.UI
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
[STAThread]
|
||||
public static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new OmniPlusUI());
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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("SIRTBroadcaster.Host")]
|
||||
[assembly: AssemblyTitle("OmniPlus.UI")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SIRTBroadcaster.Host")]
|
||||
[assembly: AssemblyProduct("OmniPlus.UI")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[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("a9d1a99d-6e55-4394-86ad-b5c53e9225eb")]
|
||||
[assembly: Guid("6518211a-e83f-4171-97c4-a61fcf66d6e0")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SIRTBroadcaster.UI.Properties
|
||||
namespace OmniPlus.UI.Properties
|
||||
{
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace SIRTBroadcaster.UI.Properties
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIRTBroadcaster.UI.Properties.Resources", typeof(Resources).Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OmniPlus.UI.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SIRTBroadcaster.UI.Properties
|
||||
namespace OmniPlus.UI.Properties
|
||||
{
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal class IrdaConnection : SerialPortConnection
|
||||
{
|
||||
protected event DataReceivedHandler MessageReceived;
|
||||
|
||||
public IrdaConnection(string portName)
|
||||
{
|
||||
this.Options.PortName = portName;
|
||||
this.Options.BaudRate = BaudRate.K115200;
|
||||
this.Options.DataBits = DataBits.X8;
|
||||
this.Options.Parity = Parity.None;
|
||||
this.Options.StopBits = StopBits.One;
|
||||
this.Options.LogFile = $".\\IRDA\\[{portName}].txt";
|
||||
}
|
||||
|
||||
public byte[] SendMessage(byte[] command)
|
||||
{
|
||||
var response = new byte[0];
|
||||
var received = false;
|
||||
|
||||
if (command is null)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
void MessageReceivedHandler(byte[] bytes)
|
||||
{
|
||||
response = bytes
|
||||
.FromIrdaMessage()
|
||||
.FromUI1236Message();
|
||||
received = true;
|
||||
}
|
||||
|
||||
this.MessageReceived += MessageReceivedHandler;
|
||||
|
||||
this.Write(1, 1, 1, 1);
|
||||
|
||||
var request = command
|
||||
.ToUI1236Message()
|
||||
.ToIrdaMessage();
|
||||
var sleep = 5000;
|
||||
var delay = 500;
|
||||
|
||||
this.Write(request);
|
||||
|
||||
while (!received && sleep >= 0)
|
||||
{
|
||||
sleep -= delay;
|
||||
|
||||
Thread.Sleep(delay);
|
||||
}
|
||||
|
||||
this.MessageReceived -= MessageReceivedHandler;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
protected override void SerialPortConnection_DataReceived(byte[] bytes)
|
||||
{
|
||||
var message = default(byte[]);
|
||||
var length = bytes.Length;
|
||||
var start = 0;
|
||||
|
||||
while (start < bytes.Length)
|
||||
{
|
||||
if (bytes[start] == OmniPlusExtensions.IRDA_START)
|
||||
{
|
||||
try
|
||||
{
|
||||
var messageLength = bytes[start + 2] * 2;
|
||||
messageLength += OmniPlusExtensions.IRDA_MIN_LENGTH;
|
||||
message = new byte[messageLength];
|
||||
|
||||
Array.Copy(bytes, start, message, 0, messageLength);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.SerialPortConnection_LogMessage(e.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
start++;
|
||||
}
|
||||
|
||||
this.MessageReceived?.Invoke(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
using OmniPlus.Options;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal abstract class SerialPortConnection
|
||||
{
|
||||
protected event StateChangedEventHandler StateChanged;
|
||||
protected event DataReceivedHandler DataReceived;
|
||||
protected event LogMessageEventHandler LogMessage;
|
||||
|
||||
private SerialPort serialPort;
|
||||
private SerialPortState state;
|
||||
|
||||
protected SerialPortConnection()
|
||||
=> this.Options = new SerialPortOptions();
|
||||
|
||||
protected SerialPortOptions Options { get; }
|
||||
|
||||
public bool Connected => this.state == SerialPortState.Open;
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
this.serialPort.DataReceived -= this.SerialPort_DataReceived;
|
||||
this.serialPort.Disposed -= this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived -= this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged -= this.SerialPort_PinChanged;
|
||||
}
|
||||
|
||||
this.serialPort?.Close();
|
||||
this.serialPort?.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.StateChanged?.Invoke(SerialPortState.ErrorReceived, e.ToString());
|
||||
}
|
||||
|
||||
this.serialPort = null;
|
||||
this.state = SerialPortState.Closed;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} closed.");
|
||||
|
||||
if (this.LogMessage != null)
|
||||
{
|
||||
foreach (var @delegate in this.LogMessage.GetInvocationList())
|
||||
{
|
||||
if (@delegate is LogMessageEventHandler eventHandler)
|
||||
{
|
||||
this.LogMessage -= eventHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.StateChanged != null)
|
||||
{
|
||||
foreach (var @delegate in this.StateChanged.GetInvocationList())
|
||||
{
|
||||
if (@delegate is LogMessageEventHandler eventHandler)
|
||||
{
|
||||
this.LogMessage -= eventHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.DataReceived != null)
|
||||
{
|
||||
foreach (var @delegate in this.DataReceived.GetInvocationList())
|
||||
{
|
||||
if (@delegate is LogMessageEventHandler eventHandler)
|
||||
{
|
||||
this.LogMessage -= eventHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Open()
|
||||
{
|
||||
this.Close();
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = new FileInfo(this.Options.LogFile);
|
||||
fileInfo.Directory.Create();
|
||||
|
||||
File.AppendAllText(this.Options.LogFile, string.Empty);
|
||||
|
||||
this.LogMessage += this.SerialPortConnection_LogMessage;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.state = SerialPortState.ErrorReceived;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName}: {e}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.serialPort = new SerialPort
|
||||
{
|
||||
PortName = this.Options.PortName,
|
||||
BaudRate = (int)this.Options.BaudRate,
|
||||
DataBits = (int)this.Options.DataBits,
|
||||
Parity = this.Options.Parity,
|
||||
StopBits = this.Options.StopBits,
|
||||
RtsEnable = this.Options.RtsEnabled,
|
||||
DtrEnable = this.Options.DtrEnabled
|
||||
};
|
||||
|
||||
this.serialPort.DataReceived += this.SerialPort_DataReceived;
|
||||
this.serialPort.Disposed += this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived += this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged += this.SerialPort_PinChanged;
|
||||
this.DataReceived += this.SerialPortConnection_DataReceived;
|
||||
this.StateChanged += this.SerialPortConnection_StateChanged;
|
||||
|
||||
this.serialPort.Open();
|
||||
|
||||
this.state = SerialPortState.Open;
|
||||
|
||||
this.StateChanged?.Invoke(this.state
|
||||
, $"{this.Options.PortName} opened"
|
||||
+ $", {this.Options.BaudRate}"
|
||||
+ $", {this.Options.DataBits}"
|
||||
+ $", {this.Options.Parity}"
|
||||
+ $", {this.Options.StopBits}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.state = SerialPortState.ErrorReceived;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName}: {e}");
|
||||
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void Write(params byte[] message)
|
||||
{
|
||||
if (this.Connected && message.Length > 0)
|
||||
{
|
||||
this.serialPort.Write(message, 0, message.Length);
|
||||
}
|
||||
|
||||
this.LogMessage?.Invoke($"TX: {BitConverter.ToString(message)}");
|
||||
}
|
||||
|
||||
protected abstract void SerialPortConnection_DataReceived(byte[] bytes);
|
||||
|
||||
protected void SerialPortConnection_LogMessage(string message)
|
||||
=> File.AppendAllText(this.Options.LogFile, $"{message}{Environment.NewLine}");
|
||||
|
||||
protected void SerialPortConnection_StateChanged(SerialPortState state, string message)
|
||||
=> File.AppendAllText(this.Options.LogFile, $"[{state}] {message}{Environment.NewLine}");
|
||||
|
||||
private void SerialPort_PinChanged(object sender, SerialPinChangedEventArgs args)
|
||||
{
|
||||
this.state = SerialPortState.PinChanged;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} {args.EventType}.");
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs args)
|
||||
{
|
||||
this.state = SerialPortState.ErrorReceived;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} {args.EventType}.");
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void SerialPort_Disposed(object sender, EventArgs args)
|
||||
{
|
||||
this.state = SerialPortState.Disposed;
|
||||
|
||||
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} disposed.");
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs args)
|
||||
{
|
||||
if (this.Connected && sender is SerialPort port && port.BytesToRead > 0)
|
||||
{
|
||||
var bytes = new byte[port.BytesToRead];
|
||||
var lock_object = new object();
|
||||
|
||||
lock (lock_object)
|
||||
{
|
||||
port.Read(bytes, 0, port.BytesToRead);
|
||||
}
|
||||
|
||||
this.DataReceived?.Invoke(bytes);
|
||||
this.LogMessage?.Invoke($"RX: {BitConverter.ToString(bytes)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal class UniProConnection : SerialPortConnection
|
||||
{
|
||||
protected event DataReceivedHandler MessageReceived;
|
||||
|
||||
public UniProConnection(string portName)
|
||||
{
|
||||
this.Options.PortName = portName;
|
||||
this.Options.BaudRate = BaudRate.K2400;
|
||||
this.Options.DataBits = DataBits.X8;
|
||||
this.Options.Parity = Parity.None;
|
||||
this.Options.StopBits = StopBits.One;
|
||||
this.Options.LogFile = $".\\UniPro\\[{portName}].txt";
|
||||
}
|
||||
|
||||
public byte[] SendMessage(byte[] command)
|
||||
{
|
||||
var response = new byte[0];
|
||||
var received = false;
|
||||
|
||||
if (command is null)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
void MessageReceivedHandler(byte[] bytes)
|
||||
{
|
||||
response = bytes.FromUniProMessage();
|
||||
received = true;
|
||||
}
|
||||
|
||||
this.MessageReceived += MessageReceivedHandler;
|
||||
|
||||
var request = command.ToUniProMessage();
|
||||
var sleep = 5000;
|
||||
var delay = 500;
|
||||
|
||||
this.Write(request);
|
||||
|
||||
while (!received && sleep >= 0)
|
||||
{
|
||||
sleep -= delay;
|
||||
|
||||
Thread.Sleep(delay);
|
||||
}
|
||||
|
||||
this.MessageReceived -= MessageReceivedHandler;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
protected override void SerialPortConnection_DataReceived(byte[] bytes)
|
||||
{
|
||||
var message = default(byte[]);
|
||||
var length = bytes.Length;
|
||||
var start = 0;
|
||||
|
||||
while (start < bytes.Length)
|
||||
{
|
||||
if (bytes[start] == OmniPlusExtensions.UNIPRO_START)
|
||||
{
|
||||
try
|
||||
{
|
||||
var messageLength = bytes[start + 2];
|
||||
messageLength += OmniPlusExtensions.UNIPRO_MIN_LENGTH;
|
||||
message = new byte[messageLength];
|
||||
|
||||
Array.Copy(bytes, start, message, 0, messageLength);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.SerialPortConnection_LogMessage(e.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
start++;
|
||||
}
|
||||
|
||||
this.MessageReceived?.Invoke(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum BaudRate
|
||||
{
|
||||
K300 = 300,
|
||||
K600 = 600,
|
||||
K1200 = 1200,
|
||||
K2400 = 2400,
|
||||
K4800 = 4800,
|
||||
K9600 = 9600,
|
||||
K19200 = 19200,
|
||||
K38400 = 38400,
|
||||
K57600 = 57600,
|
||||
K115200 = 115200,
|
||||
K230400 = 230400,
|
||||
K460800 = 460800,
|
||||
K921600 = 921600
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum DataBits
|
||||
{
|
||||
X5 = 5,
|
||||
X6 = 6,
|
||||
X7 = 7,
|
||||
X8 = 8
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum MessurementUnits : byte
|
||||
{
|
||||
CubicMeters = 0,
|
||||
CubicFeet = 1,
|
||||
CubicInches = 2,
|
||||
CubicYards = 3,
|
||||
USGallons = 4,
|
||||
ImperialGallons = 5,
|
||||
AcreFeet = 6,
|
||||
Kiloliters = 7,
|
||||
Liters = 8,
|
||||
WattHours = 9,
|
||||
KilowattHours = 10,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum ReadingSettings : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// When forward and reverse volumes are supported,
|
||||
/// this will be equal to the value of the expression (total forward volume) – (total reverse volume).
|
||||
/// Use this value for sensors with no concept of forward or reverse.
|
||||
/// </summary>
|
||||
Totalizer = 0x00,
|
||||
TotalForward = 0x01,
|
||||
TotalReverse = 0x02,
|
||||
LifetimeTotalizer = 0x03,
|
||||
TestTotalizer = 0x04,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum SerialPortState
|
||||
{
|
||||
Closed,
|
||||
Disposed,
|
||||
PinChanged,
|
||||
ErrorReceived,
|
||||
Open
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum Status : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by communication devices to indicate communication failure/timeout.
|
||||
/// Should not be used by a slave device implementing UI-1236.
|
||||
/// </summary>
|
||||
FailureOrTimeout = 0x00,
|
||||
/// <summary>
|
||||
/// Command complete, no errors
|
||||
/// </summary>
|
||||
Completed = 0x01,
|
||||
/// <summary>
|
||||
/// Error, unable to execute command
|
||||
/// </summary>
|
||||
UnableToExecute = 0x02,
|
||||
/// <summary>
|
||||
/// Error, unknown command
|
||||
/// </summary>
|
||||
UnknownCommand = 0x03,
|
||||
/// <summary>
|
||||
/// Error, unsupported control bit pattern
|
||||
/// </summary>
|
||||
UnsupportedControl = 0x04,
|
||||
/// <summary>
|
||||
/// Error, command blocked by factory seal.
|
||||
/// Added in version B1.23
|
||||
/// </summary>
|
||||
BlockedBySeal = 0x05,
|
||||
/// <summary>
|
||||
/// Custom field.
|
||||
/// </summary>
|
||||
Request = 0x80,
|
||||
/// <summary>
|
||||
/// Frame received, no error
|
||||
/// </summary>
|
||||
FrameReceived = 0xFC,
|
||||
/// <summary>
|
||||
/// Message corrupt
|
||||
/// </summary>
|
||||
MessageCorrupt = 0,
|
||||
/// <summary>
|
||||
/// Wait status
|
||||
/// </summary>
|
||||
Waiting = 0xFE,
|
||||
/// <summary>
|
||||
/// Used by communication devices to indicate unrecognized communication device command.
|
||||
/// </summary>
|
||||
UnrecognizedDevice = 0xFF
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace OmniPlus.Enums
|
||||
{
|
||||
public enum TimeUnits : byte
|
||||
{
|
||||
Milliseconds = 0,
|
||||
Seconds = 1,
|
||||
Minutes = 2,
|
||||
Hours = 3,
|
||||
Days = 4,
|
||||
Years = 5,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System.Text;
|
||||
|
||||
public class ASCIIString : FeatureRequest
|
||||
{
|
||||
public ASCIIString(int length) : base(length)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ASCIIString(byte[] response, int length) : base(response, length)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get => this.GetValue();
|
||||
set => this.SetValue(value);
|
||||
}
|
||||
|
||||
private string GetValue()
|
||||
=> Encoding.ASCII
|
||||
.GetString(this.bytes)
|
||||
.Trim();
|
||||
|
||||
private void SetValue(string value)
|
||||
{
|
||||
this.bytes.Clear();
|
||||
|
||||
var factoryID = value
|
||||
?.Substring(0, this.length)
|
||||
?? string.Empty;
|
||||
|
||||
Encoding.ASCII
|
||||
.GetBytes(factoryID)
|
||||
.CopyTo(this.bytes, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class BatteryVoltage : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 6;
|
||||
|
||||
public BatteryVoltage() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public BatteryVoltage(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ushort Volts
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 0);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 0);
|
||||
}
|
||||
|
||||
public uint ADCCount
|
||||
{
|
||||
get => BitConverter.ToUInt32(this.bytes, 2);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Build Information string must be at most 14 characters long. There are no restrictions on character type.
|
||||
/// Command is not available after factory seal.
|
||||
/// </summary>
|
||||
public class BuildInfo : ASCIIString
|
||||
{
|
||||
const int LENGTH = 14;
|
||||
|
||||
public BuildInfo() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public BuildInfo(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class ChamberCalibration : FeatureRequest
|
||||
{
|
||||
public const byte ACTIVATE_TEST = 0x00;
|
||||
public const byte REQUEST_RESULTS = 0x01;
|
||||
|
||||
public const byte TEST_ACTIVATED = 0x00;
|
||||
public const byte TEST_FAILED = 0x01;
|
||||
public const byte TEST_COMPLETED = 0x02;
|
||||
|
||||
const int LENGTH = 5;
|
||||
|
||||
public ChamberCalibration() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ChamberCalibration(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request Response
|
||||
/// 0 – Activate Factory Calibration Test Test Activation Successful
|
||||
/// 1 – Request Factory Calibration Test Results Test Failed (Timeout)
|
||||
/// 2 - ........................................ Test Successfully Completed
|
||||
/// </summary>
|
||||
public byte Control
|
||||
{
|
||||
get => this.bytes[0];
|
||||
set => this.bytes[0] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Request: Number of Rotations to collect. (not required if Requesting Calibration results) (Limited to 1 to 5000 rotations)
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Response: Number of rotations collected
|
||||
/// On Test Activation, this field echoes the number of rotations requested.
|
||||
/// On Test Failed and Test Successfully Completed, returns the number of rotations collected.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public ushort Rotations
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 1);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Request: Maximum Time command is supposed to take to execute - 1 to 3600 Seconds.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Response: Total Time it took to collect the indicated rotations. Each count is equal to 30.5176us.
|
||||
/// On Test Activation Successful, returns number of seconds test is allowed to take.
|
||||
/// On Test Failed, this field will show 0 indicating that the tested failed.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public ushort Duration
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 3);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ConfigurationParameters : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 62;
|
||||
|
||||
public ConfigurationParameters() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ConfigurationParameters(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
this.ProgrammableID = new ProgrammableID();
|
||||
this.ProgrammableID.Status = this.Status;
|
||||
this.ProgrammableID.Value = this.bytes.ToASCIIString(0, 20);
|
||||
|
||||
this.FactoryID = new FactoryID();
|
||||
this.FactoryID.Status = this.Status;
|
||||
this.FactoryID.Value = this.bytes.ToASCIIString(21, 33);
|
||||
|
||||
this.ReadingDigits = new ReadingDigits();
|
||||
this.ReadingDigits.Status = this.Status;
|
||||
this.ReadingDigits.Count = this.bytes[34];
|
||||
this.ReadingDigits.Offset = this.bytes[35];
|
||||
|
||||
this.Readings = new Readings();
|
||||
this.Readings.Status = this.Status;
|
||||
this.Readings.Value = this.bytes.ToASCIIString(36, 45);
|
||||
|
||||
this.OptionalUniDirFields = new OptionalUniDirFields();
|
||||
this.OptionalUniDirFields.Status = this.Status;
|
||||
this.OptionalUniDirFields.Past(this.bytes, 46);
|
||||
|
||||
this.AlartPersistencePeriod = this.bytes[50];
|
||||
this.DataLogIntervalMinutes = BitConverter.ToUInt16(this.bytes, 51);
|
||||
|
||||
this.DeviceID = new DeviceID();
|
||||
this.Readings.Status = this.Status;
|
||||
this.Readings.Value = this.bytes.ToASCIIString(53, 61);
|
||||
}
|
||||
|
||||
public ProgrammableID ProgrammableID { get; set; }
|
||||
|
||||
public FactoryID FactoryID { get; set; }
|
||||
|
||||
public ReadingDigits ReadingDigits { get; set; }
|
||||
|
||||
public Readings Readings { get; set; }
|
||||
|
||||
public OptionalUniDirFields OptionalUniDirFields { get; set; }
|
||||
|
||||
public byte AlartPersistencePeriod { get; set; }
|
||||
|
||||
public ushort DataLogIntervalMinutes { get; set; }
|
||||
|
||||
public DeviceID DeviceID { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// All printable characters except ';' (semicolon) and ',' (comma) are allowed.
|
||||
/// </summary>
|
||||
public class CustomerText : ASCIIString
|
||||
{
|
||||
const int LENGTH = 20;
|
||||
|
||||
public CustomerText() : base(LENGTH)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public CustomerText(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class DeviceID : ASCIIString
|
||||
{
|
||||
const int LENGTH = 9;
|
||||
|
||||
public DeviceID() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public DeviceID(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Epoch20000101 : FeatureRequest
|
||||
{
|
||||
static readonly DateTime epoch = new DateTime(2000, 01, 01, 00, 00, 00, DateTimeKind.Utc);
|
||||
|
||||
const int LENGTH = 4;
|
||||
|
||||
public Epoch20000101() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public Epoch20000101(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public uint SecondsSince
|
||||
{
|
||||
get => BitConverter.ToUInt32(this.bytes, 0);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 0);
|
||||
}
|
||||
|
||||
public DateTime DateTime
|
||||
{
|
||||
get => epoch.AddSeconds(this.SecondsSince);
|
||||
set => this.SecondsSince = (uint)(value - epoch).TotalSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class FactoryID : ASCIIString
|
||||
{
|
||||
const int LENGTH = 12;
|
||||
|
||||
public FactoryID() : base(LENGTH)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public FactoryID(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class FeatureRequest : FeatureResponse
|
||||
{
|
||||
protected readonly int length;
|
||||
|
||||
public FeatureRequest(int length)
|
||||
: base(length)
|
||||
=> this.length = length;
|
||||
|
||||
public FeatureRequest(byte[] response, int length = 0)
|
||||
: base(response, length)
|
||||
=> this.length = length;
|
||||
|
||||
public byte[] this[params byte[] cmd]
|
||||
{
|
||||
get
|
||||
{
|
||||
var cmdLength = cmd.Length;
|
||||
var request = new byte[this.length + cmdLength];
|
||||
|
||||
cmd.CopyTo(request, 0);
|
||||
this.bytes.CopyTo(request, cmdLength);
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class FeatureResponse
|
||||
{
|
||||
protected readonly byte[] bytes;
|
||||
|
||||
public FeatureResponse(int length = 0)
|
||||
=> this.bytes = new byte[length];
|
||||
|
||||
public FeatureResponse(byte[] response, int length = 0) : this(length)
|
||||
{
|
||||
if (response != null )
|
||||
{
|
||||
this.Status = (Status)response[0];
|
||||
|
||||
if (response.Length > 1 && response.Length >= length)
|
||||
{
|
||||
Array.Copy(response, 1, this.bytes, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Status Status { get; set; }
|
||||
|
||||
public bool Succeeded => this.Status == Status.Completed;
|
||||
|
||||
public static implicit operator byte[](FeatureResponse response)
|
||||
=> response?.bytes ?? new byte[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using static System.Collections.Specialized.BitVector32;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Policy;
|
||||
using System;
|
||||
|
||||
internal class Features
|
||||
{
|
||||
/// <summary>
|
||||
/// The View Factory ID command shall cause the slave device to transmit the factory ID.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall respond by sending a message containing a status byte followed by the ASCII ID string
|
||||
/// terminated by a NULL character.
|
||||
/// <para>Note: This value is reported in the ;K field of UI-1203’s AMR string.</para>
|
||||
/// </summary>
|
||||
public const byte VIEW_FACTORY_ID = 0x01;
|
||||
/// <summary>
|
||||
/// The Set Factory ID command shall set the device ID.
|
||||
/// This command shall only be executed at the factory.
|
||||
/// The CDU shall consist of the one-byte command field followed by one to twelve ASCII alphanumeric characters.
|
||||
/// The ID shall be NULL terminated.
|
||||
/// The length of the ID string is device dependent.
|
||||
/// <para>It is recommended that all devices implement this command, though it may be protected by a factory seal.</para>
|
||||
/// </summary>
|
||||
public const byte SET_FACTORY_ID = 0x02;
|
||||
|
||||
/// <summary>
|
||||
/// The View Programmable ID command shall cause the slave device to return the customer ID.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall transmit a message block containing a NULL terminated ASCII string
|
||||
/// representing the customer ID.
|
||||
/// If the ID is NULL, a single NULL character (hex 00) shall be returned in the response string.
|
||||
/// <para>Note: This is the ID that is always reported in the UI-1203 AMR string.</para>
|
||||
/// </summary>
|
||||
public const byte VIEW_PROGRAMMABLE_ID = 0x03;
|
||||
/// <summary>
|
||||
/// The Set Programmable ID command shall set the customer ID in the slave device.
|
||||
/// The CDU shall consist of the one byte command code followed by a NULL terminated ASCII string
|
||||
/// of 1-20 alphanumeric characters.
|
||||
/// The ID shall be cleared and set to NULL if this command is sent with a string consisting
|
||||
/// of a single NULL (hex 00) character.
|
||||
/// <para>
|
||||
/// Note: This sets the ID that is required to be reported in the UI-1203 AMR string.
|
||||
/// In Fixed Length reading mode, the length is restricted to 8 characters.
|
||||
/// In Variable Length reading mode, the ;I field is limited to 12 characters.
|
||||
/// Some devices my reject long IDs based on the UI-1203 restrictions.
|
||||
/// </para>
|
||||
/// <para>It is recommended that all devices implement this command.</para>
|
||||
/// </summary>
|
||||
public const byte SET_PROGRAMMABLE_ID = 0x04;
|
||||
|
||||
/// <summary>
|
||||
/// The View Version and Type command is used to determine the type of device being programmed.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall respond by sending data containing the protocol version, device type and software version.
|
||||
/// The format of the data is three comma-delimited strings with a single NULL terminator.
|
||||
/// [Protocol version],[Device type],[Software version]
|
||||
/// Each string consists of a maximum of eight characters.
|
||||
/// </summary>
|
||||
public const byte VIEW_VERSION_AND_TYPE = 0x05;
|
||||
|
||||
/// <summary>
|
||||
/// The View Customer Text command shall cause the slave device to return a string containing the customer text field.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall transmit a message block containing a NULL terminated ASCII string
|
||||
/// representing the customer text field.
|
||||
/// If the ID is NULL, a single NULL character (hex 00) shall be returned in the response string.
|
||||
/// <para>Note: This is the value reported in the ;J field of the UI-1203 AMR string.</para>
|
||||
/// </summary>
|
||||
public const byte VIEW_CUSTOMER_TEXT = 0x07;
|
||||
/// <summary>
|
||||
/// The Set Customer Text command shall set the Customer Text field in the slave device.
|
||||
/// The CDU shall consist of the one byte command code followed by a NULL terminated ASCII string
|
||||
/// of 1-20 alphanumeric characters.
|
||||
/// The Customer Text field shall be cleared and set to NULL if this command is sent with a string consisting
|
||||
/// of a single NULL (hex 00) character.
|
||||
/// <para>Note: This is the value reported in the ;J field of the UI-1203 AMR string.</para>
|
||||
/// </summary>
|
||||
public const byte SET_CUSTOMER_TEXT = 0x08;
|
||||
|
||||
/// <summary>
|
||||
/// The View Reading Digits command shall cause the slave device to return the number of reading digits.
|
||||
/// The slave device shall transmit a message block containing two 8-bit binary numbers:
|
||||
/// <para>
|
||||
/// 0: The first number represents the number of reading digits to report in the AMR string, from 4 to 9.
|
||||
/// If 9, then the; NB field will be enabled in the AMR string.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 1: The second number represents the AMR Reading Offset,
|
||||
/// which indicates the offset into the totalizer value where the AMR reading begins,
|
||||
/// counting from the right.The value is either 0 or negative.A value of 0 means to discard no digits.
|
||||
/// A value of -1 means to discard the least significant digit, etc.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For example, if the totalizer on the meter shows 876543210,
|
||||
/// and the number of reading digits is 5 with an AMR Reading Offset of -2 (0xFE),
|
||||
/// the AMR reading reported will be 65432.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that previously, the AMR Reading Offset was defined to be the number of digits to the right of the decimal point
|
||||
/// being reported, but no known devices implemented this command that way,
|
||||
/// since the position of the decimal point was unknown (electronically) on mechanical registers.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public const byte VIEW_READING_DIGITS = 0x09;
|
||||
/// <summary>
|
||||
/// The Set Number of Reading Digits command shall set the number of reading digits reported in the AMR string.
|
||||
/// The CDU shall consist of the one-byte command code followed by two 8-bit binary numbers.
|
||||
/// The first octet represents the total number of digits in the reading string.
|
||||
/// The second octet represents the AMR Reading Offset (see cmd 0x09).
|
||||
/// </summary>
|
||||
public const byte SET_READING_DIGITS = 0x0A;
|
||||
|
||||
/// <summary>
|
||||
/// The View Reading Units command shall cause the slave device to return the reading units.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall transmit an eight bit binary number representing the reading units.
|
||||
/// The table listing reading units and the associated number is contained in UI-1203.
|
||||
/// On devices that do not know their reading units, the value 255 (0xFF) will be returned.
|
||||
/// </summary>
|
||||
public const byte VIEW_READING_UNITS = 0x0B;
|
||||
/// <summary>
|
||||
/// The Set Reading Units command shall set the reading units for the slave device.
|
||||
/// The CDU shall consist of the one-byte command code followed by an eight bit binary number representing the reading units.
|
||||
/// The table listing the reading units and the associated number is contained in UI-1203.
|
||||
/// On some devices, sending the value 255 (0xFF) will disable the units subfield of the UI-1203 ; R field,
|
||||
/// on others the resolution and units subfields will be disabled.On some devices,
|
||||
/// sending the value 255 (0xFF) will result in an Unable to Execute response.
|
||||
/// On many devices, there is no error checking on the value, and it is possible to set the value to something invalid.
|
||||
/// </summary>
|
||||
public const byte SET_READING_UNITS = 0x0C;
|
||||
|
||||
/// <summary>
|
||||
/// The View Rate Units command shall cause the slave device to return the rate units.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall transmit two bytes representing the rate units.
|
||||
/// The first byte represents the totalization units and the second byte represents the time units.
|
||||
/// The table listing the rate units and the associated numbers is contained in UI-1203.
|
||||
/// </summary>
|
||||
public const byte VIEW_RATE_UNITS = 0x0D;
|
||||
/// <summary>
|
||||
/// The Set Rate Units command shall set the rate units for the slave device.
|
||||
/// The CDU shall consist of the one byte command code followed by two eight bit binary numbers
|
||||
/// representing the rate units.
|
||||
/// The first byte represents the volume units and the second byte represents the time units.
|
||||
/// The table listing the rate units and the associated numbers is contained in UI-1203.
|
||||
/// </summary>
|
||||
public const byte SET_RATE_UNITS = 0x0E;
|
||||
|
||||
/// <summary>
|
||||
/// The View Reading Resolution command shall cause the slave device to return the resolution setting for the reading.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall respond by sending a signed eight bit binary number representing
|
||||
/// the reading resolution in powers of ten.
|
||||
/// The value returned is the resolution reported in the UI-1203 read response’s ;R field,
|
||||
/// if the resolution subfield is enabled.
|
||||
/// On some devices, if the resolution subfield is disabled in the UI-1203 read response,
|
||||
/// this command will return -128 (0x80).
|
||||
/// On other devices, the resolution of the currently selected AMR digits is returned.
|
||||
/// </summary>
|
||||
public const byte VIEW_READING_RESOLUTION = 0x0F;
|
||||
/// <summary>
|
||||
/// The Set Reading Resolution command shall set the slave device resolution for the reading.
|
||||
/// The CDU consists of the command byte followed by a signed eight bit binary number representing
|
||||
/// the reading resolution in powers of ten.
|
||||
/// The maximum range of reading resolution is specified in UI-1203.
|
||||
/// Use this command to enable the resolution subfield of the UI-1203 ; R field.
|
||||
/// The value -128 (0x80) disables that subfield on most devices.On many devices,
|
||||
/// there is no error checking on this value, and what is set is what will be reported in the ; R field,
|
||||
/// even if it is incorrect.
|
||||
/// If your goal is to change the resolution of the reported reading,
|
||||
/// cmd 0x0A – Set Number of Reading Digits is most likely the command you need.
|
||||
/// </summary>
|
||||
public const byte SET_READING_RESOLUTION = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// The View Rate Resolution command shall cause the slave device to return the resolution setting for the rate.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device will send a response message with a signed eight bit binary number representing
|
||||
/// the rate resolution in powers of ten.
|
||||
/// </summary>
|
||||
public const byte VIEW_RATE_RESOLUTION = 0x11;
|
||||
/// <summary>
|
||||
/// The Set Rate Resolution command shall set the slave device resolution for rate.
|
||||
/// The CDU consists of the command code followed by a signed eight bit binary number representing
|
||||
/// the rate resolution in powers of ten.
|
||||
/// The maximum range of rate resolution is specified in UI-1203.
|
||||
/// </summary>
|
||||
public const byte SET_RATE_RESOLUTION = 0x12;
|
||||
|
||||
/// <summary>
|
||||
/// As of B1.23, there are two variants of this command:
|
||||
/// If the CDU consists of only the command byte.
|
||||
/// The slave device shall return a message block containing a NULL terminated ASCII string of one to eight characters.
|
||||
/// This version of the command existed in B1.22.
|
||||
/// In B1.23, the command was updated to allow for more than 8 digits and to support multiple sensors.
|
||||
/// The format of the B1.23 version of the command is shown in the table below.The response will be a
|
||||
/// null-terminated ASCII string.
|
||||
/// </summary>
|
||||
public const byte VIEW_READINGS = 0x13;
|
||||
|
||||
/// <summary>
|
||||
/// As of B1.23, there are two variants of this command:
|
||||
/// If the CDU consists of only the command byte.
|
||||
/// The slave device shall return a message block containing a NULL terminated ASCII string of one to eight characters.
|
||||
/// This version of the command existed in B1.22.
|
||||
/// In B1.23, the command was updated to allow for more than 8 digits and to support multiple sensors.
|
||||
/// The format of the B1.23 version of the command is shown in the table below.The response will be a
|
||||
/// null-terminated ASCII string.
|
||||
/// </summary>
|
||||
public const byte SET_READING_PRESET = 0x14;
|
||||
|
||||
/// <summary>
|
||||
/// The View Reading Mode command shall cause the slave device to return the current value of the reading mode.
|
||||
/// The CDU shall consist of the command byte. The slave device shall return a message block
|
||||
/// containing one byte binary number representing the reading mode.
|
||||
/// If the reading mode is not one of the formats specified in the description of cmd 0x16,
|
||||
/// the response for this command will be 0xFF to indicate Undefined.
|
||||
/// Command 0x27 which was introduced with B1.23 is preferable to this command as it is more flexible.
|
||||
/// </summary>
|
||||
public const byte VIEW_READING_MODE = 0x15;
|
||||
/// <summary>
|
||||
/// The Set Reading Mode command shall set the unidirectional reading mode in a register.
|
||||
/// The CDU shall consist of the command byte followed by a one byte binary number.
|
||||
/// The number represents the unidirectional reading mode setting as shown below in table three.
|
||||
/// Unidirectional reading modes and their respective fields are described
|
||||
/// in the communication protocol document(s) for each device.
|
||||
/// Some devices use different definitions than those found in the table above.
|
||||
/// Most device report the; R field before the; I field.
|
||||
/// Command 0x28 which was introduced with B1.23 is preferable to this command as it is more flexible.
|
||||
/// </summary>
|
||||
public const byte SET_READING_MODE = 0x16;
|
||||
|
||||
/// <summary>
|
||||
/// The View Build Information command shall cause the slave device to return a string containing the build information.
|
||||
/// The CDU shall consist of the command byte.
|
||||
/// The slave device shall transmit a message block containing a NULL terminated ASCII string
|
||||
/// representing the build information.
|
||||
/// If the ID is NULL, a single NULL character (hex 00) shall be returned in the response string.
|
||||
/// </summary>
|
||||
public const byte VIEW_BUILD_INFORMATION = 0x17;
|
||||
/// <summary>
|
||||
/// The Set Build Information command shall set the build Information field in the slave device.
|
||||
/// The CDU shall consist of the one byte command code followed by a NULL terminated ASCII string
|
||||
/// of 1-14 alphanumeric characters.
|
||||
/// The Build Info field shall be cleared and set to NULL if this command is sent with a string consisting of
|
||||
/// a single NULL (hex 00) character.
|
||||
/// Build information may vary from product to product.
|
||||
/// Build information may include, but not be limited to, date, time, manufacturing facility code,
|
||||
/// production line code, etc.
|
||||
/// Each project should detail build information data in its respective communication protocol specification document.
|
||||
/// </summary>
|
||||
public const byte SET_BUILD_INFORMATION = 0x18;
|
||||
|
||||
public const byte DEVICE_SPECIFIC = 0xFD;
|
||||
|
||||
/// <summary>
|
||||
/// Command is provided to allow the Factory to view multiple System Configurations with one
|
||||
/// UI1236 command to save time during Factory Configuration.
|
||||
/// </summary>
|
||||
public const byte VIEW_SYSTEM_PARAMETERS = 0xC6;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Command is provided to allow the Factory to view multiple Configurations with
|
||||
/// one UI1236 command to save time during Factory Configuration.
|
||||
/// Command is configured to take 0 to 1 parameters.
|
||||
/// To keep the command backward compatible with previous versions of the command,
|
||||
/// if no parameters are provided, the command will generate a response
|
||||
/// with all of the response elements up to View Device ID String but no including the View ID String.
|
||||
/// </summary>
|
||||
public const byte VIEW_CONFIGURATION_PARAMETERS = 0xC7;
|
||||
|
||||
/// <summary>
|
||||
/// View volume per pulse.
|
||||
/// Volume per pulse is the amount of volume (in units of milliliters) that is added to the volume counter
|
||||
/// when one pulse of a meter shaft magnet is detected.
|
||||
/// (Commonly meter shaft magnets have two or four magnetic poles and produce four or eight pulses per full rotation.)
|
||||
/// </summary>
|
||||
public const byte VIEW_INPUT_VOLUME = 0x02;
|
||||
/// <summary>
|
||||
/// Set volume per pulse.
|
||||
/// </summary>
|
||||
public const byte SET_INPUT_VOLUME = 0x03;
|
||||
|
||||
/// <summary>
|
||||
/// Command is used to test the accuracy of meter and to calibrate the Meter Register assembly.
|
||||
/// This is a factory command and is only available when the Register is not Factory Sealed.
|
||||
/// The time to execute the command is determined by the present flow on the meter when
|
||||
/// the command was sent and how many rotations are requested to be collected.
|
||||
/// Since the time is not known by the Register, it is up to the user to provide a maximum time the command will execute.
|
||||
/// If the test does not complete by the maximum time, a failure response will be generated when the Test Results are requested.
|
||||
/// Once the command is sent to execute the calibration procedure,
|
||||
/// the user will receive a response indicating that the test has started and then the Register will perform the test.
|
||||
/// While the test is being performed, the Register will be unresponsive until the test has completed.
|
||||
/// The user must wait the appropriate time to before requesting the results.
|
||||
/// Based on the flow rate and the number of samples it takes to complete the test,
|
||||
/// the user should be able to calculate how long to wait before requesting results.
|
||||
/// </summary>
|
||||
public const byte CHAMBER_CALIBRATION = 0x67;
|
||||
|
||||
/// <summary>
|
||||
/// System time (a.k.a. epoch time) is the number of seconds from midnight January 1, 2000 UTC.
|
||||
/// </summary>
|
||||
public const byte VIEW_SYSTEM_TIME = 0x10;
|
||||
/// <summary>
|
||||
/// After powering up system time starts at midnight January 2, 2000 UTC/GMT; i.e. 86400 seconds from January 1, 2000 epoch.
|
||||
/// System time can be advanced forward, but cannot be changed into the past.
|
||||
/// Setting system time to 0 while the register is not sealed causes the following to happen:
|
||||
/// <para>• Volume data log is cleared</para>
|
||||
/// <para>• Epoch time and volume reading are cleared</para>
|
||||
/// <para>• Periodic alarm log is cleared</para>
|
||||
/// <para>• Alarm counters are cleared</para>
|
||||
/// <para>• Processor is reset(command times out).</para>
|
||||
/// <para>• Upon reset system time is 86400 seconds(24 hours, January 2, 2000)</para>
|
||||
/// When system time is successfully changed by this command (except when it is set to 0),
|
||||
/// a new boot recovery record is written into flash.This way time,
|
||||
/// current volume reading and alarm counts can be recovered if Set System Time is followed by a reboot.
|
||||
/// </summary>
|
||||
public const byte SET_SYSTEM_TIME = 0x11;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class InputVolume : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 6;
|
||||
|
||||
public InputVolume() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public InputVolume(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ushort IntPart
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 0);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 0);
|
||||
}
|
||||
|
||||
public ushort Fraction
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 2);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 2);
|
||||
}
|
||||
|
||||
public byte Size
|
||||
{
|
||||
get => this.bytes[4];
|
||||
set => this.bytes[4] = value;
|
||||
}
|
||||
|
||||
public byte Range
|
||||
{
|
||||
get => this.bytes[5];
|
||||
set => this.bytes[5] = value;
|
||||
}
|
||||
|
||||
public int Factor { get; set; } = 100;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class ManifacturingTime : Epoch20000101
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Need more investigation of the purpose
|
||||
/// </summary>
|
||||
public class OptionalUniDirFields : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 4;
|
||||
|
||||
public OptionalUniDirFields() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public OptionalUniDirFields(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public void Past(byte[] bytes, int start)
|
||||
{
|
||||
this.bytes.Clear();
|
||||
|
||||
Array.Copy(bytes, start, this.bytes, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System.Text;
|
||||
|
||||
public class ProgrammableID : ASCIIString
|
||||
{
|
||||
const int LENGTH = 20;
|
||||
|
||||
public ProgrammableID() : base(LENGTH)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ProgrammableID(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Rate resolution depends on the reading units and the size of the meter.
|
||||
/// The customer is allowed to change the units of measure but they are not allowed to change Meter Range
|
||||
/// which indicates the actual size of the meter.
|
||||
/// </summary>
|
||||
public class RateResolution : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 2;
|
||||
|
||||
public RateResolution() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public RateResolution(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public sbyte Value
|
||||
{
|
||||
get => (sbyte)BitConverter.ToUInt16(this.bytes, 0);
|
||||
set => BitConverter
|
||||
.GetBytes(value)
|
||||
.CopyTo(this.bytes, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO: Implement the rate resolution table below:
|
||||
* ------------------------------------------------------------------
|
||||
* Meter Range Cubic Meters Cubic Feet Gallons Acre Feet
|
||||
* ------------------------------------------------------------------
|
||||
* m³/h cf/min gal/min
|
||||
* igal/min
|
||||
* ------------------------------------------------------------------
|
||||
* 1 ½” or 2” -3 -3 -3 Not Supported
|
||||
* 3” or 4” Extended -3 -3 -3 Not Supported
|
||||
* 3” or 4” Normal -3 -3 -3 Not Supported
|
||||
* 6” -3 -2 -2 Not Supported
|
||||
* 8” -2 -2 -2 Not Supported
|
||||
* 10” -2 -2 -2 Not Supported
|
||||
*/
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using OmniPlus.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Omni+ flow rate units are independent of the reading units.
|
||||
/// <para>Note: Acre Feet per Hour is not supported.</para>
|
||||
/// </summary>
|
||||
public class RateUnits : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 2;
|
||||
|
||||
public RateUnits() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public RateUnits(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public MessurementUnits Flow
|
||||
{
|
||||
get => (MessurementUnits)this.bytes[0];
|
||||
set
|
||||
{
|
||||
var flow = (byte)MessurementUnits.CubicMeters;
|
||||
var time = (byte)TimeUnits.Hours;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case MessurementUnits.CubicFeet:
|
||||
flow = (byte)value;
|
||||
time = (byte)TimeUnits.Minutes;
|
||||
break;
|
||||
case MessurementUnits.USGallons:
|
||||
flow = (byte)value;
|
||||
time = (byte)TimeUnits.Minutes;
|
||||
break;
|
||||
case MessurementUnits.ImperialGallons:
|
||||
flow = (byte)value;
|
||||
time = (byte)TimeUnits.Minutes;
|
||||
break;
|
||||
}
|
||||
|
||||
this.bytes[0] = flow;
|
||||
this.bytes[1] = time;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeUnits Time => (TimeUnits)this.bytes[1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class ReadingDigits : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 2;
|
||||
|
||||
public ReadingDigits() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ReadingDigits(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public byte Count
|
||||
{
|
||||
get => this.bytes[0];
|
||||
set => this.bytes[0] = value;
|
||||
}
|
||||
|
||||
public byte Offset
|
||||
{
|
||||
get => this.bytes[1];
|
||||
set => this.bytes[1] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Response will either indicate Fixed or Undefined (like ally). Use cmd 0x27 instead.
|
||||
/// Fixed mode requires a Programmable ID of exactly 8 characters and exactly 4 AMR digits.
|
||||
/// If Programmable ID or number of AMR digits is invalid, command will return Unable to Execute.
|
||||
/// The following actions will cause the register to exit Fixed mode:
|
||||
/// Setting the reading string fields with cmd 0x28 will exit fixed mode.
|
||||
/// Changing the Programmable ID to a length other than exactly 8 characters will exit fixed mode.
|
||||
/// Changing the number AMR digits to a value other than 4 will exit fixed mode.
|
||||
/// If programmable ID or number of AMR digits is set to something invalid for fixed mode,
|
||||
/// then to re - enter fixed mode requires correcting the changed parameter and sending command 0x16 Set Reading Mode again.
|
||||
/// </summary>
|
||||
public class ReadingMode : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 13;
|
||||
|
||||
public ReadingMode() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ReadingMode(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: To be implemented.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Versions B1.24 of this command are supported. Total Forward and Total Reverse are not supported.
|
||||
/// Absence of command payload(i.e.of the reading preset) clears the Totalizer reading unless
|
||||
/// Display View is set to Totalizer Test View which sets the Test Totalizer Counter to 0.
|
||||
/// Command will support setting Totalizer Value, Test Totalizer Value and the Lifetime Totalizer value
|
||||
/// while the device is not factory sealed.
|
||||
/// If the device is factory sealed, the Lifetime Totalizer is prevented from being changed
|
||||
/// and Test Totalizer is limited to setting it to 0.
|
||||
/// The Set Reading Preset command shall send the value to be used as the initial reading.
|
||||
/// The CDU consists of a one-byte command code followed by a NULL terminated ASCII string of one to eight characters
|
||||
/// representing the preset reading value.This value is assumed to be in the current units used for totalization.
|
||||
/// In protocol version B1.23, 9 digits are allowed on devices that support it.
|
||||
/// Some devices that implement B1.22 may also support a 9-digit null-terminated string.
|
||||
/// </summary>
|
||||
public class ReadingPreset : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 2;
|
||||
|
||||
public ReadingPreset() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public byte SensorID
|
||||
{
|
||||
get => this.bytes[0];
|
||||
set => this.bytes[0] = value;
|
||||
}
|
||||
|
||||
public ReadingSettings Setting
|
||||
{
|
||||
get => (ReadingSettings)this.bytes[1];
|
||||
set => this.bytes[1] = (byte)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Reading Resolution of the device depends on reading units and the size of the Meter.
|
||||
/// The customer is allowed to change the Units of measure but they are not able to change
|
||||
/// the Reading Resolution for the Meter Range.
|
||||
/// </summary>
|
||||
public class ReadingResolution : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 2;
|
||||
|
||||
public ReadingResolution() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ReadingResolution(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public sbyte Value
|
||||
{
|
||||
get => (sbyte)BitConverter.ToUInt16(this.bytes, 0);
|
||||
set => BitConverter
|
||||
.GetBytes(value)
|
||||
.CopyTo(this.bytes, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Implement the reading resolution table below:
|
||||
* -----------------------------------------------------------------------------------------------
|
||||
* Meter Range Cubic Meters Cubic Feet Imperial Gallons Gallons Acre Feet
|
||||
* -----------------------------------------------------------------------------------------------
|
||||
* 1 ½” or 2” -3 -2 0 0 -5
|
||||
* 3” or 4” Extended -2 -2 0 0 -5
|
||||
* 3” or 4” Normal -2 0 0 0 -5
|
||||
* 6” -2 0 0 0 -5
|
||||
* 8” -2 0 0 0 -4
|
||||
*/
|
||||
@@ -0,0 +1,31 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// 0xFF in the reading units byte does not change the reading units.
|
||||
/// 0xFF disables reporting of multiplier and units in the reading and flowrate uni-directional fields.
|
||||
/// Setting reading units to one of the actual supported values,
|
||||
/// enables reporting of multiplier and units in the reading and flowrate uni-directional fields.
|
||||
/// Reading Resolution is based on Meter Range and Units of Measure.
|
||||
/// Omni+ does not support a separate command to set reading resolution.
|
||||
/// </summary>
|
||||
public class ReadingUnits : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 1;
|
||||
|
||||
public ReadingUnits() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ReadingUnits(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public MessurementUnits Value
|
||||
{
|
||||
get => (MessurementUnits)this.bytes[0];
|
||||
set => this.bytes[0] = (byte)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Versions B1.24 of this command are supported. Total Forward and Total Reverse are not supported.
|
||||
/// <para>
|
||||
/// If sensor filed is set to 0, command supports viewing Lifetime Totalizer Value(Setting of 3)
|
||||
/// and Test Totalizer Value(Setting of 4). If reading the Life Time totalizer value,
|
||||
/// the number of digits reported will be increased to 13 digits to support a larger Reading.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Requesting a reading from an invalid sensor ID or reading type will result in an “Unable to execute” response.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Omni supports the B1.24 version of the command which allows additional functionality
|
||||
/// if more data is supplied in the payload. If 2 or more bytes of the payload are provided,
|
||||
/// the first byte is used to indicate the sensor with 0 being a volume sensor.
|
||||
/// The second byte of the payload is which one of the specified type of sensor is being read.
|
||||
/// If a third byte of the payload is provided, the command will also provide the multiplier resolution of the sensor reading.
|
||||
/// Omni only supports the Volume Sensor.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note: Because of the size of the Meter,
|
||||
/// the Life Time Totalizer may exceed the reportable range using the Resolution set for the Totalizer value.
|
||||
/// When the Life Time Totalizer value exceeds 12 reportable digits and the Resolution is not 0,
|
||||
/// the Resolution will be reduced until either the whole part of the Life Time Totalizer is reported
|
||||
/// or until there are no more Resolution steps to reduce the reading at which time the number
|
||||
/// will be truncated to 12 digits.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class Readings : ASCIIString
|
||||
{
|
||||
const int LENGTH = 8;
|
||||
|
||||
public Readings() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public Readings(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public byte SensorID => this.bytes[0];
|
||||
|
||||
public ReadingSettings Setting => (ReadingSettings)this.bytes[1];
|
||||
|
||||
public bool Include => this.bytes[2] == 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class RegisterSettings : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 13;
|
||||
|
||||
public RegisterSettings() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public RegisterSettings(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ushort IntPart
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 0);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 0);
|
||||
}
|
||||
|
||||
public ushort Fraction
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 2);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 2);
|
||||
}
|
||||
|
||||
public byte Size
|
||||
{
|
||||
get => this.bytes[4];
|
||||
set => this.bytes[4] = value;
|
||||
}
|
||||
|
||||
public byte Range
|
||||
{
|
||||
get => this.bytes[5];
|
||||
set => this.bytes[5] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class SystemParameters : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 59;
|
||||
|
||||
public SystemParameters() : base(LENGTH)
|
||||
{
|
||||
this.BuildInfo = new BuildInfo();
|
||||
this.ManifacturingTime = new ManifacturingTime();
|
||||
this.SystemTime = new SystemTime();
|
||||
this.VersionAndType = new VersionAndType();
|
||||
this.BatteryVoltage = new BatteryVoltage();
|
||||
}
|
||||
|
||||
public SystemParameters(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
this.BuildInfo = new BuildInfo();
|
||||
this.BuildInfo.Status = this.Status;
|
||||
this.BuildInfo.Value = this.bytes.ToASCIIString(0, 15);
|
||||
|
||||
this.ManifacturingTime = new ManifacturingTime();
|
||||
this.ManifacturingTime.Status = this.Status;
|
||||
this.ManifacturingTime.SecondsSince = BitConverter.ToUInt32(this.bytes, 16);
|
||||
|
||||
this.SystemTime = new SystemTime();
|
||||
this.SystemTime.Status = this.Status;
|
||||
this.SystemTime.SecondsSince = BitConverter.ToUInt32(this.bytes, 20);
|
||||
|
||||
this.RebootsCount = this.bytes[24];
|
||||
|
||||
this.VersionAndType = new VersionAndType();
|
||||
this.VersionAndType.Status = this.Status;
|
||||
this.VersionAndType.Value = this.bytes.ToASCIIString(25, 51);
|
||||
|
||||
this.BatteryVoltage = new BatteryVoltage();
|
||||
this.BatteryVoltage.Status = this.Status;
|
||||
this.BatteryVoltage.Volts = BitConverter.ToUInt16(this.bytes, 52);
|
||||
this.BatteryVoltage.ADCCount = BitConverter.ToUInt32(this.bytes, 54);
|
||||
|
||||
this.FactorySealed = this.bytes[58] == 1;
|
||||
}
|
||||
|
||||
public BuildInfo BuildInfo { get; set; }
|
||||
|
||||
public ManifacturingTime ManifacturingTime { get; set; }
|
||||
|
||||
public SystemTime SystemTime { get; set; }
|
||||
|
||||
public byte RebootsCount { get; set; }
|
||||
|
||||
public VersionAndType VersionAndType { get; set; }
|
||||
|
||||
public BatteryVoltage BatteryVoltage { get; set; }
|
||||
|
||||
public bool FactorySealed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class SystemTime : Epoch20000101
|
||||
{
|
||||
public SystemTime()
|
||||
{
|
||||
}
|
||||
|
||||
public SystemTime(byte[] response) : base(response)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Protocol version is at least "R1.23".
|
||||
/// Device Type ID String is "OMNI-01".
|
||||
/// Software version follows the NA2W FlexNet format; e.g. "R1.0.0A".
|
||||
/// <para>
|
||||
/// Note: In R0.3.14 firmware the Device type string is no longer hardcoded to OMNI-01 in the firmware.
|
||||
/// Now the Factory can program a different string based on if it is a T2 or R2 variant.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class VersionAndType : ASCIIString
|
||||
{
|
||||
const int LENGTH = 12;
|
||||
|
||||
public VersionAndType() : base(LENGTH)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public VersionAndType(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace OmniPlus.Hanlers
|
||||
{
|
||||
internal delegate void DataReceivedHandler(byte[] bytes);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace OmniPlus.Hanlers
|
||||
{
|
||||
internal delegate void LogMessageEventHandler(string message);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace OmniPlus.Hanlers
|
||||
{
|
||||
internal delegate byte[] MessageHandler(params byte[] bytes);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
namespace OmniPlus.Hanlers
|
||||
{
|
||||
internal delegate void StateChangedEventHandler(SerialPortState state, string reason);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F8D84B9A-0FCF-4083-B067-8C39B7314152}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OmniPlus</RootNamespace>
|
||||
<AssemblyName>OmniPlus</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Connections\IrdaConnection.cs" />
|
||||
<Compile Include="Enums\MessurementUnits.cs" />
|
||||
<Compile Include="Enums\ReadingSettings.cs" />
|
||||
<Compile Include="Enums\Status.cs" />
|
||||
<Compile Include="Enums\TimeUnits.cs" />
|
||||
<Compile Include="Features\ASCIIString.cs" />
|
||||
<Compile Include="Features\BatteryVoltage.cs" />
|
||||
<Compile Include="Features\BuildInfo.cs" />
|
||||
<Compile Include="Features\ChamberCalibration.cs" />
|
||||
<Compile Include="Features\ConfigurationParameters.cs" />
|
||||
<Compile Include="Features\CustomerText.cs" />
|
||||
<Compile Include="Features\DeviceID.cs" />
|
||||
<Compile Include="Features\Epoch20000101.cs" />
|
||||
<Compile Include="Features\FactoryID.cs" />
|
||||
<Compile Include="Features\Features.cs" />
|
||||
<Compile Include="Features\FeatureRequest.cs" />
|
||||
<Compile Include="Features\FeatureResponse.cs" />
|
||||
<Compile Include="Features\InputVolume.cs" />
|
||||
<Compile Include="Features\ManifacturingTime.cs" />
|
||||
<Compile Include="Features\OptionalUniDirFields.cs" />
|
||||
<Compile Include="Features\ProgrammableID.cs" />
|
||||
<Compile Include="Features\RateResolution.cs" />
|
||||
<Compile Include="Features\RateUnits.cs" />
|
||||
<Compile Include="Features\ReadingDigits.cs" />
|
||||
<Compile Include="Features\ReadingMode.cs" />
|
||||
<Compile Include="Features\ReadingPreset.cs" />
|
||||
<Compile Include="Features\Readings.cs" />
|
||||
<Compile Include="Features\ReadingResolution.cs" />
|
||||
<Compile Include="Features\ReadingUnits.cs" />
|
||||
<Compile Include="Features\RegisterSettings.cs" />
|
||||
<Compile Include="Features\SystemParameters.cs" />
|
||||
<Compile Include="Features\SystemTime.cs" />
|
||||
<Compile Include="Features\VersionAndType.cs" />
|
||||
<Compile Include="OmniPlusConnection.cs" />
|
||||
<Compile Include="Connections\SerialPortConnection.cs" />
|
||||
<Compile Include="Connections\UniProConnection.cs" />
|
||||
<Compile Include="Enums\BaudRate.cs" />
|
||||
<Compile Include="Enums\DataBits.cs" />
|
||||
<Compile Include="Enums\SerialPortState.cs" />
|
||||
<Compile Include="Hanlers\DataReceivedHandler.cs" />
|
||||
<Compile Include="Hanlers\LogMessageHandler.cs" />
|
||||
<Compile Include="Hanlers\MessageHandler.cs" />
|
||||
<Compile Include="Hanlers\StateChangedHandler.cs" />
|
||||
<Compile Include="OmniPlusConnectionsPool.cs" />
|
||||
<Compile Include="OmniPlusDatabase.cs" />
|
||||
<Compile Include="OmniPlusExtensions.cs" />
|
||||
<Compile Include="OmniPlusInspectionHeaders.cs" />
|
||||
<Compile Include="OmniPlusInspectionPoint.cs" />
|
||||
<Compile Include="OmniPlusMeter.cs" />
|
||||
<Compile Include="OmniPlusStateChangedEventHandler.cs" />
|
||||
<Compile Include="Options\OmniControlOptions.cs" />
|
||||
<Compile Include="Options\SerialPortOptions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NamedPipes\NamedPipes.csproj">
|
||||
<Project>{0CC5A97F-E1CD-412B-AFFE-B256FDB7DC19}</Project>
|
||||
<Name>NamedPipes</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,276 @@
|
||||
using OmniPlus.Features;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
|
||||
using static OmniPlus.Features.Features;
|
||||
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
public class OmniPlusConnection
|
||||
{
|
||||
private readonly IrdaConnection irdaConnection;
|
||||
private readonly UniProConnection uniProConnection;
|
||||
|
||||
public OmniPlusConnection(string portName)
|
||||
{
|
||||
this.irdaConnection = new IrdaConnection(portName);
|
||||
this.uniProConnection = new UniProConnection(portName);
|
||||
}
|
||||
|
||||
internal MessageHandler MessageHandler;
|
||||
|
||||
public bool ConnectIrda()
|
||||
{
|
||||
this.uniProConnection.Close();
|
||||
this.irdaConnection.Open();
|
||||
|
||||
this.MessageHandler = this.irdaConnection.SendMessage;
|
||||
|
||||
return this.irdaConnection.Connected;
|
||||
}
|
||||
|
||||
public bool ConnectUniPro()
|
||||
{
|
||||
this.irdaConnection.Close();
|
||||
this.uniProConnection.Open();
|
||||
|
||||
this.MessageHandler = this.uniProConnection.SendMessage;
|
||||
|
||||
return this.irdaConnection.Connected;
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
this.uniProConnection.Close();
|
||||
this.irdaConnection.Close();
|
||||
}
|
||||
|
||||
public FactoryID ViewFactoryID()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_FACTORY_ID);
|
||||
|
||||
return new FactoryID(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetFactoryID(FactoryID factoryID)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(factoryID[SET_FACTORY_ID]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ProgrammableID ViewProgrammableID()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_PROGRAMMABLE_ID);
|
||||
|
||||
return new ProgrammableID(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetProgrammableID(ProgrammableID programmableID)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(programmableID[SET_PROGRAMMABLE_ID]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public VersionAndType ViewVersionAndType()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_VERSION_AND_TYPE);
|
||||
|
||||
return new VersionAndType(response);
|
||||
}
|
||||
|
||||
public CustomerText ViewCustomerText()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_CUSTOMER_TEXT);
|
||||
|
||||
return new CustomerText(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetCustomerText(CustomerText customerText)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(customerText[SET_CUSTOMER_TEXT]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ReadingDigits ViewReadingDigits()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READING_DIGITS);
|
||||
|
||||
return new ReadingDigits(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetReadingDigits(ReadingDigits readingDigits)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(readingDigits[SET_READING_DIGITS]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ReadingUnits ViewReadingUnits()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READING_UNITS);
|
||||
|
||||
return new ReadingUnits(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetReadingUnits(ReadingUnits readingUnits)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(readingUnits[SET_READING_UNITS]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public RateUnits ViewRateUnits()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_RATE_UNITS);
|
||||
|
||||
return new RateUnits(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetRateUnits(RateUnits rateUnits)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(rateUnits[SET_RATE_UNITS]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ReadingResolution ViewReadingResolution()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READING_RESOLUTION);
|
||||
|
||||
return new ReadingResolution(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetReadingResolution(ReadingResolution readingResolution)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(readingResolution[SET_READING_RESOLUTION]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public RateResolution ViewRateResolution()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_RATE_RESOLUTION);
|
||||
|
||||
return new RateResolution(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetRateResolution(RateResolution rateResolution)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(rateResolution[SET_READING_RESOLUTION]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public Readings ViewReadings(Readings reading)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READINGS);
|
||||
|
||||
return new Readings(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetReadingPreset(ReadingPreset readingPreset)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(readingPreset[SET_READING_PRESET]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ReadingMode ViewReadingMode()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READING_MODE);
|
||||
|
||||
return new ReadingMode(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetReadingMode(ReadingMode readingMode)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(readingMode[SET_READING_MODE]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public BuildInfo ViewBuildInformation()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_BUILD_INFORMATION);
|
||||
|
||||
return new BuildInfo(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetBuildInformation(BuildInfo buildInformation)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(buildInformation[SET_BUILD_INFORMATION]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public SystemParameters ViewSystemParameters()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_SYSTEM_PARAMETERS);
|
||||
|
||||
return new SystemParameters(response);
|
||||
}
|
||||
|
||||
public ConfigurationParameters ViewConfigurationParameters()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_CONFIGURATION_PARAMETERS, 0x01);
|
||||
|
||||
return new ConfigurationParameters(response);
|
||||
}
|
||||
|
||||
public InputVolume SetInputVolume()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_INPUT_VOLUME);
|
||||
|
||||
return new InputVolume(response);
|
||||
}
|
||||
|
||||
public FeatureResponse SetInputVolume(InputVolume inputVolume)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(inputVolume[DEVICE_SPECIFIC, SET_INPUT_VOLUME]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ChamberCalibration StartChamberCalibration(ushort rotations, ushort duration)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(new ChamberCalibration
|
||||
{
|
||||
Rotations = rotations,
|
||||
Duration = duration,
|
||||
Control = ChamberCalibration.ACTIVATE_TEST
|
||||
});
|
||||
|
||||
return new ChamberCalibration(response);
|
||||
}
|
||||
|
||||
public ChamberCalibration ViewChamberCalibration()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, CHAMBER_CALIBRATION, ChamberCalibration.REQUEST_RESULTS);
|
||||
|
||||
return new ChamberCalibration(response);
|
||||
}
|
||||
|
||||
internal SystemTime ViewSystemTime()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_SYSTEM_TIME);
|
||||
|
||||
return new SystemTime(response);
|
||||
}
|
||||
|
||||
internal FeatureResponse SetSystemTime(SystemTime systemTime = null)
|
||||
{
|
||||
if (systemTime is null)
|
||||
{
|
||||
systemTime = new SystemTime();
|
||||
}
|
||||
|
||||
var response = this.MessageHandler.Invoke(systemTime[DEVICE_SPECIFIC, SET_SYSTEM_TIME]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
using NamedPipes;
|
||||
|
||||
using OmniPlus.Connections;
|
||||
using OmniPlus.Features;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static OmniPlus.UI.Inspection.OmniPlusInspectionHeaders;
|
||||
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
public class OmniPlusConnectionsPool : IDisposable
|
||||
{
|
||||
public event OmniPlusStateChangedEventHandler StateChanged;
|
||||
|
||||
private readonly ConcurrentDictionary<int, OmniPlusConnection> connections;
|
||||
private readonly ConcurrentDictionary<int, OmniPlusMeter> meters;
|
||||
private readonly ConcurrentDictionary<int, Task> tasks;
|
||||
private readonly NamedPipeClient namedPipeClient;
|
||||
private readonly OmniPlusDatabase database;
|
||||
|
||||
private bool available;
|
||||
private int size;
|
||||
|
||||
public OmniPlusConnectionsPool(string dbConnectionString)
|
||||
{
|
||||
this.connections = new ConcurrentDictionary<int, OmniPlusConnection>();
|
||||
this.meters = new ConcurrentDictionary<int, OmniPlusMeter>();
|
||||
this.namedPipeClient = new NamedPipeClient();
|
||||
this.database = new OmniPlusDatabase(dbConnectionString);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.StateChanged != null)
|
||||
{
|
||||
foreach (var callback in this.StateChanged.GetInvocationList())
|
||||
{
|
||||
if (callback is OmniPlusStateChangedEventHandler stateChangedCallback)
|
||||
{
|
||||
this.StateChanged -= stateChangedCallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var connection in this.connections.Values)
|
||||
{
|
||||
connection?.Disconnect();
|
||||
}
|
||||
|
||||
this.namedPipeClient.Connected -= this.NamedPipeClient_Connected;
|
||||
this.namedPipeClient.Disconnected -= this.NamedPipeClient_Disconnected;
|
||||
|
||||
this.namedPipeClient.Disconnect();
|
||||
this.connections.Clear();
|
||||
this.meters.Clear();
|
||||
}
|
||||
|
||||
public void InitializeInspection(params string[] portNames)
|
||||
{
|
||||
this.namedPipeClient.Connected += this.NamedPipeClient_Connected;
|
||||
this.namedPipeClient.Disconnected += this.NamedPipeClient_Disconnected;
|
||||
this.namedPipeClient.Connect();
|
||||
|
||||
OmniPlusConnection connection;
|
||||
OmniPlusMeter meter;
|
||||
var connections = 0;
|
||||
var position = 1;
|
||||
|
||||
foreach (var portName in portNames)
|
||||
{
|
||||
connection = new OmniPlusConnection(portName);
|
||||
meter = new OmniPlusMeter();
|
||||
|
||||
if (connection.ConnectIrda())
|
||||
{
|
||||
meter.Connected = true;
|
||||
connections++;
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.Disconnect();
|
||||
connection = default(OmniPlusConnection);
|
||||
meter = default(OmniPlusMeter);
|
||||
}
|
||||
|
||||
this.meters.TryAdd(position, meter);
|
||||
this.connections.TryAdd(position, connection);
|
||||
this.StateChanged?.Invoke(position, true, SLOT_NR, position.ToString());
|
||||
|
||||
position++;
|
||||
}
|
||||
|
||||
if (this.available)
|
||||
{
|
||||
this.available = connections > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartInspection()
|
||||
{
|
||||
this.StartOmniInitialization();
|
||||
this.StartOmniCalibration();
|
||||
this.FinishOmniInspection();
|
||||
}
|
||||
|
||||
private void StartOmniInitialization()
|
||||
{
|
||||
var factory = Task.Factory;
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
this.tasks[position] = factory.StartNew(() => this.StartOmniInitialization(position));
|
||||
}
|
||||
|
||||
factory.ContinueWhenAll(this.tasks.Values.ToArray(), _ => { });
|
||||
}
|
||||
|
||||
private void StartOmniInitialization(int position)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
this.StateChanged?.Invoke(position, meter.Connected, CONNECTED, meter.Connected ? OK : X);
|
||||
|
||||
var systemParameters = connection.ViewSystemParameters();
|
||||
meter.Initialized = systemParameters.Succeeded;
|
||||
|
||||
meter.AddSystemParameters(systemParameters);
|
||||
this.database.AddOrUpdate(systemParameters);
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.FirmwareInRange, FIRMWARE, meter.Firmware);
|
||||
this.StateChanged?.Invoke(position, true, BUILD_INFO, meter.BuildInfo);
|
||||
this.StateChanged?.Invoke(position, meter.ManifacturingTimeInRange, CREATED_ON, $"{meter.ManifacturingTime:yyyy-MM-dd}");
|
||||
this.StateChanged?.Invoke(position, meter.SystemTimeInRange, LAST_UPDATE, $"{meter.SystemTimeDrift} Sek.");
|
||||
this.StateChanged?.Invoke(position, meter.RebootsCount != 0xFF, REBOOTS_CNT, meter.RebootsCount.ToString());
|
||||
this.StateChanged?.Invoke(position, !meter.FactorySealed, SEALED, !meter.FactorySealed ? X : OK);
|
||||
|
||||
if (meter.Initialized)
|
||||
{
|
||||
var inputVolume = this.database.GetInputVolume(meter.Size);
|
||||
var inputVolumResponse = connection.SetInputVolume(inputVolume);
|
||||
meter.Initialized = inputVolumResponse.Succeeded;
|
||||
|
||||
if (meter.Initialized)
|
||||
{
|
||||
meter.AddInputVolume(inputVolume);
|
||||
}
|
||||
}
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.Initialized, ML_PER_PULSE, $"{meter.MlPerPulse:0.00000}");
|
||||
}
|
||||
else // meter or connection not in use
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, CONNECTED, null);
|
||||
this.StateChanged?.Invoke(position, null, FIRMWARE, null);
|
||||
this.StateChanged?.Invoke(position, null, BUILD_INFO, null);
|
||||
this.StateChanged?.Invoke(position, null, CREATED_ON, null);
|
||||
this.StateChanged?.Invoke(position, null, LAST_UPDATE, null);
|
||||
this.StateChanged?.Invoke(position, null, REBOOTS_CNT, null);
|
||||
this.StateChanged?.Invoke(position, null, SEALED, null);
|
||||
this.StateChanged?.Invoke(position, null, ML_PER_PULSE, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartOmniCalibration()
|
||||
{
|
||||
var factory = Task.Factory;
|
||||
var inspectionPoints = this.database.GetInspectionPoints(this.size);
|
||||
|
||||
foreach (var point in inspectionPoints)
|
||||
{
|
||||
this.namedPipeClient.RequestFlowRate(point.FlowRate);
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
this.tasks[position] = factory.StartNew(() => this.StartOmniCalibration(position, point));
|
||||
}
|
||||
|
||||
factory.ContinueWhenAll(this.tasks.Values.ToArray(), _ => { });
|
||||
|
||||
var volume = this.namedPipeClient.RequestReference();
|
||||
|
||||
foreach (var meter in this.meters.Values)
|
||||
{
|
||||
meter.AddInspectionVolume(point, volume);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var position in this.connections.Keys)
|
||||
{
|
||||
this.tasks[position] = factory.StartNew(() => this.CalibrateMeter(position));
|
||||
}
|
||||
|
||||
factory.ContinueWhenAll(this.tasks.Values.ToArray(), _ => { });
|
||||
}
|
||||
|
||||
private void StartOmniCalibration(int position, OmniPlusInspectionPoint point)
|
||||
{
|
||||
var header = $"{point.Rotations}/{point.Seconds}R/Sek.";
|
||||
var progress = 0;
|
||||
|
||||
this.StateChanged?.Invoke(position, null, header, $"{progress}%");
|
||||
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
if (!meter.CanCalibrate)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, X);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var activationResponse = connection.StartChamberCalibration(point.Rotations, point.Seconds);
|
||||
var calibrationResult = default(ChamberCalibration);
|
||||
|
||||
if (activationResponse.Succeeded)
|
||||
{
|
||||
progress += 10;
|
||||
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
//0x00 indicates that the parameters are valid and test will start 3 seconds after the response.
|
||||
Thread.Sleep(3000);
|
||||
|
||||
progress += 10;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
// waiting all the secconds to execute test
|
||||
Thread.Sleep(point.Seconds * 1000);
|
||||
|
||||
progress += 70;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
var delay = (int)(point.Seconds * 0.1) * 1000;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
calibrationResult = connection.ViewChamberCalibration();
|
||||
|
||||
if (calibrationResult.Succeeded)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(delay);
|
||||
|
||||
progress += 3;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
}
|
||||
|
||||
if (calibrationResult?.Succeeded == true)
|
||||
{
|
||||
if (calibrationResult.Control == ChamberCalibration.TEST_COMPLETED)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, true, header, $"100%");
|
||||
}
|
||||
else // calibration timeout or not ready but exceeds the 3s + seconds to run + 0.3%
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, X);
|
||||
}
|
||||
}
|
||||
else // calibration failed
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, "n/a");
|
||||
}
|
||||
}
|
||||
else // activation failed
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, "n/a");
|
||||
}
|
||||
|
||||
meter.AddCalibrationResult(point, calibrationResult);
|
||||
}
|
||||
else // meter or connection not in use
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, header, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalibrateMeter(int position)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
var correctionFactor = meter.CalculateCorrectionFactor();
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.Calibrated, CORRECTION, $"{correctionFactor:0.00}%");
|
||||
}
|
||||
else // meter or connection not in use
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, CORRECTION, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void FinishOmniInspection()
|
||||
{
|
||||
var factory = Task.Factory;
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
this.tasks[position] = factory.StartNew(() => this.FinishOmniInspection(position));
|
||||
}
|
||||
}
|
||||
|
||||
private void FinishOmniInspection(int position)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
var configurationParameters = connection.ViewConfigurationParameters();
|
||||
var canContinue = configurationParameters.Succeeded;
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
var systemTimeReset = connection.SetSystemTime();
|
||||
canContinue = systemTimeReset.Succeeded;
|
||||
}
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
var registerSettings = connection.ViewRegisterSettings();
|
||||
}
|
||||
}
|
||||
else // meter or connection not in use
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetOmni(int position, out OmniPlusConnection connection, out OmniPlusMeter meter)
|
||||
{
|
||||
var connectionFound = this.connections.TryGetValue(position, out connection);
|
||||
var meterFound = this.meters.TryGetValue(position, out meter);
|
||||
|
||||
return connectionFound
|
||||
&& connection != null
|
||||
&& meterFound
|
||||
&& meter != null
|
||||
&& meter.Connected;
|
||||
}
|
||||
|
||||
private void NamedPipeClient_Connected()
|
||||
=> this.available = true;
|
||||
|
||||
private void NamedPipeClient_Disconnected()
|
||||
=> this.available = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using OmniPlus.Features;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
internal class OmniPlusDatabase
|
||||
{
|
||||
private readonly string connectionString;
|
||||
|
||||
public OmniPlusDatabase(string omniDatabase)
|
||||
=> this.connectionString = omniDatabase;
|
||||
|
||||
internal void AddOrUpdate(SystemParameters systemParameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal InputVolume GetInputVolume(object size)
|
||||
{
|
||||
return new InputVolume();
|
||||
}
|
||||
|
||||
internal IEnumerable<OmniPlusInspectionPoint> GetInspectionPoints(int size)
|
||||
{
|
||||
return new OmniPlusInspectionPoint[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
using OmniPlus.Options;
|
||||
|
||||
using System;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal static class OmniPlusExtensions
|
||||
{
|
||||
public const byte OxOO = 0x00;
|
||||
public const byte OxO1 = 0x01;
|
||||
public const byte OxO2 = 0x02;
|
||||
public const byte OxO3 = 0x03;
|
||||
|
||||
public const byte UNIPRO_START = 0x53;
|
||||
public const byte UNIPRO_PC2REG = 0x57;
|
||||
public const byte UNIPRO_REG2PC = 0x52;
|
||||
public const byte UNIPRO_STOP = 0x0D;
|
||||
public const byte UNIPRO_MIN_LENGTH = 4;
|
||||
|
||||
public const byte UI1236_START = 0x0D;
|
||||
public const byte UI1236_MIN_LENGTH = 5;
|
||||
public const byte UI1236_HED_LENGTH = 3;
|
||||
|
||||
public const byte IRDA_START = 0x9B;
|
||||
public const byte IRDA_PC2REG = 0x33;
|
||||
public const byte IRDA_REG2PC = 0x43;
|
||||
public const byte IRDA_MIN_LENGTH = 5;
|
||||
public const byte IRDA_CRC_LENGTH = 2;
|
||||
|
||||
/// <summary>
|
||||
/// <para>UI1236 structure:</para>
|
||||
/// <para> 0. 0x0D - Start byte</para>
|
||||
/// <para> 1. .... - Length: max. 254</para>
|
||||
/// <para> 2. .... - Control byte</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-2. .... - Checksum 0 </para>
|
||||
/// <para>n-1. .... - Checksum 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] ToUI1236Message(this byte[] bytes)
|
||||
{
|
||||
var bytesLength = bytes.Length;
|
||||
var payloadLength = bytes.Length + UI1236_MIN_LENGTH;
|
||||
payloadLength += payloadLength % OxO2;
|
||||
|
||||
var index = OxOO;
|
||||
var message = new byte[payloadLength];
|
||||
message[index++] = UI1236_START;
|
||||
message[index++] = (byte)(bytesLength + UI1236_HED_LENGTH);
|
||||
|
||||
OmniControlOptions control = OxOO;
|
||||
control.ReturnResponse = true;
|
||||
message[index++] = control;
|
||||
|
||||
bytes.CopyTo(message, index--);
|
||||
|
||||
var checksum = message.CalculateCheckSUM(message.Length - OxO2);
|
||||
var checksumIndex = bytesLength + UI1236_HED_LENGTH;
|
||||
message[checksumIndex++] = checksum[OxO1];
|
||||
message[checksumIndex++] = checksum[OxOO];
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UI1236 structure:</para>
|
||||
/// <para> 0. 0x0D - Start byte</para>
|
||||
/// <para> 1. .... - Length: max. 254</para>
|
||||
/// <para> 2. .... - Control byte</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-2. .... - Checksum 0 </para>
|
||||
/// <para>n-1. .... - Checksum 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromUI1236Message(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - UI1236_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Array.Copy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UniPro structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length</para>
|
||||
/// <para> .. .... - Payload</para>
|
||||
/// <para>n-1. .... - Stop byte</para>
|
||||
/// </summary>
|
||||
public static byte[] ToUniProMessage(this byte[] bytes)
|
||||
{
|
||||
var messageLength = (byte)(bytes.Length + UNIPRO_MIN_LENGTH);
|
||||
var message = new byte[messageLength];
|
||||
var index = OxOO;
|
||||
|
||||
message[index++] = UNIPRO_START;
|
||||
message[index++] = UNIPRO_PC2REG;
|
||||
message[index++] = messageLength;
|
||||
message[messageLength - OxO1] = UNIPRO_STOP;
|
||||
|
||||
bytes.CopyTo(message, index);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UniPro structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length</para>
|
||||
/// <para> .. .... - Payload</para>
|
||||
/// <para>n-1. .... - Stop byte</para>
|
||||
/// </summary>
|
||||
public static byte[] FromUniProMessage(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - UNIPRO_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Array.Copy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] ToIrdaMessage(this byte[] bytes)
|
||||
{
|
||||
var payloadLength = bytes.Length;
|
||||
payloadLength += payloadLength % OxO2;
|
||||
|
||||
var index = OxOO;
|
||||
var message = new byte[payloadLength + IRDA_MIN_LENGTH];
|
||||
message[index++] = IRDA_START;
|
||||
message[index++] = IRDA_PC2REG;
|
||||
message[index++] = (byte)(payloadLength / OxO2);
|
||||
|
||||
bytes.CopyTo(message, index);
|
||||
|
||||
var messageLength = message.Length;
|
||||
var crc16 = message.CalculateCRC8408(1, messageLength - IRDA_CRC_LENGTH);
|
||||
message[messageLength - OxO2] = crc16[OxOO];
|
||||
message[messageLength - OxO1] = crc16[OxO1];
|
||||
|
||||
return message;
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromIrdaMessage(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - IRDA_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Array.Copy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public static byte[] CalculateCRC8408(this byte[] message, int start, int length)
|
||||
{
|
||||
var crc = 0xFFFF;
|
||||
|
||||
for (int x = start; x < length; x++)
|
||||
{
|
||||
crc ^= 0x00FF & message[x];
|
||||
|
||||
for (int i = 8; i > OxOO; i--)
|
||||
{
|
||||
if ((crc & 0x0001) != OxOO)
|
||||
{
|
||||
crc = (crc >> OxO1) ^ 0x8408;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= OxO1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crc = ~crc;
|
||||
|
||||
return BitConverter.GetBytes(crc);
|
||||
}
|
||||
|
||||
public static byte[] CalculateCheckSUM(this byte[] bytes, int length)
|
||||
{
|
||||
ushort checksum = OxOO;
|
||||
|
||||
for (int i = OxOO; i < length; i++)
|
||||
{
|
||||
checksum += bytes[i];
|
||||
}
|
||||
|
||||
return BitConverter.GetBytes(checksum);
|
||||
}
|
||||
|
||||
public static void Clear(this byte[] bytes)
|
||||
{
|
||||
var length = bytes.Length;
|
||||
|
||||
for (int i = OxOO; i < length; i++)
|
||||
{
|
||||
bytes[i] = OxOO;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToASCIIString(this byte[] bytes, int start, int end)
|
||||
{
|
||||
var asciiString = string.Empty;
|
||||
|
||||
while (start <= end)
|
||||
{
|
||||
asciiString += (char)bytes[start];
|
||||
start++;
|
||||
}
|
||||
|
||||
return asciiString.Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
internal class OmniPlusInspectionHeaders
|
||||
{
|
||||
public const string COMS_CONFIG = "COMS";
|
||||
|
||||
public const string SLOT_NR = "Einbauplatz";
|
||||
public const string CONNECTED = "Verbunden";
|
||||
public const string FIRMWARE = "Firmware";
|
||||
public const string CREATED_ON = "Herstellungsdatum";
|
||||
public const string LAST_UPDATE = "Letzte Aktualisierung";
|
||||
public const string REBOOTS_CNT = "Neustarts";
|
||||
public const string SEALED = "Versiegelt";
|
||||
public const string BUILD_INFO = "Build-Info";
|
||||
public const string ML_PER_PULSE = "ml/Puls";
|
||||
public const string CORRECTION = "Korrekturfaktor";
|
||||
//public const string REBOOTS_CNT = "Neustarts";
|
||||
//public const string REBOOTS_CNT = "Neustarts";
|
||||
|
||||
public const string OK = "✓";
|
||||
public const string X = "✘";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
using System;
|
||||
|
||||
internal struct OmniPlusInspectionPoint : IComparable<OmniPlusInspectionPoint>
|
||||
{
|
||||
public double FlowRate { get; set; }
|
||||
|
||||
public ushort Rotations { get; set; }
|
||||
|
||||
public ushort Seconds { get; set; }
|
||||
|
||||
public int CompareTo(OmniPlusInspectionPoint other)
|
||||
=> this.Rotations.CompareTo(other.Rotations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using OmniPlus.Features;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
internal class OmniPlusMeter
|
||||
{
|
||||
private readonly IDictionary<OmniPlusInspectionPoint, double> inspectionPoints;
|
||||
private readonly IDictionary<OmniPlusInspectionPoint, ChamberCalibration> calibrationResults;
|
||||
|
||||
private InputVolume inputVolume;
|
||||
private SystemParameters systemParameters;
|
||||
|
||||
public OmniPlusMeter(bool connected = false)
|
||||
{
|
||||
this.Connected = connected;
|
||||
this.inputVolume = new InputVolume();
|
||||
this.systemParameters = new SystemParameters();
|
||||
this.inspectionPoints = new Dictionary<OmniPlusInspectionPoint, double>();
|
||||
this.calibrationResults = new Dictionary<OmniPlusInspectionPoint, ChamberCalibration>();
|
||||
}
|
||||
|
||||
public bool Connected { get; set; }
|
||||
|
||||
public bool Initialized { get; set; }
|
||||
|
||||
public bool CanCalibrate { get; set; } = true;
|
||||
|
||||
public bool Calibrated { get; private set; }
|
||||
|
||||
public byte Size
|
||||
{
|
||||
get => this.inputVolume.Size;
|
||||
set => this.inputVolume.Size = value;
|
||||
}
|
||||
|
||||
public byte Range
|
||||
{
|
||||
get => this.inputVolume.Range;
|
||||
set => this.inputVolume.Range = value;
|
||||
}
|
||||
|
||||
public ushort IntPart
|
||||
{
|
||||
get => this.inputVolume.IntPart;
|
||||
set => this.inputVolume.IntPart = value;
|
||||
}
|
||||
|
||||
public ushort Fraction
|
||||
{
|
||||
get => this.inputVolume.Fraction;
|
||||
set => this.inputVolume.Fraction = value;
|
||||
}
|
||||
|
||||
public string BuildInfo
|
||||
{
|
||||
get => this.systemParameters.BuildInfo.Value.Trim('\0');
|
||||
set => this.systemParameters.BuildInfo.Value = value;
|
||||
}
|
||||
|
||||
public DateTime ManifacturingTime
|
||||
{
|
||||
get => this.systemParameters.ManifacturingTime.DateTime;
|
||||
set => this.systemParameters.ManifacturingTime.DateTime = value;
|
||||
}
|
||||
|
||||
public bool ManifacturingTimeInRange { get; private set; }
|
||||
|
||||
public DateTime SystemTime
|
||||
{
|
||||
get => this.systemParameters.SystemTime.DateTime;
|
||||
set => this.systemParameters.SystemTime.DateTime = value;
|
||||
}
|
||||
|
||||
public int SystemTimeDrift { get; private set; }
|
||||
|
||||
public bool SystemTimeInRange { get; private set; }
|
||||
|
||||
public byte RebootsCount
|
||||
{
|
||||
get => this.systemParameters.RebootsCount;
|
||||
set => this.systemParameters.RebootsCount = value;
|
||||
}
|
||||
|
||||
public string Firmware
|
||||
{
|
||||
get => this.systemParameters.VersionAndType.Value.Trim('\0');
|
||||
set => this.systemParameters.VersionAndType.Value = value;
|
||||
}
|
||||
|
||||
public bool FirmwareInRange { get; private set; }
|
||||
|
||||
public double Volts
|
||||
{
|
||||
get => Math.Max(this.systemParameters.BatteryVoltage.Volts, (ushort)1) / 1000.0;
|
||||
set => this.systemParameters.BatteryVoltage.Volts = (ushort)(value * 1000);
|
||||
}
|
||||
|
||||
public bool VoltsInRange => 3.19 <= this.Volts && this.Volts <= 3.75;
|
||||
|
||||
public uint ADCCounts
|
||||
{
|
||||
get => this.systemParameters.BatteryVoltage.ADCCount;
|
||||
set => this.systemParameters.BatteryVoltage.ADCCount = value;
|
||||
}
|
||||
|
||||
public bool FactorySealed
|
||||
{
|
||||
get => this.systemParameters.FactorySealed;
|
||||
set => this.systemParameters.FactorySealed = value;
|
||||
}
|
||||
|
||||
public double MlPerPulse { get; private set; }
|
||||
|
||||
internal void AddInputVolume(InputVolume inputVolume)
|
||||
{
|
||||
if (inputVolume != null)
|
||||
{
|
||||
this.inputVolume = inputVolume;
|
||||
|
||||
if (this.inputVolume.Fraction > 0)
|
||||
{
|
||||
this.MlPerPulse = this.inputVolume.Fraction / ushort.MaxValue * this.inputVolume.Factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddSystemParameters(SystemParameters systemParameters)
|
||||
{
|
||||
if (systemParameters != null)
|
||||
{
|
||||
this.systemParameters = systemParameters;
|
||||
|
||||
this.SystemTimeDrift = (DateTime.UtcNow - this.SystemTime).Seconds;
|
||||
this.SystemTimeInRange = Math.Abs(this.SystemTimeDrift) <= 700;
|
||||
this.ManifacturingTimeInRange = Math.Abs((DateTime.UtcNow - this.ManifacturingTime).Days) <= 365;
|
||||
|
||||
var firmwareTokens = this.Firmware
|
||||
?.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
?? new string[2];
|
||||
var versionString = firmwareTokens[0]?.Substring(1) ?? string.Empty;
|
||||
var versionParsed = double.TryParse(versionString, out var version);
|
||||
var typeString = firmwareTokens[1]?.ToUpper() ?? string.Empty;
|
||||
var isOmni = typeString == "OMNI-1" || typeString == "OMNI-2";
|
||||
|
||||
this.FirmwareInRange = versionParsed && version >= 1.23 && isOmni;
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddCalibrationResult(OmniPlusInspectionPoint point, ChamberCalibration result)
|
||||
{
|
||||
this.calibrationResults[point] = result;
|
||||
|
||||
if (this.CanCalibrate)
|
||||
{
|
||||
this.CanCalibrate
|
||||
= result != null
|
||||
&& result.Succeeded
|
||||
&& result.Control == ChamberCalibration.TEST_COMPLETED;
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddInspectionVolume(OmniPlusInspectionPoint point, double volume)
|
||||
=> this.inspectionPoints[point] = volume;
|
||||
|
||||
internal double CalculateCorrectionFactor()
|
||||
{
|
||||
// TODO: calculate correction factor.
|
||||
return double.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace OmniPlus.UI.Inspection
|
||||
{
|
||||
public delegate void OmniPlusStateChangedEventHandler(int column, bool? succeeded, string header, string value);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
namespace OmniPlus.Options
|
||||
{
|
||||
internal class OmniControlOptions
|
||||
{
|
||||
private readonly byte[] bits;
|
||||
|
||||
private OmniControlOptions(byte[] bits)
|
||||
=> this.bits = bits;
|
||||
|
||||
public bool E0Encryption => this.bits[0] == 1;
|
||||
|
||||
public bool E1Encryption => this.bits[1] == 1;
|
||||
|
||||
public bool E2Encryption => this.bits[2] == 1;
|
||||
|
||||
public bool ReturnResponse
|
||||
{
|
||||
get => this.bits[3] == 1;
|
||||
set => this.bits[3] = (byte)(value ? 1 : 0);
|
||||
}
|
||||
|
||||
public bool NFNetwork => this.bits[4] == 1;
|
||||
|
||||
public bool MultipleCommands
|
||||
{
|
||||
get => this.bits[5] == 1;
|
||||
set => this.bits[5] = (byte)(value ? 1 : 0);
|
||||
}
|
||||
|
||||
public bool LongControl
|
||||
{
|
||||
get => this.bits[6] == 1;
|
||||
set => this.bits[6] = (byte)(value ? 1 : 0);
|
||||
}
|
||||
|
||||
public bool MultipleFrames
|
||||
{
|
||||
get => this.bits[7] == 1;
|
||||
set => this.bits[7] = (byte)(value ? 1 : 0);
|
||||
}
|
||||
|
||||
public static implicit operator OmniControlOptions(byte controlByte)
|
||||
{
|
||||
var bits = new byte[8];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
bits[i] = (byte)((controlByte >> i) & 1);
|
||||
}
|
||||
|
||||
return new OmniControlOptions(bits);
|
||||
}
|
||||
|
||||
public static implicit operator byte (OmniControlOptions control)
|
||||
{
|
||||
var @byte = default(byte);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
@byte ^= (byte)(control.bits[i] << i);
|
||||
}
|
||||
|
||||
return @byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus.Options
|
||||
{
|
||||
public class SerialPortOptions
|
||||
{
|
||||
public SerialPortOptions()
|
||||
{
|
||||
this.BaudRate = BaudRate.K4800;
|
||||
this.DataBits = DataBits.X8;
|
||||
this.Parity = Parity.None;
|
||||
this.StopBits = StopBits.One;
|
||||
this.Handshake = Handshake.None;
|
||||
}
|
||||
|
||||
public string PortName { get; set; }
|
||||
|
||||
public BaudRate BaudRate { get; set; }
|
||||
|
||||
public Parity Parity { get; set; }
|
||||
|
||||
public DataBits DataBits { get; set; }
|
||||
|
||||
public StopBits StopBits { get; set; }
|
||||
|
||||
public Handshake Handshake { get; set; }
|
||||
|
||||
public bool RtsEnabled { get; set; }
|
||||
|
||||
public bool DtrEnabled { get; set; }
|
||||
|
||||
public string LogFile { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
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("OmniPlus")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OmniPlus")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f8d84b9a-0fcf-4083-b067-8c39b7314152")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends <see cref="SIRTMessage"/>.
|
||||
/// </summary>
|
||||
public interface IMessageSender
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends <see cref="SIRTMessage"/>.
|
||||
/// </summary>
|
||||
/// <param name="message"> - to send.</param>
|
||||
void SendMessage(SIRTMessage message);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// This interface holds the shared endpoints iplemented as well in the SignalR Hubs as in the clients.
|
||||
/// </summary>
|
||||
public interface ISIRTBroadcaster : IMessageSender, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Receives <see cref="SIRTMessage"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">- to receive.</param>
|
||||
void MessageReceived(SIRTMessage message);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public interface ISIRTBroadcasterClient : IMessageSender, IDisposable
|
||||
{
|
||||
event Action<uint> UnitDetected;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// SIRT broadcaster host interface.
|
||||
/// </summary>
|
||||
public interface ISIRTBroadcasterHost : IMessageSender, IDisposable
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("SIRTBroadcaster.Abstraction")]
|
||||
[assembly: AssemblyDescription("Shared library between SignalR hubs and desktop clients.")]
|
||||
[assembly: AssemblyCompany("SENSUS - a Xylem brand.")]
|
||||
[assembly: AssemblyProduct("SIRTBroadcaster.Abstraction")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("c27ba66c-c3a7-48a2-a644-cba77e28e531")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
public class SIRTConnection : SIRTModel
|
||||
{
|
||||
public string SirtPort { get; set; }
|
||||
|
||||
public override bool Equals(object other)
|
||||
=> other?.GetHashCode() == this.GetHashCode();
|
||||
|
||||
public override int GetHashCode()
|
||||
=> this.SirtId?.GetHashCode() ?? 0;
|
||||
|
||||
public override string ToString()
|
||||
=> this.SirtId;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public static class SIRTExtensions
|
||||
{
|
||||
public static byte[] ToByteArray(this SIRTMessage message)
|
||||
{
|
||||
var length = 12 + message.DataLength;
|
||||
var bytes = new byte[length];
|
||||
|
||||
bytes[0] = message.StartByte;
|
||||
bytes[1] = message.MessageType;
|
||||
bytes[2] = message.Parameter1;
|
||||
bytes[3] = message.Parameter2;
|
||||
|
||||
/// TODO: see if radio address is correct hinzugefügt.
|
||||
/// Copying address bytes to the message bytes.
|
||||
/// Index 4 <=> 7.
|
||||
BitConverter
|
||||
.GetBytes(message.Address)
|
||||
.Reverse()
|
||||
.ToArray()
|
||||
.CopyTo(bytes, 4);
|
||||
|
||||
bytes[8] = message.DataLength;
|
||||
|
||||
/// Copying data bytes to the message bytes.
|
||||
/// Index 9 <=> <see cref="SIRTMessage.DataLength"/>.
|
||||
message.Data.CopyTo(bytes, 9);
|
||||
|
||||
/// TODO: see if CRC is correct hinzugefügt.
|
||||
bytes
|
||||
.CalculateCRC(1, (ushort)(length - 4))
|
||||
.Reverse()
|
||||
.ToArray()
|
||||
.CopyTo(bytes, length - 3);
|
||||
|
||||
bytes[length - 1] = message.StopByte;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte[] CalculateCRC(this byte[] data, ushort start, ushort length)
|
||||
{
|
||||
var ui_index = start;
|
||||
var test = default(byte);
|
||||
var zeichen = default(byte);
|
||||
var crc_result = ushort.MaxValue;
|
||||
|
||||
if (data.Length >= length + start)
|
||||
{
|
||||
while (ui_index < length + start)
|
||||
{
|
||||
zeichen = data[ui_index];
|
||||
ui_index++;
|
||||
|
||||
for (byte 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 BitConverter.GetBytes(crc_result);
|
||||
}
|
||||
|
||||
public static ushort ToUInt16(this byte[] data, int startIndex)
|
||||
{
|
||||
return BitConverter.ToUInt16(new byte[]
|
||||
{
|
||||
data[startIndex + 1],
|
||||
data[startIndex],
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public static uint ToUInt32(this byte[] data, int startIndex, bool reverced = true)
|
||||
{
|
||||
if (reverced)
|
||||
{
|
||||
return BitConverter.ToUInt32(new byte[]
|
||||
{
|
||||
data[startIndex + 3],
|
||||
data[startIndex + 2],
|
||||
data[startIndex + 1],
|
||||
data[startIndex],
|
||||
}, 0);
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt32(data, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant variables used in both SignalR and desctop clients.
|
||||
/// </summary>
|
||||
public class SIRTFixed
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for naming the SignalR hub as well as for building IHubProxy for the desctop clients.
|
||||
/// </summary>
|
||||
public const string SIRT_HUB = "SIRTBroadcaster";
|
||||
|
||||
public const string SIRT_URL = "http://sla12iis01.emea.sensus.net/LaaProductionWeb"; // "http://localhost:52822/";
|
||||
|
||||
public const byte FromAir = 0x11;
|
||||
|
||||
public const byte LastCMD = 0x12;
|
||||
|
||||
public const byte Debug = 0x14;
|
||||
|
||||
public const byte StopByte = 0x16;
|
||||
|
||||
public const byte StartSIRT2PC = 0xFF;
|
||||
|
||||
public const byte StartPC2SIRT = 0x55;
|
||||
|
||||
public const byte WritePAM = 0x81;
|
||||
|
||||
public const byte ReadPAM = 0x82;
|
||||
|
||||
public const byte WriteRegister = 0x84;
|
||||
|
||||
public const byte ReadRegister = 0x87;
|
||||
|
||||
public const byte WriteRAC = 0x88;
|
||||
|
||||
public const byte ReadRAC = 0x8B;
|
||||
|
||||
public const byte AddressLength = 4;
|
||||
|
||||
public const byte CRCLength = 2;
|
||||
|
||||
public const byte OxOO = 0x00;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Generic SIRT message.
|
||||
/// Keeped simple in order to be serialized (to) and deserialized (from) as JSON or other formats.
|
||||
/// <list type="number">
|
||||
/// <listheader>It has always the same structure:</listheader>
|
||||
/// <item>[0] - Start byte.</item>
|
||||
/// <item>[1] - Message type.</item>
|
||||
/// <item>[2] - Parameter 1.</item>
|
||||
/// <item>[3] - Parameter 2.</item>
|
||||
/// <item>[4 .. 7] - Radio address.</item>
|
||||
/// <item>[8] - Data length.</item>
|
||||
/// <item>[9 .. n] - Data bytes.</item>
|
||||
/// <item>[9 + n .. 9 + n + 2] - CRC check sum.</item>
|
||||
/// <item>[9 + n + 3] - Stop byte.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public class SIRTMessage : SIRTModel
|
||||
{
|
||||
/// <summary>
|
||||
/// <list type="bullet">
|
||||
/// <listheader>Describes the message direction:</listheader>
|
||||
/// <item>PC -> SIRT always = 0x55.</item>
|
||||
/// <item>SIRT -> PC always = 0xFF.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public byte StartByte { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <list type="bullet">
|
||||
/// <listheader>Describes the message type:</listheader>
|
||||
/// <item>Write PAM = 0x81.</item>
|
||||
/// <item>Read PAM = 0x82.</item>
|
||||
/// <item>Write RAC = 0x88.</item>
|
||||
/// <item>Read RAC = 0x8B.</item>
|
||||
/// <item>Write SIRT = 0x84.</item>
|
||||
/// <item>Read SIRT = 0x87.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public byte MessageType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public byte Parameter1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public byte Parameter2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The radio address as Uint32 converted as follows:
|
||||
/// <para />
|
||||
/// <code>uint address = BitConverter.ToUInt32(new byte[] { 0x00, 0x00, 0x00, 0x20 }, 0); // => 536870912.</code>
|
||||
/// <para />
|
||||
/// <code>byte[] addressBytes = BitConverter.GetBytes(address); // => new byte[] { 0x00, 0x00, 0x00, 0x20 }.</code>
|
||||
/// <para>Note: From and to SIRT address bytes are reversed and are looking like that - new byte[] { 0x20, 0x00, 0x00, 0x00 }</para>
|
||||
/// </summary>
|
||||
public uint Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the following data bytes.
|
||||
/// Not longer than 128.
|
||||
/// </summary>
|
||||
public byte DataLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public byte[] Data { get; set; } = new byte[0];
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public byte[] CRC { get; set; } = new byte[2];
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public byte StopByte { get; set; } = SIRTFixed.StopByte;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public DateTime TimeStamp { get; set; } = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction
|
||||
{
|
||||
public class SIRTModel
|
||||
{
|
||||
public string SirtId { get; set; }
|
||||
|
||||
public short SirtRF { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net481" />
|
||||
</packages>
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace SIRTBroadcaster.Client.Messages.FromAir
|
||||
{
|
||||
public class BUP
|
||||
{
|
||||
public byte AppCode { get; set; }
|
||||
|
||||
public byte Counter { get; set; }
|
||||
|
||||
public uint Address { get; set; }
|
||||
|
||||
public uint BillingVolume { get; set; }
|
||||
|
||||
public byte Alarm { get; set; }
|
||||
|
||||
public ushort CRC { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
namespace SIRTBroadcaster.Client.Messages.FromAir
|
||||
{
|
||||
public class DEBUG
|
||||
{
|
||||
public byte Length { get; set; }
|
||||
|
||||
public byte AppCode { get; set; }
|
||||
|
||||
public byte Counter { get; set; }
|
||||
|
||||
public uint Address { get; set; }
|
||||
|
||||
public byte DebugType { get; set; }
|
||||
|
||||
public byte MeterType { get; set; }
|
||||
|
||||
public byte VersionRadioFW { get; set; }
|
||||
|
||||
public byte VersionFW { get; set; }
|
||||
|
||||
public ushort RevisionFW { get; set; }
|
||||
|
||||
public byte VersionHW { get; set; }
|
||||
|
||||
public byte FactoryState { get; set; }
|
||||
|
||||
public uint PcbId { get; set; }
|
||||
|
||||
public byte Temperatur { get; set; }
|
||||
|
||||
public ushort BatteryV { get; set; }
|
||||
|
||||
public byte WakeUpInterval { get; set; }
|
||||
|
||||
public byte TXPowerRF { get; set; }
|
||||
|
||||
public byte TXPowerFlex { get; set; }
|
||||
|
||||
public ushort OffsetRF { get; set; }
|
||||
|
||||
public byte RebootCount { get; set; }
|
||||
|
||||
public byte WatchdogCount { get; set; }
|
||||
|
||||
public uint BatterySeconds { get; set; }
|
||||
|
||||
public byte MeterSampleRate { get; set; }
|
||||
|
||||
public byte HistoryScale { get; set; }
|
||||
|
||||
public byte RegisterMode { get; set; }
|
||||
|
||||
public byte HistorySize { get; set; }
|
||||
|
||||
public byte FactoryCalibration { get; set; }
|
||||
|
||||
public byte MeterSize { get; set; }
|
||||
|
||||
public uint VolumeLED { get; set; }
|
||||
|
||||
public uint Volume { get; set; }
|
||||
|
||||
public uint OffsetFactor { get; set; }
|
||||
|
||||
public byte OffsetTime { get; set; }
|
||||
|
||||
public ushort CRC { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
namespace SIRTBroadcaster.Client.Messages.FromAir
|
||||
{
|
||||
public class SEMI
|
||||
{
|
||||
public byte Length { get; set; }
|
||||
|
||||
public byte AppCode { get; set; }
|
||||
|
||||
public byte Counter { get; set; }
|
||||
|
||||
public uint Address { get; set; }
|
||||
|
||||
public uint BillingVolume { get; set; }
|
||||
|
||||
public byte Alarm { get; set; }
|
||||
|
||||
public byte PamStatus { get; set; }
|
||||
|
||||
public byte PamRSSI { get; set; }
|
||||
|
||||
public byte MeterType { get; set; }
|
||||
|
||||
public ushort TransmissionInterval { get; set; }
|
||||
|
||||
public byte LatInterval { get; set; }
|
||||
|
||||
public ushort CurrentFlow { get; set; }
|
||||
|
||||
public uint BackwardVolume { get; set; }
|
||||
|
||||
public byte NumberOfDials { get; set; }
|
||||
|
||||
public byte VolumUnit { get; set; }
|
||||
|
||||
public uint MeterId { get; set; }
|
||||
|
||||
public byte OMStatus { get; set; }
|
||||
|
||||
public ushort OMTransmissionInterval { get; set; }
|
||||
|
||||
public byte AlarmMaskActiveInfo { get; set; }
|
||||
|
||||
public byte LeakageDetectionParams { get; set; }
|
||||
|
||||
public byte BrokenPipeDetectionParams { get; set; }
|
||||
|
||||
public ushort BatteryRemaining { get; set; }
|
||||
|
||||
public ushort BatteryEndDetected { get; set; }
|
||||
|
||||
public ushort MaxFlow { get; set; }
|
||||
|
||||
public ushort MaxFlowTime { get; set; }
|
||||
|
||||
public ushort LowBatteryDetected { get; set; }
|
||||
|
||||
public ushort LeakStart { get; set; }
|
||||
|
||||
public ushort LeakEnd { get; set; }
|
||||
|
||||
public ushort MagneticTamperStart { get; set; }
|
||||
|
||||
public ushort MagneticTamperEnd { get; set; }
|
||||
|
||||
public ushort ModuleRemoveStart { get; set; }
|
||||
|
||||
public ushort ModuleRemoveEnd { get; set; }
|
||||
|
||||
public ushort BackflowStart { get; set; }
|
||||
|
||||
public ushort BackflowEnd { get; set; }
|
||||
|
||||
public ushort BrokenPipeStart { get; set; }
|
||||
|
||||
public ushort BrokenPipeEnd { get; set; }
|
||||
|
||||
public ushort LogContent { get; set; }
|
||||
|
||||
public ushort LoggingInterval { get; set; }
|
||||
|
||||
public ushort FixedDateReadingContent { get; set; }
|
||||
|
||||
public byte BillingDay { get; set; }
|
||||
|
||||
public uint ActualDateTime { get; set; }
|
||||
|
||||
public byte HistoryErrorLimitInDays { get; set; }
|
||||
|
||||
public string CustomerText { get; set; }
|
||||
|
||||
public ushort TimeOfFDRReset { get; set; }
|
||||
|
||||
public ushort TimeOfLogReset { get; set; }
|
||||
|
||||
public byte MeterSize { get; set; }
|
||||
|
||||
public ushort CRC { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
namespace SIRTBroadcaster.Client
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction;
|
||||
using SIRTBroadcaster.Client.Messages.FromAir;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
|
||||
public partial class Payload
|
||||
{
|
||||
private readonly ConcurrentStack<BUP> bups;
|
||||
private readonly ConcurrentStack<DEBUG> debugs;
|
||||
private readonly ConcurrentStack<SEMI> semis;
|
||||
private readonly string sirtId;
|
||||
private readonly uint address;
|
||||
|
||||
public Payload(string sirtId, uint address)
|
||||
{
|
||||
this.sirtId = sirtId;
|
||||
this.address = address;
|
||||
|
||||
this.bups = new ConcurrentStack<BUP>();
|
||||
this.debugs = new ConcurrentStack<DEBUG>();
|
||||
this.semis = new ConcurrentStack<SEMI>();
|
||||
}
|
||||
|
||||
public event Action<BUP> NewBUP;
|
||||
public event Action<DEBUG> NewDEBUG;
|
||||
public event Action<SEMI> NewSEMI;
|
||||
|
||||
public BUP LastBUP => this.bups.TryPeek(out var bup) ? bup : new BUP();
|
||||
|
||||
public DEBUG LastDEBUG => this.debugs.TryPeek(out var debug) ? debug : new DEBUG();
|
||||
|
||||
public SEMI LastSEMI => this.semis.TryPeek(out var semi) ? semi : new SEMI();
|
||||
|
||||
internal void AddBUP(SIRTMessage message)
|
||||
{
|
||||
var data = message.Data;
|
||||
var bup = new BUP
|
||||
{
|
||||
AppCode = data[0],
|
||||
Counter = data[1],
|
||||
Address = data.ToUInt32(2),
|
||||
BillingVolume = data.ToUInt32(6),
|
||||
Alarm = data[10],
|
||||
CRC = data.ToUInt16(11),
|
||||
};
|
||||
|
||||
this.bups.Push(bup);
|
||||
this.NewBUP?.Invoke(bup);
|
||||
}
|
||||
|
||||
internal void AddDEBUG(SIRTMessage message)
|
||||
{
|
||||
var data = message.Data;
|
||||
var debug = new DEBUG
|
||||
{
|
||||
Length = data[0],
|
||||
AppCode = data[1],
|
||||
Counter = data[2],
|
||||
Address = data.ToUInt32(3),
|
||||
DebugType = data[7],
|
||||
MeterType = data[8],
|
||||
VersionRadioFW = data[9],
|
||||
VersionFW = data[10],
|
||||
RevisionFW = data.ToUInt16(11),
|
||||
VersionHW = data[13],
|
||||
FactoryState = data[14],
|
||||
PcbId = data.ToUInt32(15),
|
||||
Temperatur = data[19],
|
||||
BatteryV = data.ToUInt16(20),
|
||||
WakeUpInterval = data[22],
|
||||
TXPowerRF = data[23],
|
||||
TXPowerFlex = data[24],
|
||||
OffsetRF = data.ToUInt16(25),
|
||||
RebootCount = data[27],
|
||||
WatchdogCount = data[28],
|
||||
BatterySeconds = data.ToUInt32(29),
|
||||
MeterSampleRate = data[33],
|
||||
HistoryScale = data[34],
|
||||
RegisterMode = data[35],
|
||||
HistorySize = data[36],
|
||||
FactoryCalibration = data[37],
|
||||
MeterSize = data[38],
|
||||
VolumeLED = data.ToUInt32(39),
|
||||
Volume = data.ToUInt32(43),
|
||||
OffsetFactor = data.ToUInt32(47),
|
||||
OffsetTime = data[51]
|
||||
};
|
||||
|
||||
if (data.Length == 53)
|
||||
{
|
||||
debug.CRC = data.ToUInt16(52);
|
||||
}
|
||||
|
||||
this.debugs.Push(debug);
|
||||
this.NewDEBUG?.Invoke(debug);
|
||||
}
|
||||
|
||||
internal void AddSEMI(SIRTMessage message)
|
||||
{
|
||||
var data = message.Data;
|
||||
var semi = new SEMI
|
||||
{
|
||||
Length = data[0],
|
||||
AppCode = data[1],
|
||||
Counter = data[2],
|
||||
Address = data.ToUInt32(3),
|
||||
BillingVolume = data.ToUInt32(7),
|
||||
Alarm = data[11],
|
||||
PamStatus = data[12],
|
||||
PamRSSI = data[13],
|
||||
MeterType = data[14],
|
||||
TransmissionInterval = data.ToUInt16(15),
|
||||
LatInterval = data[17],
|
||||
CurrentFlow = data.ToUInt16(18),
|
||||
BackwardVolume = data.ToUInt32(20),
|
||||
NumberOfDials = data[24],
|
||||
VolumUnit = data[25],
|
||||
MeterId = data.ToUInt32(26),
|
||||
OMStatus = data[30],
|
||||
OMTransmissionInterval = data.ToUInt16(31),
|
||||
AlarmMaskActiveInfo = data[33],
|
||||
LeakageDetectionParams = data[34],
|
||||
BrokenPipeDetectionParams = data[35],
|
||||
BatteryRemaining = data.ToUInt16(36),
|
||||
BatteryEndDetected = data.ToUInt16(38),
|
||||
MaxFlow = data.ToUInt16(40),
|
||||
MaxFlowTime = data.ToUInt16(42),
|
||||
LowBatteryDetected = data.ToUInt16(44),
|
||||
LeakStart = data.ToUInt16(46),
|
||||
LeakEnd = data.ToUInt16(48),
|
||||
MagneticTamperStart = data.ToUInt16(50),
|
||||
MagneticTamperEnd = data.ToUInt16(52),
|
||||
ModuleRemoveStart = data.ToUInt16(54),
|
||||
ModuleRemoveEnd = data.ToUInt16(56),
|
||||
BackflowStart = data.ToUInt16(58),
|
||||
BackflowEnd = data.ToUInt16(60),
|
||||
BrokenPipeStart = data.ToUInt16(62),
|
||||
BrokenPipeEnd = data.ToUInt16(64),
|
||||
LogContent = data.ToUInt16(66),
|
||||
LoggingInterval = data.ToUInt16(68),
|
||||
FixedDateReadingContent = data.ToUInt16(70),
|
||||
BillingDay = data[72],
|
||||
ActualDateTime = data.ToUInt32(73),
|
||||
HistoryErrorLimitInDays = data[77],
|
||||
CustomerText = Encoding.UTF8.GetString(new byte[]
|
||||
{
|
||||
data[78],
|
||||
data[79],
|
||||
data[80],
|
||||
data[81],
|
||||
data[82],
|
||||
data[83],
|
||||
data[84],
|
||||
data[85],
|
||||
data[86],
|
||||
}),
|
||||
TimeOfFDRReset = data.ToUInt16(87),
|
||||
TimeOfLogReset = data.ToUInt16(89),
|
||||
MeterSize = data[91],
|
||||
};
|
||||
|
||||
if (data.Length == 93)
|
||||
{
|
||||
semi.CRC = data.ToUInt16(92);
|
||||
}
|
||||
|
||||
this.semis.Push(semi);
|
||||
this.NewSEMI?.Invoke(semi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Parameters
|
||||
{
|
||||
using static SIRTBroadcaster.Abstraction.SIRTFixed;
|
||||
|
||||
public struct LastCMD
|
||||
{
|
||||
private LastCMD(byte value)
|
||||
{
|
||||
this.Value = value;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case WritePAM: this.Name = nameof(WritePAM); break;
|
||||
case ReadPAM: this.Name = nameof(ReadPAM); break;
|
||||
case WriteRAC: this.Name = nameof(WriteRAC); break;
|
||||
case ReadRAC: this.Name = nameof(ReadRAC); break;
|
||||
case WriteRegister: this.Name = nameof(WriteRegister); break;
|
||||
case ReadRegister: this.Name = nameof(ReadRegister); break;
|
||||
default: this.Name = string.Empty; break;
|
||||
}
|
||||
}
|
||||
|
||||
public byte Value { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public static implicit operator LastCMD (byte value)
|
||||
=> new LastCMD(value);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Parameters
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction.Values;
|
||||
|
||||
/// <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 : Parameter
|
||||
{
|
||||
private P11(byte value) : base(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 0 - RF-Module1 is source || RF-Module2 is source
|
||||
/// </summary>
|
||||
public Bit SourceChannel => this.bits[0];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 1 - only one RF module data is valid || both RF module data are valid
|
||||
/// </summary>
|
||||
public Bit AreBothValid => this.bits[1];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 2 - RF-Module1 data is valid || RF-Module1 data is invalid
|
||||
/// </summary>
|
||||
public Bit InvalidModule1 => this.bits[2];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 3 - RF-Module2 data is valid || RF-Module2 data is invalid
|
||||
/// </summary>
|
||||
public Bit InvalidModule2 => this.bits[3];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 4 - all ok || invalid -> module detects length > 128
|
||||
/// </summary>
|
||||
public Bit Overflow => this.bits[4];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 5 - no attention for PAM / RAC || will look at PAM / RAC Pool
|
||||
/// </summary>
|
||||
public Bit Attention => this.bits[5];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 6 -
|
||||
/// If .modeSensus = 0 wireless M-busMode
|
||||
/// 0: S1 - Mode
|
||||
/// 1: T1 - Mode
|
||||
/// If.modeSensus = 1 SensusRF
|
||||
/// 0: receive at f1
|
||||
/// 1: receive at f2
|
||||
/// </summary>
|
||||
public Bit ModeRF => this.bits[6];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 7 - wireless M-Bus Mode || Sensus RF Mode
|
||||
/// </summary>
|
||||
public Bit ModeSensus => this.bits[7];
|
||||
|
||||
public static implicit operator P11(byte value)
|
||||
=> new P11(value);
|
||||
|
||||
public static implicit operator byte(P11 parameter)
|
||||
=> parameter.value;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Parameters
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction.Values;
|
||||
|
||||
/// <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.
|
||||
/// NOTE: The bits of Parameter 12 are decoded as following, where Bit 0 is the least significant bit
|
||||
/// </summary>
|
||||
public class P12 : Parameter
|
||||
{
|
||||
private P12(byte value) : base(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 0 - ok || requested buffer is full or not available
|
||||
/// </summary>
|
||||
public Bit IsBufferFull => this.bits[0];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 1 - ok || operating system is busy
|
||||
/// </summary>
|
||||
public Bit IsOSBusy => this.bits[1];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 2 - ok || wrong CRC recognized
|
||||
/// </summary>
|
||||
public Bit IsWrongCRC => this.bits[2];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 3 - ok || command cannot be executed
|
||||
/// </summary>
|
||||
public Bit IsCmdNotExecuted => this.bits[3];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 4 - ok || telegram / command byte unknown
|
||||
/// </summary>
|
||||
public Bit IsCmdUnknown => this.bits[4];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 5 - ok || no such entry found
|
||||
/// </summary>
|
||||
public Bit IsEntryNotFound => this.bits[5];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 6 - ok || unknown fixed byte
|
||||
/// </summary>
|
||||
public Bit HasUnknownByte => this.bits[6];
|
||||
|
||||
/// <summary>
|
||||
/// Bit: 7 - normal address || address was 0xFFFFFFFF
|
||||
/// </summary>
|
||||
public Bit IsWildcardAddress => this.bits[7];
|
||||
|
||||
public static implicit operator P12 (byte value)
|
||||
=> new P12(value);
|
||||
|
||||
public static implicit operator byte (P12 parameter)
|
||||
=> parameter.value;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Parameters
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction.Values;
|
||||
|
||||
public abstract class Parameter
|
||||
{
|
||||
protected readonly byte value;
|
||||
protected readonly Bit[] bits;
|
||||
|
||||
protected Parameter(byte value)
|
||||
{
|
||||
this.value = value;
|
||||
this.bits = new Bit[8];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
this.bits[i] = (byte)(value >> i & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Parameters
|
||||
{
|
||||
public struct RSSI
|
||||
{
|
||||
public RSSI(short rf, byte value)
|
||||
{
|
||||
this.Value = 0;
|
||||
this.Percent = 0;
|
||||
|
||||
if (rf == 433)
|
||||
{
|
||||
this.Value = (sbyte)(0.5 * value - 140);
|
||||
this.Percent = (float)(-40.316 + 0.66 * value);
|
||||
}
|
||||
else if (rf == 433)
|
||||
{
|
||||
this.Value = (sbyte)(0.5 * value - 131.3);
|
||||
this.Percent = (float)(-57.6667 + 0.7333 * value);
|
||||
}
|
||||
|
||||
if (this.Percent < 0)
|
||||
{
|
||||
this.Percent = 0;
|
||||
}
|
||||
else if (this.Percent > 100)
|
||||
{
|
||||
this.Percent = 100;
|
||||
}
|
||||
}
|
||||
|
||||
public sbyte Value { get; }
|
||||
|
||||
public float Percent { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("SIRTBroadcaster.Client")]
|
||||
[assembly: AssemblyDescription("Shared library between SignalR hubs and desktop clients.")]
|
||||
[assembly: AssemblyCompany("SENSUS - a Xylem brand.")]
|
||||
[assembly: AssemblyProduct("SIRTBroadcaster.Client")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("4221f992-599e-498c-a409-6d1e70e0a6f9")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,76 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4221F992-599E-498C-A409-6D1E70E0A6F9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SIRTBroadcaster.Client</RootNamespace>
|
||||
<AssemblyName>SIRTBroadcaster.Client</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=2.4.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.2.4.3\lib\net45\Microsoft.AspNet.SignalR.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Messages\FromAir\BUP.cs" />
|
||||
<Compile Include="Messages\FromAir\DEBUG.cs" />
|
||||
<Compile Include="Parameters\LastCMD.cs" />
|
||||
<Compile Include="Parameters\P11.cs" />
|
||||
<Compile Include="Parameters\P12.cs" />
|
||||
<Compile Include="Parameters\Parameter.cs" />
|
||||
<Compile Include="Parameters\RSSI.cs" />
|
||||
<Compile Include="Messages\Payload.cs" />
|
||||
<Compile Include="Messages\FromAir\SEMI.cs" />
|
||||
<Compile Include="SIRTBroadcasterClient.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Values\Bit.cs" />
|
||||
<Compile Include="Values\RadioAddress.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SIRTBroadcaster.Abstraction\SIRTBroadcaster.Abstraction.csproj">
|
||||
<Project>{C27BA66C-C3A7-48A2-A644-CBA77E28E531}</Project>
|
||||
<Name>SIRTBroadcaster.Abstraction</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,180 +0,0 @@
|
||||
namespace SIRTBroadcaster.Client
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction;
|
||||
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
|
||||
public interface ISIRTBroadcasterSignalRClient : ISIRTBroadcasterClient
|
||||
{
|
||||
bool TryGetPayload(string sirtId, uint address, out Payload payload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements a SignalR client connection.
|
||||
/// </summary>
|
||||
public class SIRTBroadcasterClient : ISIRTBroadcaster, ISIRTBroadcasterSignalRClient
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, ConcurrentDictionary<uint, Payload>> payloads;
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private readonly ICollection<IDisposable> disposables;
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private readonly HubConnection hubConnection;
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private readonly IHubProxy hubProxy;
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private bool hubConnected;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
public SIRTBroadcasterClient(params string[] sirts)
|
||||
{
|
||||
this.payloads = new ConcurrentDictionary<string, ConcurrentDictionary<uint, Payload>>
|
||||
(collection: sirts.ToDictionary(x => x, _ => new ConcurrentDictionary<uint, Payload>()));
|
||||
this.hubConnection = new HubConnection(SIRTFixed.SIRT_URL);
|
||||
this.hubProxy = this.hubConnection.CreateHubProxy(SIRTFixed.SIRT_HUB);
|
||||
this.disposables = new List<IDisposable>();
|
||||
|
||||
this.ConfigureHubConnection();
|
||||
}
|
||||
|
||||
public event Action<UInt32> UnitDetected;
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all disposables in this instance and clears all collections.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var disposable in this.disposables)
|
||||
{
|
||||
disposable?.Dispose();
|
||||
}
|
||||
|
||||
this.disposables.Clear();
|
||||
|
||||
this.hubConnection.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO: Exception logging.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives messages from the SignalR hub connection.
|
||||
/// Under different checks the received messages are added to the payloads collection.
|
||||
/// Afterword is the <see cref="UnitDetected"/> event triggered if received message is a BUP.
|
||||
/// </summary>
|
||||
/// <param name="message"> - received <see cref="SIRTMessage"/>.</param>
|
||||
public void MessageReceived(SIRTMessage message)
|
||||
{
|
||||
if (message is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var sirtId = message.SirtId;
|
||||
var address = message.Address;
|
||||
var payload = this.payloads
|
||||
.GetOrAdd(sirtId, new ConcurrentDictionary<uint, Payload>())
|
||||
.GetOrAdd(address, new Payload(sirtId, address));
|
||||
|
||||
if (message.MessageType == SIRTFixed.FromAir)
|
||||
{
|
||||
var length = message.DataLength;
|
||||
|
||||
if (length == 13)
|
||||
{
|
||||
payload.AddBUP(message);
|
||||
|
||||
this.UnitDetected?.Invoke(address);
|
||||
}
|
||||
else if (length >= 51 && 53 <= length)
|
||||
{
|
||||
payload.AddDEBUG(message);
|
||||
}
|
||||
else if (length >= 91 && 93 <= length)
|
||||
{
|
||||
payload.AddSEMI(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Do smething !?.
|
||||
}
|
||||
}
|
||||
else if (message.MessageType == SIRTFixed.LastCMD)
|
||||
{
|
||||
|
||||
}
|
||||
else if (message.MessageType == SIRTFixed.Debug)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message to the hub.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void SendMessage(SIRTMessage message)
|
||||
{
|
||||
if (this.hubConnected)
|
||||
{
|
||||
this.hubProxy.Invoke(nameof(ISIRTBroadcaster.SendMessage), message);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetPayload(string sirtId, uint address, out Payload payload)
|
||||
{
|
||||
payload = payload = this.payloads
|
||||
.GetOrAdd(sirtId, new ConcurrentDictionary<uint, Payload>())
|
||||
.GetOrAdd(address, new Payload(sirtId, address));
|
||||
|
||||
return payload != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Add description ...
|
||||
/// </summary>
|
||||
private void ConfigureHubConnection()
|
||||
{
|
||||
this.disposables.Add(this.hubProxy.On<SIRTMessage>(nameof(ISIRTBroadcaster.MessageReceived), this.MessageReceived));
|
||||
|
||||
this.hubConnection.StateChanged += (args) =>
|
||||
{
|
||||
this.hubConnected = args.NewState == ConnectionState.Connected;
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
this.hubConnection
|
||||
.Start()
|
||||
.ConfigureAwait(true)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO: exception logging.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Values
|
||||
{
|
||||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
/// <summary>
|
||||
/// Bit is a custom value type.
|
||||
/// Is convertable from and to: byte, byte?, bool and bool?.
|
||||
/// By default returns null.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonBitConverter))]
|
||||
public struct Bit
|
||||
{
|
||||
private readonly byte? bit;
|
||||
|
||||
public Bit(byte? bit)
|
||||
=> this.bit = bit;
|
||||
|
||||
public override string ToString()
|
||||
=> bit?.ToString();
|
||||
|
||||
public static implicit operator Bit (byte? bit)
|
||||
=> new Bit(bit);
|
||||
|
||||
public static implicit operator Bit (byte bit)
|
||||
=> new Bit(bit);
|
||||
|
||||
public static implicit operator Bit (bool bit)
|
||||
=> new Bit((byte?)(bit ? 1 : 0));
|
||||
|
||||
public static implicit operator Bit (bool? bit)
|
||||
=> new Bit(bit == null ? null : (byte?)(bit == true ? 1 : 0));
|
||||
|
||||
public static implicit operator byte (Bit bit)
|
||||
=> bit.bit ?? 0;
|
||||
|
||||
public static implicit operator byte? (Bit bit)
|
||||
=> bit.bit;
|
||||
|
||||
public static implicit operator bool? (Bit bit)
|
||||
{
|
||||
if (bit.bit.HasValue)
|
||||
{
|
||||
return bit.bit == 1;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonBitConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (existingValue is Bit value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return default(byte);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is Bit existingValue)
|
||||
{
|
||||
writer.WriteValue((byte)existingValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
namespace SIRTBroadcaster.Abstraction.Values
|
||||
{
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[JsonConverter(typeof(RadioAddressConverter))]
|
||||
public struct RadioAddress : IEnumerable<byte>
|
||||
{
|
||||
private readonly uint radioAddress;
|
||||
private readonly byte[] addressBytes;
|
||||
|
||||
public RadioAddress(uint radioAddress)
|
||||
{
|
||||
this.radioAddress = radioAddress;
|
||||
|
||||
var bytes = BitConverter.GetBytes(radioAddress);
|
||||
|
||||
this.addressBytes = new byte[]
|
||||
{
|
||||
bytes[3],
|
||||
bytes[2],
|
||||
bytes[1],
|
||||
bytes[0],
|
||||
};
|
||||
}
|
||||
|
||||
public RadioAddress(byte[] addressBytes)
|
||||
{
|
||||
this.addressBytes = addressBytes;
|
||||
this.radioAddress = BitConverter.ToUInt32(addressBytes, 0);
|
||||
}
|
||||
|
||||
public int Length => this.addressBytes.Length;
|
||||
|
||||
public IEnumerator<byte> GetEnumerator()
|
||||
{
|
||||
foreach (var @byte in this.addressBytes)
|
||||
{
|
||||
yield return @byte;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> this.GetEnumerator();
|
||||
|
||||
public static implicit operator RadioAddress (uint radioAddress)
|
||||
=> new RadioAddress(radioAddress);
|
||||
|
||||
public static implicit operator uint (RadioAddress radioAddress)
|
||||
=> radioAddress.radioAddress;
|
||||
|
||||
public static implicit operator RadioAddress (byte[] addressBytes)
|
||||
=> new RadioAddress(addressBytes);
|
||||
|
||||
public static implicit operator byte[] (RadioAddress radioAddress)
|
||||
=> radioAddress.addressBytes;
|
||||
}
|
||||
|
||||
public class RadioAddressConverter : JsonConverter
|
||||
{
|
||||
public override Boolean CanConvert(Type type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (existingValue is RadioAddress radioAddress)
|
||||
{
|
||||
return radioAddress;
|
||||
}
|
||||
|
||||
return default(uint);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is RadioAddress radioAddress)
|
||||
{
|
||||
writer.WriteValue((uint)radioAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.SignalR.Client" version="2.4.3" targetFramework="net481" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net481" />
|
||||
</packages>
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace SIRTBroadcaster.Host
|
||||
{
|
||||
using SIRTBroadcaster.Abstraction;
|
||||
|
||||
using System;
|
||||
|
||||
internal interface ISIRTListener : IDisposable
|
||||
{
|
||||
event Action<SIRTMessage> MessageReceived;
|
||||
|
||||
SIRTConnection SIRTConnection { get; }
|
||||
|
||||
void SendData(SIRTMessage message);
|
||||
|
||||
void SendData(byte[] data);
|
||||
|
||||
bool StartListening();
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A9D1A99D-6E55-4394-86AD-B5C53E9225EB}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SIRTBroadcaster.Host</RootNamespace>
|
||||
<AssemblyName>SIRTBroadcaster.Host</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=2.4.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.2.4.3\lib\net45\Microsoft.AspNet.SignalR.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ISIRTListener.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SIRTBroadcasterHost.cs" />
|
||||
<Compile Include="SIRTListener.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SIRTBroadcaster.Abstraction\SIRTBroadcaster.Abstraction.csproj">
|
||||
<Project>{C27BA66C-C3A7-48A2-A644-CBA77E28E531}</Project>
|
||||
<Name>SIRTBroadcaster.Abstraction</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,153 +0,0 @@
|
||||
namespace SIRTBroadcaster.Host
|
||||
{
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
|
||||
using SIRTBroadcaster.Abstraction;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Implements a SignalR host connection.
|
||||
/// Operates from and to SIRT without saving any data.
|
||||
/// </summary>
|
||||
public class SIRTBroadcasterHost : ISIRTBroadcaster, ISIRTBroadcasterHost
|
||||
{
|
||||
/// <summary>
|
||||
/// This collection holds all signed events to the hub.
|
||||
/// On dispose they are also disposed.
|
||||
/// </summary>
|
||||
private readonly ICollection<IDisposable> disposables;
|
||||
/// <summary>
|
||||
/// SIRT listener object.
|
||||
/// </summary>
|
||||
private readonly ISIRTListener sirtListener;
|
||||
/// <summary>
|
||||
/// Hub connection object.
|
||||
/// </summary>
|
||||
private readonly HubConnection hubConnection;
|
||||
/// <summary>
|
||||
/// Hub proxy object. Handels the hub endpoints.
|
||||
/// </summary>
|
||||
private readonly IHubProxy hubProxy;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hub connection state.
|
||||
/// </summary>
|
||||
private bool hubConnected;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the SIRT connection state.
|
||||
/// </summary>
|
||||
private bool sirtConnected;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes all private members needed to start message handling.
|
||||
/// Starts a hub connection.
|
||||
/// Also starts sirt connection.
|
||||
/// </summary>
|
||||
/// <param name="sirtConnection"> - model containing informations about the sirt.</param>
|
||||
public SIRTBroadcasterHost(SIRTConnection sirtConnection)
|
||||
{
|
||||
this.disposables = new List<IDisposable>();
|
||||
this.sirtListener = new SIRTListener(sirtConnection);
|
||||
this.hubConnection = new HubConnection(SIRTFixed.SIRT_URL);
|
||||
this.hubProxy = this.hubConnection.CreateHubProxy(SIRTFixed.SIRT_HUB);
|
||||
|
||||
this.ConfigureHubConnection();
|
||||
this.ConfigureSIRTListener();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all disposables in this instance and clears all collections.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.sirtListener.Dispose();
|
||||
|
||||
foreach (var disposable in this.disposables)
|
||||
{
|
||||
disposable?.Dispose();
|
||||
}
|
||||
|
||||
this.disposables.Clear();
|
||||
|
||||
this.hubConnection.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO: Exception logging.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message to the SignalR hub if the hub is connected and the message is not null.
|
||||
/// </summary>
|
||||
/// <param name="message"> - to send.</param>
|
||||
public void MessageReceived(SIRTMessage message)
|
||||
{
|
||||
if (this.hubConnected && message != null)
|
||||
{
|
||||
this.hubProxy.Invoke(nameof(ISIRTBroadcaster.MessageReceived), message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message directly to the SIRT if the SIRT is connected and the message is not null.
|
||||
/// </summary>
|
||||
/// <param name="message"> - to send.</param>
|
||||
public void SendMessage(SIRTMessage message)
|
||||
{
|
||||
if (this.sirtConnected && message != null)
|
||||
{
|
||||
this.sirtListener.SendData(message.ToByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the hub connection.
|
||||
/// </summary>
|
||||
private void ConfigureHubConnection()
|
||||
{
|
||||
this.disposables.Add(this.hubProxy.On<SIRTMessage>(nameof(ISIRTBroadcaster.SendMessage), this.SendMessage));
|
||||
|
||||
this.hubConnection.StateChanged += (args) =>
|
||||
{
|
||||
this.hubConnected = args.NewState == ConnectionState.Connected;
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
this.hubConnection
|
||||
.Start()
|
||||
.ConfigureAwait(true)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO: exception logging.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the SIRT connection.
|
||||
/// </summary>
|
||||
private void ConfigureSIRTListener()
|
||||
{
|
||||
if (this.sirtListener.StartListening())
|
||||
{
|
||||
this.sirtListener.MessageReceived += this.MessageReceived;
|
||||
this.sirtListener.SendData(new byte[]
|
||||
{
|
||||
/// SIRT init string.
|
||||
0x55, 0x84, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x80, 0x01, 0x90, 0xA0, 0x16
|
||||
});
|
||||
|
||||
this.sirtConnected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user