Merge branch 'temperature_calibration' into 'main'

Temperature calibration

See merge request la_operations/laa_production!11
This commit is contained in:
Stoyan Zlatev
2023-09-04 12:43:00 +00:00
103 changed files with 46880 additions and 1228 deletions
+2 -2
View File
@@ -14,5 +14,5 @@ using System.Reflection;
//[assembly: AssemblyVersion("1.2.*.0")]
[assembly: AssemblyVersion("2.6.4.*")]
[assembly: AssemblyFileVersion("2.6.4.0")]
[assembly: AssemblyVersion("2.6.0.*")]
[assembly: AssemblyFileVersion("2.6.0.0")]
+9 -1
View File
@@ -155,11 +155,19 @@
</site>
<site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\laa_production\Common\Service\MeterProcessState" />
<virtualDirectory path="/" physicalPath="C:\Users\SZLATEV\source\repos\laa_production\Common\Service\MeterProcessState" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" />
</bindings>
</site>
<site name="TestMVC" id="3">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\Users\SZLATEV\source\repos\laa_production\Common\TestMVC" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:59615:localhost" />
</bindings>
</site>
<siteDefaults>
<!-- To enable logging, please change the below attribute "enabled" to "true" -->
+67 -67
View File
@@ -157,8 +157,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protocols", "Protocols", "{
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MjkControlledCodeRef", "MjkControlledCodeRef", "{B4F8545B-F379-42A5-BDE9-763FD7B79598}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "modbus_master_csharp", "..\..\..\MJK\Code\C#\modbus_master_csharp\src\modbus_master_csharp\modbus_master_csharp.csproj", "{F14940F8-3C86-4BB7-A915-B021E4B3052D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxToolBox", "Ui\MagFluxToolBox\MagFluxToolBox.csproj", "{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxConfig", "Hardware\WaterMeter\MagFlux\MagFluxConfig\MagFluxConfig.csproj", "{70398B99-B134-4BBD-968B-7399B70C3CE2}"
@@ -189,6 +187,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonMessurementUnits", "C
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
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4
@@ -3487,70 +3487,6 @@ Global
{35726BCF-975C-4B49-BEFA-C00D90394F1D}.XP32bit|x64.Build.0 = Release|Any CPU
{35726BCF-975C-4B49-BEFA-C00D90394F1D}.XP32bit|x86.ActiveCfg = Release|Any CPU
{35726BCF-975C-4B49-BEFA-C00D90394F1D}.XP32bit|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.Build.0 = Release|Any CPU
{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -4447,6 +4383,70 @@ Global
{AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x64.Build.0 = Release|Any CPU
{AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x86.ActiveCfg = Release|Any CPU
{AFC428F5-0141-4A3F-BEF2-470A89D972F6}.XP32bit|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.COM|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x64.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.ActiveCfg = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Debug|x86.Build.0 = Debug|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.PerformTest|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.Release|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.ReleaseTest|x86.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Any CPU.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x64.Build.0 = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.ActiveCfg = Release|Any CPU
{F14940F8-3C86-4BB7-A915-B021E4B3052D}.XP32bit|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -4517,7 +4517,6 @@ Global
{C9393A97-C0BB-4D59-A879-B572BE04CE15} = {5563DD3B-2287-4BED-97BF-F0389FF505AF}
{94579693-7AC6-4FF0-B540-1F3780E1BCFA} = {C9393A97-C0BB-4D59-A879-B572BE04CE15}
{B4F8545B-F379-42A5-BDE9-763FD7B79598} = {C9393A97-C0BB-4D59-A879-B572BE04CE15}
{F14940F8-3C86-4BB7-A915-B021E4B3052D} = {B4F8545B-F379-42A5-BDE9-763FD7B79598}
{A5E7CE52-3101-4E9B-B896-C2C0FADE4812} = {03D4F23E-7E4A-4091-BC96-036C996D351A}
{70398B99-B134-4BBD-968B-7399B70C3CE2} = {C9393A97-C0BB-4D59-A879-B572BE04CE15}
{B5DA260C-71CC-45CA-B79E-D1B376AF718C} = {C9393A97-C0BB-4D59-A879-B572BE04CE15}
@@ -4533,6 +4532,7 @@ Global
{FD30EB7A-7809-4E62-9374-791D31877D6D} = {696A94BE-7237-4AE2-9E36-6059DE519971}
{17C15B79-9A9E-4079-8FE2-0E563F18CA01} = {C17363DF-A043-4F25-8EBA-2B3B078227DC}
{AFC428F5-0141-4A3F-BEF2-470A89D972F6} = {C17363DF-A043-4F25-8EBA-2B3B078227DC}
{F14940F8-3C86-4BB7-A915-B021E4B3052D} = {B4F8545B-F379-42A5-BDE9-763FD7B79598}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164}
+117
View File
@@ -0,0 +1,117 @@
namespace CommonConsole
{
using System;
using System.Linq;
using System.Text;
public static class BitExtensions
{
public static byte[] GetBits(this byte[] bytes)
{
if (bytes is null)
{
return Array.Empty<byte>();
}
var bytesCount = bytes.Length;
var bitsCount = bytesCount * 8;
var bits = new byte[bitsCount];
var bit = 0;
foreach (var @byte in bytes)
{
for (int b = 7; b >= 0; b--)
{
bits[bit++] = (byte)((@byte >> b) % 2);
}
}
return bits;
}
public static byte[] GetBytes(this byte value, int take = 1)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this sbyte value, int take = 2)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this short value, int take = 2)
=> BitConverter.GetBytes(value).Take(2);
public static byte[] GetBytes(this ushort value, int take = 2)
=> BitConverter.GetBytes(value).Take(2);
public static byte[] GetBytes(this int value, int take = 4)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this uint value, int take = 4)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this long value, int take = 8)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this ulong value, int take = 8)
=> BitConverter.GetBytes(value).Take(take);
public static byte[] GetBytes(this double value)
=> BitConverter.GetBytes(value);
public static byte[] GetBytes(this string value)
=> Encoding.ASCII.GetBytes(value);
public static byte[] Swap(this byte[] bytes)
{
if (bytes is null)
{
return Array.Empty<byte>();
}
var length = bytes.Length;
var swapped = new byte[length];
for (int x = 0; x < length; x++)
{
swapped[x] = bytes[length - x - 1];
}
return swapped;
}
public static byte[] Take(this byte[] bytesSRC, int count)
{
if (bytesSRC is null || count < 0)
{
return Array.Empty<byte>();
}
var bytesDST = new byte[count];
Array.Copy(bytesSRC, 0, bytesDST, 0, count);
return bytesDST;
}
public static string ToHex(this byte[] value, string separator = " ")
{
if (value is null)
{
return string.Empty;
}
return BitConverter.ToString(value).Replace("-", separator);
}
public static byte[] FromHex(this string value, string separator = " ")
{
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty<byte>();
}
return value
.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => byte.TryParse(x, out byte b) ? b : default(byte))
.ToArray();
}
}
}
+12
View File
@@ -46,11 +46,22 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BitExtensions.cs" />
<Compile Include="ConfigurationJson.cs" />
<Compile Include="JsonConverters\CurrentConverter.cs" />
<Compile Include="JsonConverters\FlowConverter.cs" />
<Compile Include="JsonConverters\PressureConverter.cs" />
<Compile Include="JsonConverters\TemperatureConverter.cs" />
<Compile Include="JsonConverters\TimeConverter.cs" />
<Compile Include="JsonConverters\VolumeConverter.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Unit.cs" />
<Compile Include="Value.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="configuration.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
@@ -59,5 +70,6 @@
<Name>CommonMessurementUnits</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+330
View File
@@ -0,0 +1,330 @@
namespace CommonConsole
{
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
public class ConfigurationJson : Dictionary<string, Section>
{
public Section this[byte id]
=> this.Values.FirstOrDefault(x => x.Id == id)
?? new Section();
public new Section this[string key]
{
get
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Section name should not be null or white space!");
}
if (!this.TryGetValue(key, out var section))
{
section = new Section();
this[key] = section;
}
return section;
}
set
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Section name should not be null or white space!");
}
this[key] = value;
}
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext _)
{
foreach (var kvp in this)
{
kvp.Value.Name = kvp.Key;
}
}
}
public class Section
{
public byte Id { get; set; }
[JsonIgnore]
public string Name { get; internal set; }
public Version Version { get; set; }
public Registers Registers { get; set; }
public Status Status { get; set; }
public Register this[string key]
{
get
{
if (this.Registers is null)
{
return new Register();
}
return this.Registers[key];
}
set
{
if (this.Registers != null)
{
this.Registers[key] = value;
}
}
}
public Register this[byte id]
=> this.Registers?[id] ?? new Register();
}
public class Version
{
public int? First { get; set; }
public int? Last { get; set; }
public bool InVersion(int version)
{
if (this.First is null && this.Last is null)
{
return false;
}
return (this.First ?? int.MinValue) <= version && (this.First ?? int.MaxValue) >= version;
}
}
public class Registers : Dictionary<string, Register>
{
public Register this[byte id]
=> this.Values.FirstOrDefault(x => x.Id == id)
?? new Register();
public new Register this[string key]
{
get
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Register name should not be null or white space!");
}
if (!this.TryGetValue(key, out var register))
{
register = new Register();
this[key] = register;
}
return register;
}
set
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Register name should not be null or white space!");
}
this[key] = value;
}
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext _)
{
foreach (var kvp in this)
{
kvp.Value.Name = kvp.Key;
}
}
}
public class Register
{
public byte Id { get; set; }
[JsonIgnore]
public string Name { get; internal set; }
public Details Details { get; set; }
public Detail this[int version]
=> this.Details?[version] ?? new Detail();
}
public class Details : List<Detail>
{
public new Detail this[int version]
=> this.FirstOrDefault(x => x.Version?.InVersion(version) ?? false)
?? new Detail();
}
public class Detail
{
public string Type { get; set; }
public string StaticType { get; set; }
public Privilege Privilege { get; set; }
public Version Version { get; set; }
public Values Values { get; set; }
[JsonIgnore]
public Value Value { get; set; }
[JsonIgnore]
public Unit Unit { get; set; }
public object this[string property]
{
get
{
if (property == nameof(Value))
{
return this.Value?.Current;
}
else if (property == nameof(Unit))
{
return this.Unit?.Base;
}
return null;
}
set
{
if (property == nameof(Value) && this.Value != null)
{
this.Value.Current = value;
}
else if (property == nameof(Unit) && this.Unit != null)
{
this.Unit.Base = value;
}
}
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext _)
{
try
{
var valueType = System.Type.GetType(
typeName: $"CommonConsole.{this.Type}",
throwOnError: false,
ignoreCase: true);
var instance = Activator.CreateInstance(valueType);
if (instance is Value value)
{
if (this.Values != null)
{
value.Current = this.Values.Default;
}
this.Value = value;
}
}
catch (Exception e)
{
// TODO: Handle exceptions.
}
}
}
public class Values
{
public object Default { get; set; }
public object Minimum { get; set; }
public object Maximum { get; set; }
}
public class Privilege
{
public Access Lvl1 { get; set; }
public Access Lvl2 { get; set; }
public Access Lvl3 { get; set; }
public Access Lvl4 { get; set; }
public Access Lvl5 { get; set; }
public Access Lvl6 { get; set; }
public Access Lvl7 { get; set; }
public Access Lvl8 { get; set; }
}
public enum Access : byte
{
NS,
NA,
RO,
WO,
RW
}
public class Status : Dictionary<string, StatusInfo>
{
}
public class StatusInfo
{
public byte Id { get; set; }
public string Action { get; set; }
public string Description { get; set; }
}
public class AccessConverter : JsonConverter
{
public override bool CanConvert(Type type)
=> type == typeof(Access)
|| type == typeof(Access?);
public override object ReadJson(JsonReader reader, Type _, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var value = serializer.Deserialize<string>(reader);
if (Enum.TryParse(value, true, out Access access))
{
return access;
}
return default(Access);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer _1)
{
if (value != null)
{
writer.WriteValue($"{value}");
}
}
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class CurrentConverter : JsonConverter<Current>
{
public override Current ReadJson(JsonReader reader, Type objectType, Current existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Current value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class FlowConverter : JsonConverter<Flow>
{
public override Flow ReadJson(JsonReader reader, Type objectType, Flow existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Flow value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class PressureConverter : JsonConverter<Pressure>
{
public override Pressure ReadJson(JsonReader reader, Type objectType, Pressure existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Pressure value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class TemperatureConverter : JsonConverter<Temperature>
{
public override Temperature ReadJson(JsonReader reader, Type objectType, Temperature existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Temperature value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class TimeConverter : JsonConverter<Time>
{
public override Time ReadJson(JsonReader reader, Type objectType, Time existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Time value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
@@ -0,0 +1,27 @@
namespace CommonConsole.JsonConverters
{
using Newtonsoft.Json;
using System;
public class VolumeConverter : JsonConverter<Volume>
{
public override Volume ReadJson(JsonReader reader, Type objectType, Volume existingValue, bool hasExistingValue, JsonSerializer serializer)
{
while (reader.ValueType != typeof(double))
{
reader.Read();
}
if (reader.Value is double value)
{
return value;
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, Volume value, JsonSerializer serializer)
=> writer.WriteValue((double)value);
}
}
+55 -37
View File
@@ -1,54 +1,72 @@
namespace CommonConsole
{
using CommonMessurementUnits;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
int x = 3;
Console.WriteLine($"From Int32: {x}");
byte[] xb = x.GetBytes();
Console.WriteLine($"Bits: {string.Join("", xb.GetBits())}");
Console.WriteLine($"Hex bytes: {xb.ToHex()}");
int y = BitConverter.ToInt32(xb, 0);
Console.WriteLine($"To Int32: {y}");
Console.WriteLine();
var content = File.ReadAllText("../../configuration.json");
var configuration = JsonConvert.DeserializeObject<ConfigurationJson>(content);
byte sectionId = 10;
byte registerId = 2;
int version = 20;
var model = new TestClass
/// Getting application section from the configuration
var sectionById = configuration[sectionId];
if (!string.IsNullOrWhiteSpace(sectionById.Name))
{
Current = 130,
Flow = 40,
Pressure = 250000,
Temperature = 21,
Time = 960,
Volume = 40,
};
/// ??? When requested by name creates new Section if name not exists in the keys collection.
var sectionByName = configuration[sectionById.Name];
}
var modelJson = JsonConvert.SerializeObject(model, Formatting.Indented);
var testModel = JsonConvert.DeserializeObject<TestClass>(modelJson);
/// Geting register by sectionId and registerId
var registerById = configuration[sectionId][registerId];
Console.WriteLine($"To Json: {modelJson}");
Console.WriteLine($"From Json: {JsonConvert.SerializeObject(testModel, Formatting.Indented)}");
if (!string.IsNullOrWhiteSpace(registerById.Name))
{
/// ??? When requested by name creates new Register for the section if name not exists in the keys collection.
var registerByName = configuration[sectionId][registerById.Name];
}
configuration[sectionId][registerId][version].Unit = Unit.MessurementUnits.FirstOrDefault() ?? nameof(Volume);
var unit = configuration[sectionId][registerId][version][nameof(Unit)];
if (unit is null)
{
configuration[sectionId][registerId][version][nameof(Unit)] = 1000;
}
configuration[sectionId][registerId][version].Value = Value.ValueTypes.FirstOrDefault() ?? nameof(int32_t);
var value = configuration[sectionId][registerId][version][nameof(Value)];
if (value is null)
{
configuration[sectionId][registerId][version][nameof(Value)] = 1000;
}
}
}
public class TestClass
{
public Current Current { get; set; }
public Flow Flow { get; set; }
public Pressure Pressure { get; set; }
public Temperature Temperature { get; set; }
public Time Time { get; set; }
public Volume Volume { get; set; }
private static JsonSerializerSettings settings => new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new AccessConverter(),
new IsoDateTimeConverter
{
DateTimeStyles = DateTimeStyles.AssumeUniversal
}
},
};
}
}
+223
View File
@@ -0,0 +1,223 @@
namespace CommonConsole
{
using CommonConsole.JsonConverters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
public abstract class Unit
{
public const int MsInSec = 1000;
public const int SecInMin = 60;
public const int MinInH = 60;
public const int HInDay = 24;
public const int MlInL = 1000;
public const int LInm3 = 1000;
public const int PInBar = 100000;
public const int MAInH = 1000;
protected double value;
public virtual object Base { get; set; }
public override string ToString()
=> this.value.ToString();
public override bool Equals(object obj)
=> this.value.Equals(obj);
public override int GetHashCode()
=> this.value.GetHashCode();
public static implicit operator double (Unit @base)
=> @base?.value ?? default(double);
public static implicit operator double? (Unit @base)
=> @base?.value;
public static implicit operator Unit(string unitName)
{
try
{
var valueType = Type.GetType(
typeName: $"CommonConsole.{unitName}",
throwOnError: false,
ignoreCase: true);
var instance = Activator.CreateInstance(valueType);
if (instance is Unit unit)
{
return unit;
}
}
catch (Exception e)
{
// TODO: Handle exceptions.
}
return default(Unit);
}
public static IEnumerable<string> MessurementUnits
=> typeof(Unit)
.Assembly
.GetTypes()
.Where(x => typeof(Unit).IsAssignableFrom(x) && !x.IsAbstract)
.Select(x => x.Name);
}
[JsonConverter(typeof(CurrentConverter))]
public class Current : Unit
{
public double MiliampereHours
{
get => this.AmpereHours * MAInH;
set => this.AmpereHours = value / MAInH;
}
public double AmpereHours
{
get => this.value;
set => this.value = value;
}
public static implicit operator Current(double x)
=> new Current { value = x };
public static implicit operator Current(double? x)
=> new Current { value = x ?? 0 };
}
[JsonConverter(typeof(FlowConverter))]
public class Flow : Unit
{
public double CubicMeterInHour
{
get => this.value;
set => this.value = value;
}
public double LiterInMinute
{
get => this.CubicMeterInHour / MinInH * LInm3;
set => this.CubicMeterInHour = value * MinInH / LInm3;
}
public static implicit operator Flow(double x)
=> new Flow { value = x };
public static implicit operator Flow(double? x)
=> new Flow { value = x ?? 0 };
}
[JsonConverter(typeof(PressureConverter))]
public class Pressure : Unit
{
public double Pascal
{
get => this.value;
set => this.value = value;
}
public double Bar
{
get => this.Pascal / PInBar;
set => this.Pascal = value * PInBar;
}
public static implicit operator Pressure(double x)
=> new Pressure { value = x };
public static implicit operator Pressure(double? x)
=> new Pressure { value = x ?? 0 };
}
[JsonConverter(typeof(TemperatureConverter))]
public class Temperature : Unit
{
public double Celsius
{
get => this.value;
set => this.value = value;
}
public static implicit operator Temperature(double x)
=> new Temperature { value = x };
public static implicit operator Temperature(double? x)
=> new Temperature { value = x ?? 0 };
}
[JsonConverter(typeof(TimeConverter))]
public class Time : Unit
{
public double Miliseconds
{
get => this.Seconds * MsInSec;
set => this.Seconds = value / MsInSec;
}
public double Seconds
{
get => this.value;
set => this.value = value;
}
public double Minutes
{
get => this.Seconds / SecInMin;
set => this.Seconds = value * SecInMin;
}
public double Hours
{
get => this.Minutes / MinInH;
set => this.Minutes = value * MinInH;
}
public double Days
{
get => this.Hours / HInDay;
set => this.Hours = value * HInDay;
}
public static implicit operator Time(double x)
=> new Time { value = x };
public static implicit operator Time(double? x)
=> new Time { value = x ?? 0 };
}
[JsonConverter(typeof(VolumeConverter))]
public class Volume : Unit
{
public double Mililiter
{
get => this.Liter * MlInL;
set => this.Liter = value / MlInL;
}
public double Liter
{
get => this.value * LInm3;
set => this.value = value / LInm3;
}
public double CubicMeter
{
get => this.value * this.Factor;
set => this.value = value / this.Factor;
}
public int Factor { get; set; } = 1000;
public static implicit operator Volume(double x)
=> new Volume { value = x };
public static implicit operator Volume(double? x)
=> new Volume { value = x ?? 0 };
}
}
+183
View File
@@ -0,0 +1,183 @@
namespace CommonConsole
{
using System;
using System.Collections.Generic;
using System.Linq;
public abstract class Value
{
public virtual object Current { get; set; }
public virtual byte[] Buffer { get; set; }
public static implicit operator Value(string valueName)
{
try
{
var valueType = Type.GetType(
typeName: $"CommonConsole.{valueName}",
throwOnError: false,
ignoreCase: true);
var instance = Activator.CreateInstance(valueType);
if (instance is Value value)
{
return value;
}
}
catch (Exception e)
{
// TODO: Handle exceptions.
}
return default(Value);
}
public static IEnumerable<string> ValueTypes
=> typeof(Value)
.Assembly
.GetTypes()
.Where(x => typeof(Value).IsAssignableFrom(x) && !x.IsAbstract)
.Select(x => x.Name);
}
public class Value<T> : Value
{
protected T value;
}
public class bool_t : Value<bool>
{
public override object Current
{
get => this.value;
set => this.value = (bool)value;
}
}
public class rpc : Value<int>
{
public override object Current
{
get => this.value;
set => this.value = (int)value;
}
}
public class @string : Value<string>
{
public override object Current
{
get => this.value;
set => this.value = (string)value;
}
}
public class time_t : Value<int>
{
public override object Current
{
get => this.value;
set => this.value = (int)value;
}
}
public class status_t : Value<byte>
{
public override object Current
{
get => this.value;
set => this.value = (byte)value;
}
}
public class enum8 : Value<byte>
{
public override object Current
{
get => this.value;
set => this.value = (byte)value;
}
}
public class uint8_t : Value<byte>
{
public override object Current
{
get => this.value;
set => this.value = (byte)value;
}
}
public class uint16_t : Value<ushort>
{
public override object Current
{
get => this.value;
set => this.value = (ushort)value;
}
}
public class uint32_t : Value<uint>
{
public override object Current
{
get => this.value;
set => this.value = (uint)value;
}
}
public class uint64_t : Value<ulong>
{
public override object Current
{
get => this.value;
set => this.value = (ulong)value;
}
}
public class uint96_t : Value<string>
{
public override object Current
{
get => this.value;
set => this.value = (string)value;
}
}
public class int8_t : Value<sbyte>
{
public override object Current
{
get => this.value;
set => this.value = (sbyte)value;
}
}
public class int16_t : Value<short>
{
public override object Current
{
get => this.value;
set => this.value = (short)value;
}
}
public class int32_t : Value<int>
{
public override object Current
{
get => this.value;
set => this.value = (int)value;
}
}
public class int64_t : Value<long>
{
public override object Current
{
get => this.value;
set => this.value = (long)value;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -56,7 +56,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Base.cs" />
<Compile Include="Unit.cs" />
<Compile Include="BitExtensions.cs" />
<Compile Include="Current.cs" />
<Compile Include="Flow.cs" />
+1 -1
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(CurrentConverter))]
public class Current : Base
public class Current : Unit
{
public double MiliampereHours
{
+1 -1
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(FlowConverter))]
public class Flow : Base
public class Flow : Unit
{
public double CubicMeterInHour
{
+1 -1
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(PressureConverter))]
public class Pressure : Base
public class Pressure : Unit
{
public double Pascal
{
+1 -1
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(TemperatureConverter))]
public class Temperature : Base
public class Temperature : Unit
{
public double Celsius
{
+1 -1
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(TimeConverter))]
public class Time : Base
public class Time : Unit
{
public double Miliseconds
{
@@ -1,6 +1,6 @@
namespace CommonMessurementUnits
{
public abstract class Base
public abstract class Unit
{
public const int MsInSec = 1000;
public const int SecInMin = 60;
@@ -22,10 +22,10 @@
public override int GetHashCode()
=> this.value.GetHashCode();
public static explicit operator double (Base @base)
public static explicit operator double (Unit @base)
=> @base?.value ?? default(double);
public static explicit operator double? (Base @base)
public static explicit operator double? (Unit @base)
=> @base?.value;
}
}
+5 -3
View File
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
[JsonConverter(typeof(VolumeConverter))]
public class Volume : Base
public class Volume : Unit
{
public double Mililiter
{
@@ -21,10 +21,12 @@
public double CubicMeter
{
get => this.value;
set => this.value = value;
get => this.value * this.Factor;
set => this.value = value / this.Factor;
}
public int Factor { get; set; } = 1000;
public static implicit operator Volume(double x)
=> new Volume { value = x };
@@ -1,19 +1,19 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties;
using Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json;
using Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters;
/// <summary>
/// JSON filer reader for generation of register lists
/// </summary>
@@ -22,12 +22,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <summary>
/// Registers defined in configuration.json file
/// </summary>
public List<IRegister> ConfigRegistersDefinitions;
public List<IRegister> ConfigRegistersDefinitions { get; set; }
= new List<IRegister>();
/// <summary>
/// Applications defined in configuration.json file
/// </summary>
public List<ApplicationDefinition> ConfigApplicationDefinitions;
public List<ApplicationDefinition> ConfigApplicationDefinitions { get; set; }
= new List<ApplicationDefinition>();
/// <summary>
///
/// </summary>
public IDictionary<string, AppSection> Value { get; private set; }
/// <summary>
/// Ctor
@@ -50,416 +57,189 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <summary>
/// Convert file content to register list
/// </summary>
/// <param name="fileContent"></param>
/// <param name="configurationJson"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
private void Convert(String fileContent)
private void Convert(string configurationJson)
{
var applicationGroups = (JObject)JsonConvert.DeserializeObject(fileContent);
ConfigRegistersDefinitions = new List<IRegister>();
ConfigApplicationDefinitions = new List<ApplicationDefinition>();
var sections = default(IDictionary<string, AppSection>);
try
{
//extract information of every application
if (applicationGroups != null)
foreach (var currentApplication in applicationGroups)
{
var o = (JObject)currentApplication.Value;
var application = new ApplicationDefinition();
Byte applicationAddress = 0;
sections = JsonConvert
.DeserializeObject<IDictionary<string, AppSection>>(configurationJson, SerializerSettings)
?? new Dictionary<string, AppSection>();
}
catch (Exception e)
{
sections = new Dictionary<string, AppSection>();
}
foreach (var groupProp in o)
this.Value = sections;
foreach (var sectionKVP in sections)
{
var appId = sectionKVP.Value.Id;
var appName = sectionKVP.Key;
this.ConfigApplicationDefinitions.Add(new ApplicationDefinition
{
AppId = appId,
AppName = appName
});
var section = sectionKVP.Value;
if (section is null)
{
continue;
}
var registers = section.Registers;
if (registers is null)
{
continue;
}
foreach (var registerKVP in registers)
{
var register = registerKVP.Value;
if (register is null)
{
continue;
}
var details = register.Details;
if (details is null)
{
continue;
}
var regId = register.Id;
foreach (var detail in details)
{
var values = detail.Values;
this.ConfigRegistersDefinitions.Add(new RegisterDefinition
{
try
{
if (groupProp.Key == "id")
{
applicationAddress = groupProp.Value.Value<Byte>();
application.AppName = currentApplication.Key;
application.AppId = applicationAddress;
ConfigApplicationDefinitions.Add(application);
}
else if (groupProp.Key == "registers")
{
foreach (var registers in groupProp.Value)
{
var register = (JProperty)registers;
try
{
foreach (var registerJ in register.Value)
{
var reg = (JProperty)registerJ;
Byte? registerAddress = null;
if (reg.Name == "id")
{
registerAddress = (Byte)reg.Value;
}
if (reg.Name == "details")
{
var details = ((JArray)reg.Value);
foreach (var jdetail in details.Children())
{
var actualRegister = new RegisterDefinition();
var idTag = reg.Parent.First(f => ((JProperty)f).Name == "id");
var id = (Byte)(JProperty)idTag; //.Value<int>();
if (registerAddress.HasValue)
{
throw new Exception("invalid json cast");
}
actualRegister.RegAddressInApp = id;
actualRegister.AppName = currentApplication.Key;
actualRegister.AppAddress = applicationAddress;
actualRegister.RegisterDetail = new RegisterDetail();
actualRegister.RegisterName = register.Name;
var detailO = (JObject)jdetail;
JProperty detail;
detail = detailO.Property("privilege");
if (detail.Name == "privilege")
{
actualRegister.RegisterDetail.Privilege =
JsonConvert.DeserializeObject<Privilege>(
detail.Value.ToString(), Settings);
}
detail = detailO.Property("type");
if (detail.Name == "type")
{
actualRegister.DataType =
typeof(String); // detail.Value.ToString();
switch (detail.Value.ToString().ToLower())
{
case "bool_t":
actualRegister.DataType = typeof(Boolean);
break;
case "rpc":
actualRegister.DataType = typeof(Rpc);
break;
case "string":
actualRegister.DataType = typeof(String);
break;
case "uint32_t":
actualRegister.DataType = typeof(UInt32);
break;
case "time_t":
actualRegister.DataType = typeof(TimeT);
break;
case "status_t":
actualRegister.DataType = typeof(StatusT);
break;
case "uint16_t":
actualRegister.DataType = typeof(UInt16);
break;
case "uint8_t":
actualRegister.DataType = typeof(byte);
break;
case "enum8":
actualRegister.DataType = typeof(Enum8);
break;
case "uint64_t":
actualRegister.DataType = typeof(UInt64);
break;
case "uint96_t":
actualRegister.DataType = typeof(UInt96);
break;
case "int8_t":
actualRegister.DataType = typeof(sbyte);
break;
case "int32_t":
actualRegister.DataType = typeof(Int32);
break;
case "int64_t":
actualRegister.DataType = typeof(Int64);
break;
case "int16_t":
actualRegister.DataType = typeof(Int16);
break;
}
}
detail = detailO.Property("description");
if (detail.Name == "description")
{
actualRegister.RegisterDetail.Description =
detail.Value.ToString();
}
detail = detailO.Property("version");
if (detail.Name == "version")
{
actualRegister.RegisterDetail.Version =
JsonConvert.DeserializeObject<FwVersion>(
detail.Value.ToString());
}
detail = detailO.Property("values");
if (detail != null && detail.Name == "values")
{
foreach (var dValues in detail.Children().First())
{
switch (((JProperty)dValues).Name)
{
case "default":
actualRegister.Default =
(Int64)((JProperty)dValues).Value;
break;
case "maximum":
actualRegister.Maximum =
(Int64)((JProperty)dValues).Value;
break;
case "minimum":
actualRegister.Minimum =
(Int64)((JProperty)dValues).Value;
break;
}
}
}
detail = detailO.Property(StaticType.StaticTypeFieldIdentifier);
if (detail != null && detail.Name ==
StaticType.StaticTypeFieldIdentifier)
{
actualRegister.RestoreCapability =
new StaticType(detail.Value.ToString());
}
ConfigRegistersDefinitions.Add(actualRegister);
}
}
}
}
catch (Exception )
{
//todo log ex
}
}
}
}
catch (Exception )
{
//todo log ex
}
}
}
}
catch (Exception )
{
// ignored
}
////tofile
var listOfRegisters = new List<RegisterDefinition>();
foreach (var item in ConfigRegistersDefinitions)
{
if (item is RegisterDefinition reg)
{
if (listOfRegisters.Any(a => a.GetIdent() == reg.GetIdent()))
{
var oldItem = listOfRegisters.First(a => a.GetIdent() == reg.GetIdent());
if (oldItem.RegisterDetail.Version.Last < reg.RegisterDetail.Version.Last)
{
listOfRegisters.Remove(oldItem);
listOfRegisters.Add(reg);
}
}
else
{
listOfRegisters.Add(reg);
AppAddress = appId,
AppName = appName,
DataType = this.GetType(detail.Type),
Default = values?.Default is long d ? d : default(long?),
IsAvailable = default(bool),
Maximum = values?.Maximum is long max ? max : default(long?),
Minimum = values?.Minimum is long min ? min : default(long?),
RegAddressInApp = regId,
// RegisterAddress = new byte[] { appId, regId },
RegisterDetail = detail,
RegisterName = registerKVP.Key,
RestoreCapability = new StaticType(detail.StaticType)
});
}
}
}
//#region create a file for my american friends
//var sbCSV = new StringBuilder();
//sbCSV.AppendLine("Filter;Ident;First;Last");
//foreach (var item in ConfigRegistersDefinitions)
//{
// if (item is RegisterDefinition Reg)
// {
// sbCSV.AppendLine($"ALL;{Reg.GetIdent()};{Reg.RegisterDetail.Version.First}; {Reg.RegisterDetail.Version.Last};");
// }
//}
//foreach (var item in lsitOfRegisters)
//{
// sbCSV.AppendLine($"InUse;{item.GetIdent()};{item.RegisterDetail.Version.First}; {item.RegisterDetail.Version.Last};");
//}
//foreach (var item in lsitOfRegisters)
//{
// sbCSV.AppendLine($"InUse;{item.GetIdent()};{item.RegisterDetail.Version.First}; {item.RegisterDetail.Version.Last};");
//}
//var k = sbCSV.ToString();
//sbCSV.AppendLine("###");
//sbCSV.AppendLine("###");
//sbCSV.AppendLine("###");
//sbCSV.AppendLine("App;Version");
//foreach (var item in lsitOfRegisters)
//{
// sbCSV.AppendLine($"InUse;{item.GetIdent()};{item.RegisterDetail.Version.First}; {item.RegisterDetail.Version.Last};");
//}
//foreach (var grpReg in lsitOfRegisters.GroupBy(g => g.AppName))
//{
// sb.AppendLine($"public static class {grpReg.Key} {{");
// foreach (var item in grpReg)
// {
// sbCSV.Append($"{grpReg.Key};{item.RegisterName};{item.DataType.Name};{item.RegisterDetail.Description}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl1.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl2.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl3.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl4.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl5.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl6.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl7.ToString()}");
// sbCSV.Append($";{ item.RegisterDetail.Privilege.Lvl8.ToString()}");
// sb.AppendLine($"public static readonly RegisterDefinition {item.RegisterName} = new RegisterDefinition() {{");
// sb.AppendLine($"DataType = typeof({item.DataType.Name}),");
// sb.AppendLine($"Address = new byte[2] {{ (byte){item.RegisterAddress[0]}, (byte){item.RegisterAddress[1]} }},");
// sb.AppendLine($"Default = new long?(");
// if (item.Default.HasValue)
// {
// sb.Append(item.Default.Value);
// sbCSV.Append($";{item.Default.Value}");
// }
// else
// {
// sbCSV.Append(";-");
// }
// sb.Append($"),");
// sb.AppendLine($"Maximum = new long?(");
// if (item.Maximum.HasValue)
// {
// sb.Append(item.Maximum.Value);
// sbCSV.Append($";{item.Maximum.Value}");
// }
// else
// {
// sbCSV.Append(";-");
// }
// sb.Append($"),");
// sb.AppendLine($"Minimum = new long?(");
// if (item.Minimum.HasValue)
// {
// sb.Append(item.Minimum.Value);
// sbCSV.Append($";{item.Minimum.Value}");
// }
// else
// {
// sbCSV.Append(";-");
// }
// sb.Append($"),");
// sb.AppendLine($"Detail = new Detail(){{");
// sb.AppendLine($" Description = \"{item.RegisterDetail.Description}\",");
// sb.AppendLine($" Version = new Version(1,{item.RegisterDetail.Version.Last}),");
// sb.AppendLine($" Privilege = new Privilege(){{");
// //
// sb.AppendLine($" Lvl1 = Access.{item.RegisterDetail.Privilege.Lvl1.ToString()},");
// sb.AppendLine($" Lvl2 = Access.{item.RegisterDetail.Privilege.Lvl2.ToString()},");
// sb.AppendLine($" Lvl3 = Access.{item.RegisterDetail.Privilege.Lvl3.ToString()},");
// sb.AppendLine($" Lvl4 = Access.{item.RegisterDetail.Privilege.Lvl4.ToString()},");
// sb.AppendLine($" Lvl5 = Access.{item.RegisterDetail.Privilege.Lvl5.ToString()},");
// sb.AppendLine($" Lvl6 = Access.{item.RegisterDetail.Privilege.Lvl6.ToString()},");
// sb.AppendLine($" Lvl7 = Access.{item.RegisterDetail.Privilege.Lvl7.ToString()},");
// sb.AppendLine($" Lvl8 = Access.{item.RegisterDetail.Privilege.Lvl8.ToString()},");
// sb.AppendLine($" }}");
// sb.AppendLine($"}}");
// sb.AppendLine($"}};");
// sbCSV.AppendLine(";");
// }
// sb.AppendLine($"}}");
//}
//#endregion
//var z = sbCSV.ToString();
//var code = sb.ToString();
}
internal class LvlConverter : JsonConverter
{
public override Boolean CanConvert(Type t) => t == typeof(Access) || t == typeof(Access?);
public override Object ReadJson(JsonReader reader, Type t, Object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var value = serializer.Deserialize<String>(reader);
switch (value)
{
case "NA":
return Access.Na;
case "RO":
return Access.Ro;
case "RW":
return Access.Rw;
case "WO":
return Access.Wo;
}
throw new Exception("Cannot unmarshal type Lvl");
}
public override void WriteJson(JsonWriter writer, Object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
var value = (Access)untypedValue;
switch (value)
{
case Access.Na:
serializer.Serialize(writer, "NA");
return;
case Access.Ro:
serializer.Serialize(writer, "RO");
return;
case Access.Rw:
serializer.Serialize(writer, "RW");
return;
case Access.Wo:
serializer.Serialize(writer, "WO");
return;
}
throw new Exception("Cannot marshal type Lvl");
}
public static readonly LvlConverter Singleton = new LvlConverter();
}
/// <summary>
/// Settings
/// </summary>
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
public static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
LvlConverter.Singleton,
AccessConverter.Singleton,
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
private Type GetType(string value)
{
switch (value.ToLower())
{
case "bool_t": return typeof(Boolean);
case "rpc": return typeof(Rpc);
case "string": return typeof(String);
case "uint32_t": return typeof(UInt32);
case "time_t": return typeof(TimeT);
case "status_t": return typeof(StatusT);
case "uint16_t": return typeof(UInt16);
case "uint8_t": return typeof(byte);
case "enum8": return typeof(Enum8);
case "uint64_t": return typeof(UInt64);
case "uint96_t": return typeof(UInt96);
case "int8_t": return typeof(sbyte);
case "int32_t": return typeof(Int32);
case "int64_t": return typeof(Int64);
case "int16_t": return typeof(Int16);
default: throw new Exception($"Type {value} not recognized!");
}
}
}
/// <summary>
///
/// </summary>
public class AccessConverter : JsonConverter
{
/// <summary>
///
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public override bool CanConvert(Type t) => t == typeof(Access) || t == typeof(Access?);
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <param name="t"></param>
/// <param name="existingValue"></param>
/// <param name="serializer"></param>
/// <returns></returns>
public override Object ReadJson(JsonReader reader, Type t, Object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var value = serializer.Deserialize<string>(reader);
if (Enum.TryParse(value, true, out Access access))
{
return access;
}
return default(Access);
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
/// <param name="untypedValue"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, Object untypedValue, JsonSerializer serializer)
{
if (untypedValue is Access access)
{
writer.WriteValue(access.ToString());
}
else
{
throw new Exception("Cannot marshal type Lvl");
}
}
/// <summary>
///
/// </summary>
public static readonly AccessConverter Singleton = new AccessConverter();
}
}
@@ -372,7 +372,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties configuration_1json__JsonSchema="https://codemagic.io/codemagic-schema.json" />
<UserProperties configuration_1json__JsonSchema="https://fasterci.com/config.schema.json" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -1853,7 +1853,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
RequestProtocolProcess();
//if register check by read back is not required we return the acknowledge state
if (!checkRegister || regDef.RegisterDetail.Privilege.Lvl8 == Registers.Access.Wo)
if (!checkRegister || regDef.RegisterDetail.Privilege.Lvl8 == Registers.Access.WO)
{
return responseRecord.Acknowledge == RequestAcknowledgeState.Ok;
}
@@ -193,7 +193,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
foreach (var reg in meterRegisters.MeterRegisterDic.Where(r => r.Key.RegisterDetail?.Version.First != null
&& r.Key.RegisterDetail.Version.Last != null && r.Key.RestoreCapability.StaticTypeValue != null
&& r.Key.DataType != typeof(Rpc) && r.Key.IsAvailable &&
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.Rw || r.Key.RegisterDetail.Privilege.Lvl8 == Access.Ro)))
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW || r.Key.RegisterDetail.Privilege.Lvl8 == Access.RO)))
{
_registersPostUpdate.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
// only registers which are present before the update
@@ -252,7 +252,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
foreach (var reg in meterRegisters.MeterRegisterDic.Where(r => r.Key.RegisterDetail?.Version.First != null
&& r.Key.RegisterDetail.Version.Last != null && r.Key.RestoreCapability.StaticTypeValue != null
&& r.Key.DataType != typeof(Rpc) && r.Key.IsAvailable &&
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.Rw || r.Key.RegisterDetail.Privilege.Lvl8 == Access.Ro)))
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW || r.Key.RegisterDetail.Privilege.Lvl8 == Access.RO)))
{
_registersPreUpdate.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
// only registers which are present before the update
@@ -266,7 +266,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
// changed, only registers which are present before the update can be restored!
foreach (var reg in _registersPreUpdate.MeterRegisterDic.Where(r =>
r.Key.RestoreCapability.CheckRestoreCapability() &&
r.Key.RegisterDetail.Privilege.Lvl8 == Access.Rw))
r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW))
{
_restoreRegNames.Add(reg.Key.GetIdent());
}
@@ -8,22 +8,22 @@
/// <summary>
/// Not set, means no valid input/information
/// </summary>
NotSet,
NS,
/// <summary>
/// No Access
/// </summary>
Na,
NA,
/// <summary>
/// read only
/// </summary>
Ro,
RO,
/// <summary>
/// Write only
/// </summary>
Wo,
WO,
/// <summary>
/// Read and Write
/// </summary>
Rw
RW
}
}
@@ -0,0 +1,15 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
using System.Collections.Generic;
public class AppSection
{
public byte Id { get; set; }
public FwVersion Version { get; set; }
public IDictionary<string, Register> Registers { get; set; }
public IDictionary<string, Status> Status { get; set; }
}
}
@@ -0,0 +1,17 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
public class Details
{
public string Type { get; set; }
public Privilege Privilege { get; set; }
public string Description { get; set; }
public FwVersion Version { get; set; }
public string StaticType { get; set; }
public Value Values { get; set; }
}
}
@@ -0,0 +1,9 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
public class FwVersion
{
public int? First { get; set; }
public int? Last { get; set; }
}
}
@@ -1,4 +1,4 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
/// <summary>
/// Representing the 8 access levels meter register can have
@@ -9,30 +9,37 @@
/// Value for first level
/// </summary>
public Access Lvl1 { get; set; }
/// <summary>
/// Value for second level
/// </summary>
public Access Lvl2 { get; set; }
/// <summary>
/// Value for third level
/// </summary>
public Access Lvl3 { get; set; }
/// <summary>
/// Value for fourth level
/// </summary>
public Access Lvl4 { get; set; }
/// <summary>
/// Value for fifth level
/// </summary>
public Access Lvl5 { get; set; }
/// <summary>
/// Value for sixth level
/// </summary>
public Access Lvl6 { get; set; }
/// <summary>
/// Value for seventh level
/// </summary>
public Access Lvl7 { get; set; }
/// <summary>
/// Value for eighth level
/// </summary>
@@ -0,0 +1,11 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
using System.Collections.Generic;
public class Register
{
public byte Id { get; set; }
public IEnumerable<Details> Details { get; set; }
}
}
@@ -0,0 +1,11 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
public class Status
{
public byte Id { get; set; }
public string Action { get; set; }
public string Description { get; set; }
}
}
@@ -0,0 +1,11 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
public class Value
{
public object Minimum { get; set; }
public object Maximum { get; set; }
public object Default { get; set; }
}
}
@@ -1,6 +1,6 @@
using System;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json;
using Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
@@ -12,7 +12,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
/// </summary>
public class RegisterDefinition : IRegister
{
/// <summary>
/// name of the application which uses the register
/// </summary>
@@ -71,7 +70,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
/// <summary>
/// describe the accessibility for different login levels
/// </summary>
public RegisterDetail RegisterDetail { get; set; }
public Details RegisterDetail { get; set; }
/// <summary>
/// default value
@@ -98,25 +97,5 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
{
throw new NotImplementedException();
}
///// <inheritdoc />
//public override Boolean Equals(Object obj)
//{
// return obj is RegisterDefinition fooItem && GetHashCode() == fooItem.GetHashCode();
//}
///// <inheritdoc />
//public override Int32 GetHashCode()
//{
// var hashCode = base.GetHashCode();
// if (RegisterDetail == null) return hashCode;
// hashCode ^= RegisterDetail.GetHashCode();
// if (RegisterDetail.Version != null)
// {
// hashCode ^= RegisterDetail.Version.GetHashCode();
// }
// return hashCode;
//}
}
}
@@ -1,31 +0,0 @@
using System;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties
{
/// <summary>
/// Version range of firmware (FW)
/// </summary>
public class FwVersion
{
/// <summary>
/// first and last version of this FW
/// </summary>
/// <param name="first"></param>
/// <param name="last"></param>
public FwVersion(Int32? first, Int32? last)
{
Last = last;
First = first;
}
/// <summary>
/// first version
/// </summary>
public Int32? First { get; set; }
/// <summary>
/// last version
/// </summary>
public Int32? Last { get; set; }
}
}
@@ -1,27 +0,0 @@
using System;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties
{
/// <summary>
/// details of registers
/// </summary>
public class RegisterDetail
{
/// <summary>
/// access level 0 to 8
/// </summary>
public Privilege Privilege { get; set; }
/// <summary>
/// extended description of register
/// </summary>
public String Description { get; set; }
/// <summary>
/// register FW version, describes the support of this register by FW versions
/// from first to last. The same register may be supported with a different content
/// like the default value by in an other version of this FW (application)
/// </summary>
public FwVersion Version { get; set; }
}
}
@@ -113,13 +113,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
{
public static readonly String StoreConfiguration = "IRDA_StoreConfiguration";
}
public static class Logger
{
public static readonly String StoreConfiguration = "LOGGER_StoreConfiguration";
}
public static List<String> GetMinRequiredRegisters()
{
return new List<String>()
@@ -102,13 +102,17 @@
<Compile Include="DataTypes\st_radio_tfx.cs" />
<Compile Include="DataTypes\TimeT.cs" />
<Compile Include="DataTypes\UInt96.cs" />
<Compile Include="Json\AppSection.cs" />
<Compile Include="Json\FwVersion.cs" />
<Compile Include="Json\Details.cs" />
<Compile Include="Json\Register.cs" />
<Compile Include="Json\Status.cs" />
<Compile Include="Json\Value.cs" />
<Compile Include="RegisterCheck.cs" />
<Compile Include="RegisterConverter.cs" />
<Compile Include="RegisterDefinition.cs" />
<Compile Include="RegisterProperties\RegisterDetail.cs" />
<Compile Include="RegisterProperties\FwVersion.cs" />
<Compile Include="MeterRegisters.cs" />
<Compile Include="RegisterProperties\Privilege.cs" />
<Compile Include="Json\Privilege.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Registers.cs" />
</ItemGroup>
@@ -124,6 +128,10 @@
<Project>{26AFCF1E-1287-48B8-A506-32B1E8A0DD0E}</Project>
<Name>WaterMeterRegisters</Name>
</ProjectReference>
<ProjectReference Include="..\Applications\Applications.csproj">
<Project>{315E94B8-B82F-4B25-B5BD-297DF3BC1D54}</Project>
<Name>Applications</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
@@ -59,10 +59,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\..\..\MJK\Code\C#\modbus_master_csharp\src\modbus_master_csharp\modbus_master_csharp.csproj">
<Project>{f14940f8-3c86-4bb7-a915-b021e4b3052d}</Project>
<Name>modbus_master_csharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\CommonCore.Configuration\CommonCore.Configuration.csproj">
<Project>{9eb1f659-6f73-4f65-bcab-4114fd94f5fc}</Project>
<Name>CommonCore.Configuration</Name>
@@ -53,8 +53,8 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\..\..\..\MJK\Code\C#\modbus_master_csharp\src\modbus_master_csharp\modbus_master_csharp.csproj">
<Project>{f14940f8-3c86-4bb7-a915-b021e4b3052d}</Project>
<ProjectReference Include="..\..\..\..\..\modbus_master_csharp\modbus_master_csharp.csproj">
<Project>{F14940F8-3C86-4BB7-A915-B021E4B3052D}</Project>
<Name>modbus_master_csharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\Utils\Logging\Logging.csproj">
@@ -1 +1 @@
bf6bb8fceb3db5a9977dadc407cf576684bf7127
89102b0142e574de38a9f47d370f3334e5e6c268
@@ -62,7 +62,7 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions
UserControl.lblText.Content = $"Read {dic.GetIdent()}({done1}/{total.Count})";
}
));
if (dic.RegisterName.ToLower() != "password" && dic.RegisterDetail.Privilege.Lvl8 != Access.Wo)
if (dic.RegisterName.ToLower() != "password" && dic.RegisterDetail.Privilege.Lvl8 != Access.WO)
{
switch (dic.GetIdent().ToLower())
{
@@ -15,8 +15,6 @@ namespace Service.MeterProcessState.Controllers
[RoutePrefix("api/GenesisMeter")]
public class GenesisMeterController : ApiController
{
public static class GlobalConfig
{
public static Lazy<String> connectionString = new Lazy<String>(()
@@ -0,0 +1,31 @@
namespace Xylem.Common.Service.MeterProcessState.Controllers
{
using System.IO;
using System.Text;
using System.Web;
using System.Web.Http;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
public class JsonConfigurationController : ApiController
{
[HttpGet]
public IHttpActionResult Get()
{
var dir = HttpContext.Current.Request.MapPath("../");
Directory.CreateDirectory(dir);
var file = Path.Combine(dir, "configuration.json");
if (!File.Exists(file))
{
File.WriteAllText(file, string.Empty);
}
var reader = new GenesisConfigurationReader(file);
return this.Json(reader.Value, GenesisConfigurationReader.SerializerSettings, Encoding.UTF8);
}
}
}
@@ -47,26 +47,28 @@ namespace Service.MeterProcessState.Controllers
}
[Route("AddLut"), HttpPost]
public async Task<Boolean> AddLut(Int32 PcbId, Double RefTempC, Double AvgTof)
public async Task<Boolean> AddLut(Int32 PcbId, Double RefTempC, Double AvgTof, DateTime dt)
{
try
{
using (AuftragContext ctx = new AuftragContext())
using (var ctx = new AuftragContext())
{
var newItem = ctx.CordonelTempLut.Add(new CordonelTempLut()
{
PcbId = PcbId,
RefTempC = RefTempC,
AvgTof = AvgTof,
Active = true,
Timestamp = dt == default(DateTime) ? null : (DateTime?)dt
});
var newItem = ctx.CordonelTempLut.Add(new CordonelTempLut() { PcbId = PcbId, RefTempC = RefTempC, AvgTof = AvgTof, Active = true });
return await ctx.SaveChangesAsync() > 0;
}
}
catch (Exception ex)
{
throw ex;
}
}
@@ -1,21 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Xylem.Common.Service.MeterProcessState.Data
namespace Xylem.Common.Service.MeterProcessState.Data
{
using System;
using System.ComponentModel.DataAnnotations;
public class CordonelTempLut
{
[Key]
public Int32 Id { get; set; }
public Int32 PcbId { get; set; }
public Double RefTempC { get; set; }
public Double AvgTof { get; set; }
public Boolean Active { get; set; }
public DateTime? Timestamp { get; set; }
}
}
@@ -10,7 +10,7 @@
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Controller</Controller_SelectedScaffolderCategoryPath>
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
<WebStackScaffolding_IsLayoutPageSelected>True</WebStackScaffolding_IsLayoutPageSelected>
File diff suppressed because it is too large Load Diff
+41 -39
View File
@@ -1,67 +1,69 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TempFlansh
{
static class Program
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
private static void Main()
{
Console.WriteLine("Comport");
short cport = short.Parse(Console.ReadLine());
var ap = TempHelper.UniversalOpenCom(cport, 4800, 8, 0, 0);
var helper = new TempHelper();
var filename = $"{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}_temp.log";
//while (true)
//{
// var outT = $"{DateTime.Now} {helper.ReadCurrentDisplayValue().ToString()}";
// File.AppendAllLines(filename, new List<string>() { outT });
// Console.WriteLine(outT);
// Thread.Sleep(1000);
//}
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("TempPipe", PipeDirection.Out))
//var filename = $"{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}_temp.log";
////while (true)
////{
//// var outT = $"{DateTime.Now} {helper.ReadCurrentDisplayValue().ToString()}";
//// File.AppendAllLines(filename, new List<string>() { outT });
//// Console.WriteLine(outT);
//// Thread.Sleep(1000);
////}
while (true)
{
Console.WriteLine("NamedPipeServerStream object created.");
// Wait for a client to connect
Console.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Console.Write("Open Comport");
Console.WriteLine("Client connected.");
try
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("TempPipe", PipeDirection.Out))
{
// Read user input and send that to the client process.
using (StreamWriter sw = new StreamWriter(pipeServer))
Console.WriteLine("NamedPipeServerStream object created.");
// Wait for a client to connect
Console.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Console.Write("Open Comport");
Console.WriteLine("Client connected.");
try
{
sw.AutoFlush = true;
while (true)
// Read user input and send that to the client process.
using (StreamWriter sw = new StreamWriter(pipeServer))
{
sw.WriteLine(helper.ReadCurrentDisplayValue().ToString());
Thread.Sleep(100);
}
sw.AutoFlush = true;
while (pipeServer.IsConnected)
{
//sw.WriteLine("19.0");
sw.WriteLine(helper.ReadCurrentDisplayValue().ToString());
Console.WriteLine(helper.ReadCurrentDisplayValue().ToString());
Thread.Sleep(500);
}
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
+41
View File
@@ -12,6 +12,22 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>L:\TiloW\TempMeter\publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -57,6 +73,18 @@
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>ADF2291D112B2A4A17DB68B014F2CBCC31E5CCCE</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>TempFlansh_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</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>
@@ -110,6 +138,7 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<None Include="TempFlansh_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
@@ -153,5 +182,17 @@
<Name>SoftwareAccessHelper</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+10 -10
View File
@@ -5,7 +5,7 @@ using System.IO;
using System.Linq;
using System.Text;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterProperties;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json;
namespace Tools.JsonToXlsHelper
{
@@ -138,21 +138,21 @@ namespace Tools.JsonToXlsHelper
foreach (var privilegeitem in detailValue.Children())
{
var accessValue = Access.NotSet;
var accessValue = Access.NS;
switch (((JProperty)privilegeitem).Value.ToString().ToUpper())
{
case "RO":
accessValue = Access.Ro;
accessValue = Access.RO;
break;
case "RW":
accessValue = Access.Rw;
accessValue = Access.RW;
break;
case "WO":
accessValue = Access.Wo;
accessValue = Access.WO;
break;
case "NA":
accessValue = Access.Na;
accessValue = Access.NA;
break;
}
@@ -366,13 +366,13 @@ namespace Tools.JsonToXlsHelper
{
switch (a)
{
case Access.Na:
case Access.NA:
return "Na";
case Access.Ro:
case Access.RO:
return "Ro";
case Access.Wo:
case Access.WO:
return "Wo";
case Access.Rw:
case Access.RW:
return "Rw";
default:
return "NotSet";
@@ -1 +1 @@
247396738e2c5d26ac00f9df05c0cc5c61d7f33a
338bdd8d71c148c9df0972f903098eb23eacf0c9
+382 -183
View File
@@ -1,4 +1,6 @@
namespace Xylem.Common.Ui.GenesisToolBox
using System.Drawing;
namespace Xylem.Common.Ui.GenesisToolBox
{
partial class FrmTempMeter
{
@@ -29,14 +31,9 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnConnect = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.cbComSlot = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.lblPcbId = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.timer2 = new System.Windows.Forms.Timer(this.components);
this.tabControl1 = new System.Windows.Forms.TabControl();
this.automaticCalibrationTabControl = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.btnRefreshLut = new System.Windows.Forms.Button();
this.txtLuts = new System.Windows.Forms.TextBox();
@@ -57,89 +54,39 @@
this.btnStopRecord = new System.Windows.Forms.Button();
this.btnStartRecord = new System.Windows.Forms.Button();
this.txtCurrentTofs = new System.Windows.Forms.TextBox();
this.tabPage4 = new System.Windows.Forms.TabPage();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.btnUpdateGrid = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.AutomaticCalibrationTab = new System.Windows.Forms.TabPage();
this.automaticContentBox = new System.Windows.Forms.RichTextBox();
this.autometicControlsSplitter = new System.Windows.Forms.Splitter();
this.automaticControlsPanel = new System.Windows.Forms.Panel();
this.messurementTOFTolerance = new System.Windows.Forms.TextBox();
this.label42 = new System.Windows.Forms.Label();
this.stopAutomaticBtn = new System.Windows.Forms.Button();
this.startAutomaticBtn = new System.Windows.Forms.Button();
this.messurementToleranceInC = new System.Windows.Forms.TextBox();
this.label11 = new System.Windows.Forms.Label();
this.messurementStep = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.messurementDauerInMs = new System.Windows.Forms.TextBox();
this.label8 = new System.Windows.Forms.Label();
this.temperatureChecksCount = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.temperatureCheckInC = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.temperatureCheckInMs = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.timer3 = new System.Windows.Forms.Timer(this.components);
this.button3 = new System.Windows.Forms.Button();
this.tabControl1.SuspendLayout();
this.mainMenuStrip = new System.Windows.Forms.MenuStrip();
this.messurementExitAfterInMin = new System.Windows.Forms.TextBox();
this.label12 = new System.Windows.Forms.Label();
this.automaticCalibrationTabControl.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.tabPage3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudRef)).BeginInit();
this.tabPage4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.AutomaticCalibrationTab.SuspendLayout();
this.automaticControlsPanel.SuspendLayout();
this.SuspendLayout();
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(12, 37);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(234, 24);
this.btnConnect.TabIndex = 30;
this.btnConnect.Text = "Connect";
this.btnConnect.UseVisualStyleBackColor = true;
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 14);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(28, 13);
this.label2.TabIndex = 29;
this.label2.Text = "Slot:";
//
// cbComSlot
//
this.cbComSlot.FormattingEnabled = true;
this.cbComSlot.Items.AddRange(new object[] {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20"});
this.cbComSlot.Location = new System.Drawing.Point(43, 10);
this.cbComSlot.Name = "cbComSlot";
this.cbComSlot.Size = new System.Drawing.Size(37, 21);
this.cbComSlot.TabIndex = 28;
this.cbComSlot.Text = "1";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(99, 14);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(40, 13);
this.label1.TabIndex = 33;
this.label1.Text = "PcbID:";
//
// lblPcbId
//
this.lblPcbId.AutoSize = true;
this.lblPcbId.Location = new System.Drawing.Point(153, 14);
this.lblPcbId.Name = "lblPcbId";
this.lblPcbId.Size = new System.Drawing.Size(10, 13);
this.lblPcbId.TabIndex = 34;
this.lblPcbId.Text = "-";
//
// timer1
//
this.timer1.Interval = 5000;
@@ -149,27 +96,31 @@
//
this.timer2.Tick += new System.EventHandler(this.timer2_Tick);
//
// tabControl1
// automaticCalibrationTabControl
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Controls.Add(this.tabPage4);
this.tabControl1.Location = new System.Drawing.Point(12, 90);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(652, 649);
this.tabControl1.TabIndex = 55;
this.tabControl1.Tag = "";
this.automaticCalibrationTabControl.Controls.Add(this.tabPage1);
this.automaticCalibrationTabControl.Controls.Add(this.tabPage2);
this.automaticCalibrationTabControl.Controls.Add(this.tabPage3);
this.automaticCalibrationTabControl.Controls.Add(this.AutomaticCalibrationTab);
this.automaticCalibrationTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.automaticCalibrationTabControl.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.automaticCalibrationTabControl.Location = new System.Drawing.Point(0, 24);
this.automaticCalibrationTabControl.Margin = new System.Windows.Forms.Padding(0);
this.automaticCalibrationTabControl.Name = "automaticCalibrationTabControl";
this.automaticCalibrationTabControl.Padding = new System.Drawing.Point(0, 0);
this.automaticCalibrationTabControl.SelectedIndex = 0;
this.automaticCalibrationTabControl.Size = new System.Drawing.Size(1245, 724);
this.automaticCalibrationTabControl.TabIndex = 55;
this.automaticCalibrationTabControl.Tag = "";
//
// tabPage1
//
this.tabPage1.Controls.Add(this.btnRefreshLut);
this.tabPage1.Controls.Add(this.txtLuts);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Location = new System.Drawing.Point(4, 25);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(644, 623);
this.tabPage1.Size = new System.Drawing.Size(1237, 695);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Current entrys in LUT";
this.tabPage1.UseVisualStyleBackColor = true;
@@ -197,10 +148,10 @@
this.tabPage2.Controls.Add(this.lblCheck);
this.tabPage2.Controls.Add(this.label9);
this.tabPage2.Controls.Add(this.btnCheck);
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Location = new System.Drawing.Point(4, 25);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(644, 623);
this.tabPage2.Size = new System.Drawing.Size(1237, 695);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Manual check temp";
this.tabPage2.UseVisualStyleBackColor = true;
@@ -210,7 +161,7 @@
this.lblCheck.AutoSize = true;
this.lblCheck.Location = new System.Drawing.Point(221, 66);
this.lblCheck.Name = "lblCheck";
this.lblCheck.Size = new System.Drawing.Size(10, 13);
this.lblCheck.Size = new System.Drawing.Size(12, 16);
this.lblCheck.TabIndex = 54;
this.lblCheck.Text = "-";
//
@@ -219,7 +170,7 @@
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(147, 66);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(68, 13);
this.label9.Size = new System.Drawing.Size(85, 16);
this.label9.TabIndex = 53;
this.label9.Text = "Check Temp";
//
@@ -247,10 +198,10 @@
this.tabPage3.Controls.Add(this.btnStopRecord);
this.tabPage3.Controls.Add(this.btnStartRecord);
this.tabPage3.Controls.Add(this.txtCurrentTofs);
this.tabPage3.Location = new System.Drawing.Point(4, 22);
this.tabPage3.Location = new System.Drawing.Point(4, 25);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
this.tabPage3.Size = new System.Drawing.Size(644, 623);
this.tabPage3.Size = new System.Drawing.Size(1237, 695);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "Manual add LUT";
this.tabPage3.UseVisualStyleBackColor = true;
@@ -260,7 +211,7 @@
this.lblAvgDutTof.AutoSize = true;
this.lblAvgDutTof.Location = new System.Drawing.Point(235, 322);
this.lblAvgDutTof.Name = "lblAvgDutTof";
this.lblAvgDutTof.Size = new System.Drawing.Size(10, 13);
this.lblAvgDutTof.Size = new System.Drawing.Size(12, 16);
this.lblAvgDutTof.TabIndex = 60;
this.lblAvgDutTof.Text = "-";
//
@@ -269,7 +220,7 @@
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(235, 299);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(71, 13);
this.label7.Size = new System.Drawing.Size(87, 16);
this.label7.TabIndex = 59;
this.label7.Text = "Avg DUT Tof";
//
@@ -278,7 +229,7 @@
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(95, 299);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(90, 13);
this.label6.Size = new System.Drawing.Size(111, 16);
this.label6.TabIndex = 58;
this.label6.Text = "Avg Ref Temp C°";
//
@@ -287,7 +238,7 @@
this.lblDuration.AutoSize = true;
this.lblDuration.Location = new System.Drawing.Point(145, 47);
this.lblDuration.Name = "lblDuration";
this.lblDuration.Size = new System.Drawing.Size(10, 13);
this.lblDuration.Size = new System.Drawing.Size(12, 16);
this.lblDuration.TabIndex = 57;
this.lblDuration.Text = "-";
//
@@ -296,7 +247,7 @@
this.lblLines.AutoSize = true;
this.lblLines.Location = new System.Drawing.Point(145, 25);
this.lblLines.Name = "lblLines";
this.lblLines.Size = new System.Drawing.Size(10, 13);
this.lblLines.Size = new System.Drawing.Size(12, 16);
this.lblLines.TabIndex = 56;
this.lblLines.Text = "-";
//
@@ -305,7 +256,7 @@
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(94, 47);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(47, 13);
this.label5.Size = new System.Drawing.Size(58, 16);
this.label5.TabIndex = 55;
this.label5.Text = "Duration";
//
@@ -314,7 +265,7 @@
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(94, 25);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(32, 13);
this.label4.Size = new System.Drawing.Size(40, 16);
this.label4.TabIndex = 54;
this.label4.Text = "Lines";
//
@@ -380,88 +331,324 @@
this.txtCurrentTofs.Size = new System.Drawing.Size(380, 230);
this.txtCurrentTofs.TabIndex = 49;
//
// tabPage4
// AutomaticCalibrationTab
//
this.tabPage4.Controls.Add(this.dataGridView1);
this.tabPage4.Controls.Add(this.btnUpdateGrid);
this.tabPage4.Controls.Add(this.button2);
this.tabPage4.Controls.Add(this.button1);
this.tabPage4.Location = new System.Drawing.Point(4, 22);
this.tabPage4.Name = "tabPage4";
this.tabPage4.Padding = new System.Windows.Forms.Padding(3);
this.tabPage4.Size = new System.Drawing.Size(644, 623);
this.tabPage4.TabIndex = 3;
this.tabPage4.Text = "Auto Calibration";
this.tabPage4.UseVisualStyleBackColor = true;
this.AutomaticCalibrationTab.BackColor = System.Drawing.SystemColors.Window;
this.AutomaticCalibrationTab.Controls.Add(this.automaticContentBox);
this.AutomaticCalibrationTab.Controls.Add(this.autometicControlsSplitter);
this.AutomaticCalibrationTab.Controls.Add(this.automaticControlsPanel);
this.AutomaticCalibrationTab.Location = new System.Drawing.Point(4, 25);
this.AutomaticCalibrationTab.Margin = new System.Windows.Forms.Padding(0);
this.AutomaticCalibrationTab.Name = "AutomaticCalibrationTab";
this.AutomaticCalibrationTab.Size = new System.Drawing.Size(1237, 695);
this.AutomaticCalibrationTab.TabIndex = 3;
this.AutomaticCalibrationTab.Text = "Automatic Calibration";
//
// dataGridView1
// automaticContentBox
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(27, 105);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(586, 324);
this.dataGridView1.TabIndex = 61;
this.automaticContentBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.automaticContentBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.automaticContentBox.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.automaticContentBox.Location = new System.Drawing.Point(331, 0);
this.automaticContentBox.Name = "automaticContentBox";
this.automaticContentBox.Size = new System.Drawing.Size(906, 695);
this.automaticContentBox.TabIndex = 2;
this.automaticContentBox.Text = "";
//
// btnUpdateGrid
// autometicControlsSplitter
//
this.btnUpdateGrid.Location = new System.Drawing.Point(148, 6);
this.btnUpdateGrid.Name = "btnUpdateGrid";
this.btnUpdateGrid.Size = new System.Drawing.Size(61, 61);
this.btnUpdateGrid.TabIndex = 60;
this.btnUpdateGrid.Text = "Update Grid";
this.btnUpdateGrid.UseVisualStyleBackColor = true;
this.btnUpdateGrid.Click += new System.EventHandler(this.btnUpdateGrid_Click);
this.autometicControlsSplitter.BackColor = System.Drawing.SystemColors.ScrollBar;
this.autometicControlsSplitter.Cursor = System.Windows.Forms.Cursors.VSplit;
this.autometicControlsSplitter.Location = new System.Drawing.Point(328, 0);
this.autometicControlsSplitter.Name = "autometicControlsSplitter";
this.autometicControlsSplitter.Size = new System.Drawing.Size(3, 695);
this.autometicControlsSplitter.TabIndex = 1;
this.autometicControlsSplitter.TabStop = false;
//
// button2
// automaticControlsPanel
//
this.button2.Location = new System.Drawing.Point(238, 6);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(89, 62);
this.button2.TabIndex = 59;
this.button2.Text = "End automatic";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
this.automaticControlsPanel.BackColor = System.Drawing.SystemColors.Menu;
this.automaticControlsPanel.Controls.Add(this.messurementExitAfterInMin);
this.automaticControlsPanel.Controls.Add(this.label12);
this.automaticControlsPanel.Controls.Add(this.messurementTOFTolerance);
this.automaticControlsPanel.Controls.Add(this.label42);
this.automaticControlsPanel.Controls.Add(this.stopAutomaticBtn);
this.automaticControlsPanel.Controls.Add(this.startAutomaticBtn);
this.automaticControlsPanel.Controls.Add(this.messurementToleranceInC);
this.automaticControlsPanel.Controls.Add(this.label11);
this.automaticControlsPanel.Controls.Add(this.messurementStep);
this.automaticControlsPanel.Controls.Add(this.label10);
this.automaticControlsPanel.Controls.Add(this.messurementDauerInMs);
this.automaticControlsPanel.Controls.Add(this.label8);
this.automaticControlsPanel.Controls.Add(this.temperatureChecksCount);
this.automaticControlsPanel.Controls.Add(this.label3);
this.automaticControlsPanel.Controls.Add(this.temperatureCheckInC);
this.automaticControlsPanel.Controls.Add(this.label2);
this.automaticControlsPanel.Controls.Add(this.temperatureCheckInMs);
this.automaticControlsPanel.Controls.Add(this.label1);
this.automaticControlsPanel.Dock = System.Windows.Forms.DockStyle.Left;
this.automaticControlsPanel.Location = new System.Drawing.Point(0, 0);
this.automaticControlsPanel.Name = "automaticControlsPanel";
this.automaticControlsPanel.Padding = new System.Windows.Forms.Padding(5);
this.automaticControlsPanel.Size = new System.Drawing.Size(328, 695);
this.automaticControlsPanel.TabIndex = 0;
//
// button1
// messurementTOFTolerance
//
this.button1.Location = new System.Drawing.Point(34, 6);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(89, 62);
this.button1.TabIndex = 58;
this.button1.Text = "Start automatic";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click_1);
this.messurementTOFTolerance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messurementTOFTolerance.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.messurementTOFTolerance.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messurementTOFTolerance.Location = new System.Drawing.Point(5, 298);
this.messurementTOFTolerance.Margin = new System.Windows.Forms.Padding(0);
this.messurementTOFTolerance.Name = "messurementTOFTolerance";
this.messurementTOFTolerance.Size = new System.Drawing.Size(318, 24);
this.messurementTOFTolerance.TabIndex = 16;
//
// label42
//
this.label42.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label42.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label42.Location = new System.Drawing.Point(5, 281);
this.label42.Margin = new System.Windows.Forms.Padding(5);
this.label42.Name = "label42";
this.label42.Size = new System.Drawing.Size(318, 18);
this.label42.TabIndex = 15;
this.label42.Text = "Messurement TOF tolerance in %";
this.label42.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// stopAutomaticBtn
//
this.stopAutomaticBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.stopAutomaticBtn.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.stopAutomaticBtn.Location = new System.Drawing.Point(5, 426);
this.stopAutomaticBtn.Margin = new System.Windows.Forms.Padding(5);
this.stopAutomaticBtn.Name = "stopAutomaticBtn";
this.stopAutomaticBtn.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5);
this.stopAutomaticBtn.Size = new System.Drawing.Size(318, 36);
this.stopAutomaticBtn.TabIndex = 13;
this.stopAutomaticBtn.Text = "Stop messurement";
this.stopAutomaticBtn.UseVisualStyleBackColor = true;
this.stopAutomaticBtn.Click += new System.EventHandler(this.StopAutomaticBtn_Clicked);
//
// startAutomaticBtn
//
this.startAutomaticBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.startAutomaticBtn.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.startAutomaticBtn.Location = new System.Drawing.Point(5, 380);
this.startAutomaticBtn.Margin = new System.Windows.Forms.Padding(5);
this.startAutomaticBtn.Name = "startAutomaticBtn";
this.startAutomaticBtn.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5);
this.startAutomaticBtn.Size = new System.Drawing.Size(318, 36);
this.startAutomaticBtn.TabIndex = 12;
this.startAutomaticBtn.Text = "Start messurement";
this.startAutomaticBtn.UseVisualStyleBackColor = true;
this.startAutomaticBtn.Click += new System.EventHandler(this.StartAutomaticBtn_Clicked);
//
// messurementToleranceInC
//
this.messurementToleranceInC.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messurementToleranceInC.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.messurementToleranceInC.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messurementToleranceInC.Location = new System.Drawing.Point(5, 252);
this.messurementToleranceInC.Margin = new System.Windows.Forms.Padding(0);
this.messurementToleranceInC.Name = "messurementToleranceInC";
this.messurementToleranceInC.Size = new System.Drawing.Size(318, 24);
this.messurementToleranceInC.TabIndex = 11;
//
// label11
//
this.label11.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label11.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label11.Location = new System.Drawing.Point(5, 235);
this.label11.Margin = new System.Windows.Forms.Padding(5);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(318, 18);
this.label11.TabIndex = 10;
this.label11.Text = "Messurement tolerance in °C";
this.label11.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// messurementStep
//
this.messurementStep.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messurementStep.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.messurementStep.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messurementStep.Location = new System.Drawing.Point(5, 206);
this.messurementStep.Margin = new System.Windows.Forms.Padding(0);
this.messurementStep.Name = "messurementStep";
this.messurementStep.Size = new System.Drawing.Size(318, 24);
this.messurementStep.TabIndex = 9;
//
// label10
//
this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label10.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label10.Location = new System.Drawing.Point(5, 189);
this.label10.Margin = new System.Windows.Forms.Padding(5);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(318, 18);
this.label10.TabIndex = 8;
this.label10.Text = "Messurement steps in miliseconds";
this.label10.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// messurementDauerInMs
//
this.messurementDauerInMs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messurementDauerInMs.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.messurementDauerInMs.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messurementDauerInMs.Location = new System.Drawing.Point(5, 160);
this.messurementDauerInMs.Margin = new System.Windows.Forms.Padding(0);
this.messurementDauerInMs.Name = "messurementDauerInMs";
this.messurementDauerInMs.Size = new System.Drawing.Size(318, 24);
this.messurementDauerInMs.TabIndex = 7;
//
// label8
//
this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label8.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label8.Location = new System.Drawing.Point(5, 143);
this.label8.Margin = new System.Windows.Forms.Padding(5);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(318, 18);
this.label8.TabIndex = 6;
this.label8.Text = "Messurement dauer in miliseconds";
this.label8.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// temperatureChecksCount
//
this.temperatureChecksCount.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.temperatureChecksCount.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.temperatureChecksCount.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.temperatureChecksCount.Location = new System.Drawing.Point(5, 114);
this.temperatureChecksCount.Margin = new System.Windows.Forms.Padding(0);
this.temperatureChecksCount.Name = "temperatureChecksCount";
this.temperatureChecksCount.Size = new System.Drawing.Size(318, 24);
this.temperatureChecksCount.TabIndex = 5;
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label3.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label3.Location = new System.Drawing.Point(5, 97);
this.label3.Margin = new System.Windows.Forms.Padding(5);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(318, 18);
this.label3.TabIndex = 4;
this.label3.Text = "Temperature checks count";
this.label3.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// temperatureCheckInC
//
this.temperatureCheckInC.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.temperatureCheckInC.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.temperatureCheckInC.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.temperatureCheckInC.Location = new System.Drawing.Point(5, 68);
this.temperatureCheckInC.Margin = new System.Windows.Forms.Padding(0);
this.temperatureCheckInC.Name = "temperatureCheckInC";
this.temperatureCheckInC.Size = new System.Drawing.Size(318, 24);
this.temperatureCheckInC.TabIndex = 3;
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label2.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label2.Location = new System.Drawing.Point(5, 51);
this.label2.Margin = new System.Windows.Forms.Padding(5);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(318, 18);
this.label2.TabIndex = 2;
this.label2.Text = "Temperature checks in °C";
this.label2.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// temperatureCheckInMs
//
this.temperatureCheckInMs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.temperatureCheckInMs.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.temperatureCheckInMs.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.temperatureCheckInMs.Location = new System.Drawing.Point(5, 22);
this.temperatureCheckInMs.Margin = new System.Windows.Forms.Padding(0);
this.temperatureCheckInMs.MinimumSize = new System.Drawing.Size(2, 25);
this.temperatureCheckInMs.Name = "temperatureCheckInMs";
this.temperatureCheckInMs.Size = new System.Drawing.Size(318, 24);
this.temperatureCheckInMs.TabIndex = 1;
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label1.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label1.Location = new System.Drawing.Point(5, 5);
this.label1.Margin = new System.Windows.Forms.Padding(5);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(318, 18);
this.label1.TabIndex = 0;
this.label1.Text = "Temperature checks in miliseconds";
this.label1.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// timer3
//
this.timer3.Interval = 10000;
this.timer3.Tick += new System.EventHandler(this.timer3_Tick);
//
// button3
// mainMenuStrip
//
this.button3.Location = new System.Drawing.Point(641, 26);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(163, 47);
this.button3.TabIndex = 56;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.button3_Click);
this.mainMenuStrip.BackColor = System.Drawing.SystemColors.Control;
this.mainMenuStrip.Location = new System.Drawing.Point(0, 0);
this.mainMenuStrip.Name = "mainMenuStrip";
this.mainMenuStrip.Size = new System.Drawing.Size(1245, 24);
this.mainMenuStrip.TabIndex = 57;
this.mainMenuStrip.Text = "menuStrip1";
//
// messurementExitAfterInMin
//
this.messurementExitAfterInMin.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messurementExitAfterInMin.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.messurementExitAfterInMin.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messurementExitAfterInMin.Location = new System.Drawing.Point(5, 344);
this.messurementExitAfterInMin.Margin = new System.Windows.Forms.Padding(0);
this.messurementExitAfterInMin.Name = "messurementExitAfterInMin";
this.messurementExitAfterInMin.Size = new System.Drawing.Size(318, 24);
this.messurementExitAfterInMin.TabIndex = 18;
//
// label12
//
this.label12.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label12.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.label12.Location = new System.Drawing.Point(5, 327);
this.label12.Margin = new System.Windows.Forms.Padding(5);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(318, 18);
this.label12.TabIndex = 17;
this.label12.Text = "Exit when °C is not changing (in minutes) ";
this.label12.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// FrmTempMeter
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1245, 780);
this.Controls.Add(this.button3);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.lblPcbId);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnConnect);
this.Controls.Add(this.label2);
this.Controls.Add(this.cbComSlot);
this.ClientSize = new System.Drawing.Size(1245, 748);
this.Controls.Add(this.automaticCalibrationTabControl);
this.Controls.Add(this.mainMenuStrip);
this.MainMenuStrip = this.mainMenuStrip;
this.Name = "FrmTempMeter";
this.Text = "FrmTempMeter";
this.tabControl1.ResumeLayout(false);
this.automaticCalibrationTabControl.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage1.PerformLayout();
this.tabPage2.ResumeLayout(false);
@@ -469,23 +656,18 @@
this.tabPage3.ResumeLayout(false);
this.tabPage3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudRef)).EndInit();
this.tabPage4.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.AutomaticCalibrationTab.ResumeLayout(false);
this.automaticControlsPanel.ResumeLayout(false);
this.automaticControlsPanel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ComboBox cbComSlot;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label lblPcbId;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Timer timer2;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabControl automaticCalibrationTabControl;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.Button btnRefreshLut;
private System.Windows.Forms.TextBox txtLuts;
@@ -506,12 +688,29 @@
private System.Windows.Forms.Button btnStopRecord;
private System.Windows.Forms.Button btnStartRecord;
private System.Windows.Forms.TextBox txtCurrentTofs;
private System.Windows.Forms.TabPage tabPage4;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button btnUpdateGrid;
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.TabPage AutomaticCalibrationTab;
private System.Windows.Forms.Timer timer3;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.MenuStrip mainMenuStrip;
private System.Windows.Forms.RichTextBox automaticContentBox;
private System.Windows.Forms.Splitter autometicControlsSplitter;
private System.Windows.Forms.Panel automaticControlsPanel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox temperatureCheckInMs;
private System.Windows.Forms.TextBox temperatureCheckInC;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox temperatureChecksCount;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox messurementDauerInMs;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox messurementStep;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.TextBox messurementToleranceInC;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Button stopAutomaticBtn;
private System.Windows.Forms.Button startAutomaticBtn;
private System.Windows.Forms.TextBox messurementTOFTolerance;
private System.Windows.Forms.Label label42;
private System.Windows.Forms.TextBox messurementExitAfterInMin;
private System.Windows.Forms.Label label12;
}
}
File diff suppressed because it is too large Load Diff
@@ -126,4 +126,7 @@
<metadata name="timer3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>191, 17</value>
</metadata>
<metadata name="mainMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>278, 17</value>
</metadata>
</root>
+10 -2
View File
@@ -25,7 +25,7 @@
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>2</ApplicationRevision>
<ApplicationVersion>1.5.0.%2a</ApplicationVersion>
<ApplicationVersion>2.6.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
@@ -43,7 +43,7 @@
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Xylem.Common.Ui.GenesisToolBox.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
<NoWarn>0003;1591;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -417,13 +417,16 @@
<DependentUpon>FrmTempMeter.cs</DependentUpon>
</Compile>
<Compile Include="Infrastructure\ADLoginModel.cs" />
<Compile Include="Infrastructure\Appsettings.cs" />
<Compile Include="Infrastructure\Software.cs" />
<Compile Include="Infrastructure\SoftwareUser.cs" />
<Compile Include="Infrastructure\SoftwareVersion.cs" />
<Compile Include="Infrastructure\SoftwareFunctions.cs" />
<Compile Include="Infrastructure\TempMeterModels.cs" />
<Compile Include="Infrastructure\UserLoginModel.cs" />
<Compile Include="ProccessConfig.cs" />
<Compile Include="Program.cs" />
<Compile Include="ProgrammState.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="FrmLeagcyTestApp.cs">
<SubType>Form</SubType>
@@ -698,6 +701,10 @@
<Project>{a33e3c6d-eaae-4a20-a0ee-f9e6922fd029}</Project>
<Name>SoftwareAccessHelper</Name>
</ProjectReference>
<ProjectReference Include="..\..\TempFlansh\TempFlansh.csproj">
<Project>{62E5BA37-36AB-4F0A-BC12-554E7A1F1A39}</Project>
<Name>TempFlansh</Name>
</ProjectReference>
<ProjectReference Include="..\..\Utils\ByteArrayStyle\ByteArrayStyle.csproj">
<Project>{8a619cd5-6c8d-420c-a132-7946c6f13e6e}</Project>
<Name>ByteArrayStyle</Name>
@@ -731,6 +738,7 @@
<Content Include="RegAsm4.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="README.md" />
<None Include="Resources\SensusLogoXylem.JPG" />
</ItemGroup>
<ItemGroup>
@@ -10,6 +10,6 @@
<ErrorReportUrlHistory />
<FallbackCulture>de-DE</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ProjectFiles</ProjectView>
<ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup>
</Project>
@@ -0,0 +1,222 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
using System;
using System.ComponentModel;
using System.Configuration;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
internal static class Appsettings
{
private const string EMPTY = "";
private static readonly Configuration configuration = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
private class DefaultValues
{
public const int TemperatureCheckInMs = 6_000;
public const double TemperatureCheckInC = 1.00;
public const int TemperatureChecksCount = 10;
public const int MessurementDauerInMs = 600_000;
public const int MessurementStep = 10_000;
public const double MessurementToleranceInC = 0.05;
public const double MessurementTOFTolerance = 30.00;
public const int ExitWhenNotChangedInMin = 60;
}
public class AppsettingsModel : INotifyPropertyChanged
{
/// <summary>
/// The time in whitch should be checked for temperature changes greater than <see cref="TemperatureCheckInC"/>°C. By default: 1min * 60sec * 1000ms = 60_000ms.
/// After temperature change is detected, messurement should start for <see cref="MessurementDauerInMs"/> in tolerance from +/- <see cref="MessurementToleranceInC"/>°C.
/// </summary>
public string TemperatureCheckInMs
{
get => GetStringValue(DefaultValues.TemperatureCheckInMs);
set => this.NotifyPropertyChanged(value, DefaultValues.TemperatureCheckInMs);
}
/// <summary>
/// The mark on whitch should be notified for temperature change.
/// By default +/-1°C.
/// </summary>
public string TemperatureCheckInC
{
get => GetStringValue(DefaultValues.TemperatureCheckInC);
set => this.NotifyPropertyChanged(value, DefaultValues.TemperatureCheckInC);
}
/// <summary>
/// Describes after how many checks the temperature is counted as same.
/// By default 10.
/// </summary>
public string TemperatureChecksCount
{
get => GetStringValue(DefaultValues.TemperatureChecksCount);
set => this.NotifyPropertyChanged(value, DefaultValues.TemperatureChecksCount);
}
/// <summary>
/// Describes how long should be messured current temperature.
/// By default: 10min * 60sec * 1000ms = 600_000ms.
/// </summary>
public string MessurementDauerInMs
{
get => GetStringValue(DefaultValues.MessurementDauerInMs);
set => this.NotifyPropertyChanged(value, DefaultValues.MessurementDauerInMs);
}
/// <summary>
/// Describes in how many seconds schuld be messured.
/// By default: 10sec * 1000ms = 10_000ms.
/// </summary>
public string MessurementStep
{
get => GetStringValue(DefaultValues.MessurementStep);
set => this.NotifyPropertyChanged(value, DefaultValues.MessurementStep);
}
/// <summary>
/// Describes the temperature tolerance in whitch the messurement is valid.
/// If the tolerance is oversteped, the messurement is canceled.
/// By default: +/-0.05°C.
/// </summary>
public string MessurementToleranceInC
{
get => GetStringValue(DefaultValues.MessurementToleranceInC);
set => this.NotifyPropertyChanged(value, DefaultValues.MessurementToleranceInC);
}
/// <summary>
/// Describes the tolerance in whitch should all TOF's laying (in %).
/// By default: +/-30.00%.
/// </summary>
public string MessurementTOFTolerance
{
get => GetStringValue(DefaultValues.MessurementTOFTolerance);
set => this.NotifyPropertyChanged(value, DefaultValues.MessurementTOFTolerance);
}
/// <summary>
/// Describes in how mutch time schuld the messurement be canceled when temperature not changing.
/// </summary>
public string ExitWhenNotChangedInMin
{
get => GetStringValue(DefaultValues.ExitWhenNotChangedInMin);
set => this.NotifyPropertyChanged(value, DefaultValues.ExitWhenNotChangedInMin);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged<T>(object currentValue, T defaultValue, [CallerMemberName] string property = EMPTY)
{
try
{
currentValue = Convert.ChangeType(currentValue, typeof(T));
}
catch
{
currentValue = defaultValue;
}
currentValue.SetValue<T>(defaultValue, property);
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public static AppsettingsModel Model { get; } = new AppsettingsModel();
/// <summary>
/// <see cref="AppsettingsModel.TemperatureCheckInMs"/>
/// </summary>
public static int TemperatureCheckInMs => GetValue(DefaultValues.TemperatureCheckInMs);
/// <summary>
/// <see cref="AppsettingsModel.TemperatureCheckInC"/>
/// </summary>
public static double TemperatureCheckInC => GetValue(DefaultValues.TemperatureCheckInC);
/// <summary>
/// <see cref="AppsettingsModel.TemperatureChecksCount"/>
/// </summary>
public static int TemperatureChecksCount => GetValue(DefaultValues.TemperatureChecksCount);
/// <summary>
/// <see cref="AppsettingsModel.MessurementDauerInMs"/>
/// </summary>
public static int MessurementDauerInMs => GetValue(DefaultValues.MessurementDauerInMs);
/// <summary>
/// <see cref="AppsettingsModel.MessurementStep"/>
/// </summary>
public static int MessurementStep => GetValue(DefaultValues.MessurementStep);
/// <summary>
/// <see cref="AppsettingsModel.MessurementToleranceInC"/>
/// </summary>
public static double MessurementToleranceInC => GetValue(DefaultValues.MessurementToleranceInC);
/// <summary>
/// <see cref="AppsettingsModel.MessurementTOFTolerance"/>
/// </summary>
public static double MessurementTOFTolerance => GetValue(DefaultValues.MessurementTOFTolerance);
/// <summary>
/// <see cref="AppsettingsModel.ExitWhenNotChangedInMin"/>
/// </summary>
public static int ExitWhenNotChangedInMin => GetValue(DefaultValues.ExitWhenNotChangedInMin);
private static int GetValue(int defaultValue, [CallerMemberName] string property = EMPTY)
{
var setting = configuration.AppSettings.Settings[property]?.Value;
if (int.TryParse($"{setting}", out var value))
{
return value;
}
return defaultValue;
}
private static double GetValue(double defaultValue, [CallerMemberName] string property = EMPTY)
{
var setting = configuration.AppSettings.Settings[property]?.Value;
if (double.TryParse($"{setting}", out var value))
{
return value;
}
return defaultValue;
}
private static string GetStringValue(object defaultValue, string format = EMPTY, [CallerMemberName] string property = EMPTY)
{
return configuration.AppSettings.Settings[property]?.Value ?? defaultValue?.ToString();
}
private static void SetValue<T>(this object value, object @default, [CallerMemberName] string property = EMPTY)
{
if (value == null || value.Equals(default(T)))
{
value = @default;
}
var saved = configuration.AppSettings.Settings[property];
var currentValue = $"{value}";
if (saved is null)
{
configuration.AppSettings.Settings.Add(property, currentValue);
}
else
{
configuration.AppSettings.Settings[property].Value = currentValue;
}
configuration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
}
}
@@ -0,0 +1,430 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Timers;
public class CordonelTempLut
{
public int Id { get; set; }
public int PcbId { get; set; }
public double RefTempC { get; set; }
public double AvgTof { get; set; }
public bool Active { get; set; }
public DateTime? Timestamp { get; set; }
}
public class RefTempRange
{
public Double Min { get; set; }
public Double Max { get; set; }
}
public class LutTemp
{
public int PcbId { get; set; }
public int FromTempC { get; set; }
public int ToTempC { get; set; }
public double? AvgRefTempC { get; set; }
public ICollection<double> ListOfRecordedTofs { get; set; } = new List<double>();
public double? AvgTofs { get; set; }
}
internal enum ProgrammState
{
Start,
Connected,
RecordRuning,
RecordStoped,
RecodCalculated,
}
internal struct Messurement
{
public double T { get; set; }
public double TOF { get; set; }
public DateTime DTS { get; set; }
}
internal class AutomaticTemperatureCalibration
{
private readonly int messurementsCount;
private readonly Func<double> tofSource;
private readonly Timer temperatureWatcher;
private readonly Timer messurementWatcher;
private readonly ICollection<Messurement> messurements;
private int messurmentN;
private double referenceT;
private bool waitingChanges;
private int temperatureChecks;
private int temperatureErrors;
private StreamReader streamReader;
private NamedPipeClientStream pipeStream;
private DateTime? timestamp;
public AutomaticTemperatureCalibration(Func<double> tofSource)
{
this.tofSource = tofSource;
// Instead of time tracking,
this.messurementsCount = Appsettings.MessurementDauerInMs / Appsettings.MessurementStep;
this.temperatureWatcher = new Timer(Appsettings.TemperatureCheckInMs);
this.temperatureWatcher.Elapsed += this.CheckTemperature;
this.messurementWatcher = new Timer(Appsettings.MessurementStep);
this.messurementWatcher.Elapsed += this.Messure;
this.waitingChanges = true;
this.messurements = new List<Messurement>();
}
public event Action Start;
public event Action Stop;
public event Action<string> InfoMessage;
public event Action<string> ErrorMessage;
public event Action<string> WarningMessage;
public event Action<double, double, DateTime> TemperatureMesured;
public void StartMessuring()
{
this.Info(string.Empty);
this.Info($"================================");
this.Info($"[INFO] Starting messurements ...");
if (this.tofSource != null)
{
try
{
this.pipeStream = new NamedPipeClientStream(".", "TempPipe", PipeDirection.In);
this.pipeStream.Connect(3000);
}
catch (Exception e)
{
this.Error(e.Message);
this.Stop?.Invoke();
}
if (this.pipeStream.IsConnected)
{
this.streamReader = new StreamReader(this.pipeStream);
this.StopMessurementWatcher();
this.StartTemperatureWatcher();
this.Start?.Invoke();
}
}
else
{
this.Stop?.Invoke();
this.Info($"\tTOF source is missing.");
}
}
public void StopMessuring()
{
this.Info(string.Empty);
if (this.tofSource != null)
{
this.StopMessurementWatcher();
this.StopTemperatureWatcher();
this.streamReader.Dispose();
this.pipeStream.Close();
}
this.Stop?.Invoke();
this.Info($"[INFO] Messurements canceled.");
this.Info($"=============================");
this.Info(string.Empty);
}
private void Info(string message)
=> this.InfoMessage?.Invoke(message);
private void Warning(string message)
=> this.WarningMessage?.Invoke(message);
private void Error(string message)
=> this.ErrorMessage?.Invoke(message);
private void StartTemperatureWatcher()
{
this.temperatureWatcher.AutoReset = true;
this.temperatureWatcher.Enabled = true;
this.temperatureWatcher.Start();
}
private void StopTemperatureWatcher()
{
this.temperatureWatcher.Stop();
this.temperatureWatcher.Enabled = false;
this.temperatureWatcher.AutoReset = false;
}
private void StartMessurementWatcher()
{
this.messurmentN = 1;
this.messurementWatcher.AutoReset = true;
this.messurementWatcher.Enabled = true;
this.messurementWatcher.Start();
}
private void StopMessurementWatcher()
{
this.messurmentN = 1;
this.messurementWatcher.Stop();
this.messurementWatcher.Enabled = false;
this.messurementWatcher.AutoReset = false;
}
private void CheckTemperature(object sender, ElapsedEventArgs args)
{
// Default start number.
const int start = 1;
// If reading of the reference temperature succeeds.
if (this.TryGetReferenceT(out var referenceT))
{
// Calculating the absolute difference to the previouse temperature.
var differenceT = Math.Abs(this.referenceT - referenceT);
if (this.waitingChanges && differenceT < Appsettings.TemperatureCheckInC)
{
// Reset counter to default.
this.temperatureChecks = 0;
this.Warning($"[CHECK] Temperature is not changed {this.referenceT,5:0.00} <=> {referenceT,5:0.00}°C difference {differenceT,5:0.00}°C {args.SignalTime:hh:mm:ss.fff}ms");
if (this.timestamp.HasValue && Math.Abs((args.SignalTime - this.timestamp.Value).TotalMinutes) > Appsettings.ExitWhenNotChangedInMin)
{
this.StopMessuring();
}
return;
}
this.timestamp = args.SignalTime;
// If difference is greater or equal than configured, reset counter and start tracking the new temperature.
if (differenceT >= Appsettings.TemperatureCheckInC)
{
if (this.temperatureChecks == 0)
{
this.Info(string.Empty);
this.Info($"[CHECK] Start counting: {Appsettings.TemperatureChecksCount} times for {referenceT:0.00}°C +/-{Appsettings.MessurementToleranceInC:0.00}°C");
}
this.waitingChanges = false;
// Start counting from 1.
this.temperatureChecks = start;
// Saving current temperature for fuhrter comparisons.
this.referenceT = referenceT;
var t = differenceT == referenceT ? 0 : differenceT;
this.Info($"[CHECK] {this.temperatureChecks, 2}. {referenceT, 5:0.00}°C difference {t, 5:0.00}°C {args.SignalTime:hh:mm:ss.fff}ms");
}
// If tolerance is smaller or equal than configured,
else if (differenceT <= Appsettings.MessurementToleranceInC)
{
// the temperature is same also continue counting.
this.temperatureChecks++;
this.Info($"[CHECK] {this.temperatureChecks, 2}. {referenceT, 5:0.00}°C difference {differenceT, 5:0.00}°C {args.SignalTime:hh:mm:ss.fff}ms");
}
// If counter reaches configured counts then start messurement for configured time.
if (this.temperatureChecks == Appsettings.TemperatureChecksCount)
{
this.waitingChanges = true;
// Reset counter to default.
this.temperatureChecks = 0;
// Next call breaks current method execution.
this.StopTemperatureWatcher();
// Next call starts new messurement as configured.
this.StartMessurementWatcher();
this.Info(string.Empty);
this.Info($"[INFO] Starting messurement - {args.SignalTime: yyyy-MM-dd hh:mm:ss.ffff}, {Appsettings.MessurementStep}ms for {Appsettings.MessurementDauerInMs}ms");
}
}
else
{
this.waitingChanges = true;
// Reset counter to default.
this.temperatureChecks = 0;
// Reset temperature to default.
this.referenceT = default(double);
this.Info(string.Empty);
this.Warning($"[WARNING] Reading reference temperature failed, resseting state.");
}
}
private void Messure(object sender, ElapsedEventArgs args)
{
// If reading of the reference temperature succeeds ...
if (this.TryGetReferenceT(out var referenceT))
{
var differenceT = Math.Abs(this.referenceT - referenceT);
// If the absolute difference is in expected tolerance.
if (differenceT <= Appsettings.MessurementToleranceInC)
{
this.referenceT = referenceT;
var currentTOF = this.tofSource();
var hasValidTOF = true;
this.Info($"[INFO] {this.messurmentN, 2}. {currentTOF, 19:F18}, {referenceT, 5:0.00}°C, +/-{differenceT, 5:0.00}°C, {args.SignalTime:hh:mm:ss.fff}ms");
// For some LINQ expressions the collection should have at least 1 item in it.
if (this.messurements.Any())
{
// For instance if the tolerance is 30% => 30 / 100 = 0.3
var tolerance = Appsettings.MessurementTOFTolerance / 100;
// Calculating min tolerance: (if TOF = 1) * (1.00 - 0.3 = 0.7) = 0.7 is the min tolerance.
var min = this.messurements.Min(x => x.TOF) * (1.00 - tolerance);
// Calculating max tolerance: (if TOF = 1) * (1.00 + 0.3 = 1.3) = 1.3 is the max tolerance.
var max = this.messurements.Max(x => x.TOF) * (1.00 + tolerance);
// Determinates wheter current TOF is between min and max tolerance
hasValidTOF = currentTOF >= min && currentTOF <= max;
if (!hasValidTOF)
{
this.Error($"[ERROR] Invalid TOF: {currentTOF}");
}
}
// When current TOF is between min and max tolerance
if (hasValidTOF)
{
// New messurement record is created and added to the messurements.
this.messurements.Add(new Messurement
{
T = referenceT,
TOF = currentTOF,
DTS = args.SignalTime
});
}
}
// Else the absolute difference was greater than expected.
else if (differenceT >= Appsettings.TemperatureCheckInC)
{
// Sets the messurements to the calculated count.
// This should breack current method execution in the next step.
this.messurmentN = this.messurementsCount;
this.Warning($"[WARNING] {referenceT:0.00}°C overstepped the tolerance of +/-{Appsettings.TemperatureCheckInC:0.00}.");
}
else
{
this.temperatureErrors++;
this.Warning($"[WARNING] {referenceT:0.00}°C overstepped the tolerance of +/-{Appsettings.MessurementToleranceInC:0.00}.");
this.Warning($"[WARNING] Next time current messurment will be canceled.");
}
// In each case counts 1 more.
this.messurmentN++;
}
else
{
this.Warning($"[WARNING] Reading reference temperature failed.");
}
// If the messurements count is reached.
if (this.messurmentN > this.messurementsCount || this.temperatureErrors > 2)
{
// Calculates the time difference between first and last messurement times.
var timespan = this.messurements.LastOrDefault().DTS - this.messurements.FirstOrDefault().DTS;
// If there are enough messurements, more than the half of the Appsettings.MessurementDauerInMs.
if (timespan.TotalMilliseconds > Appsettings.MessurementDauerInMs / 2)
{
// Average temperature is calculated.
var tmp = this.messurements.Average(x => x.T);
// Average times od flights is calculated.
var tof = this.messurements.Average(x => x.TOF);
this.Info($"[INFO] Data collected over {timespan}, sending average values ...");
// Notifies whit the average values and a timestamp that the messurement is completed.
this.TemperatureMesured?.Invoke(tmp, tof, args.SignalTime);
// All existing messurements are cleared.
this.messurements.Clear();
this.Info($"[SENT] {tmp, 5} {tof, 19} {args.SignalTime}");
}
else
{
this.Error($"[ERROR] {timespan.Milliseconds}ms <= {Appsettings.MessurementDauerInMs / 2}");
}
this.messurmentN = 1;
// In each case, when the messuremens count is reached current method execution should be stopped.
this.StopMessurementWatcher();
// Next call starts seeking for new temperature change.
this.StartTemperatureWatcher();
this.Info($"[INFO] Messurement is done.");
this.Info(string.Empty);
}
}
private bool TryGetReferenceT(out double referenceT)
{
referenceT = 0;
var succeeded = false;
var readAttempts = 1;
var value = string.Empty;
try
{
do
{
lock (this.streamReader)
{
value = this.streamReader.ReadLine();
}
if (double.TryParse(value, NumberStyles.Any, new CultureInfo("de"), out referenceT)
|| double.TryParse(value, NumberStyles.Any, new CultureInfo("us"), out referenceT))
{
succeeded = true;
break;
}
System.Threading.Thread.Sleep(10);
} while (readAttempts++ <= 1000);
}
catch (Exception e)
{
this.Error(e.Message);
}
return succeeded;
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace Xylem.Common.Ui.GenesisToolBox
{
internal enum ProgrammState
{
Start,
Connected,
RecordRuning,
RecordStoped
}
}
+6 -6
View File
@@ -661,8 +661,8 @@ namespace Xylem.Common.Ui.GenesisToolBox
//var regDef = _currentGenesis.GetRegisterDefinitionByName(reg);
SetProgreess($"Read Register {regDef.RegisterName}", total, done + 1);
if (regDef.RegisterDetail != null && (
regDef.RegisterDetail.Privilege.Lvl8 == Access.Ro ||
regDef.RegisterDetail.Privilege.Lvl8 == Access.Rw))
regDef.RegisterDetail.Privilege.Lvl8 == Access.RO ||
regDef.RegisterDetail.Privilege.Lvl8 == Access.RW))
{
try
{
@@ -755,8 +755,8 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
((DataRow)rowItem)["RawValueFile"] = keyValue.value;
if (regDef.RegisterDetail.Privilege.Lvl8 == Access.Ro ||
regDef.RegisterDetail.Privilege.Lvl8 == Access.Rw)
if (regDef.RegisterDetail.Privilege.Lvl8 == Access.RO ||
regDef.RegisterDetail.Privilege.Lvl8 == Access.RW)
{
Byte[] rawRegister;
if (regDef.DataType == typeof(String) || regDef.DataType == typeof(Int64) ||
@@ -1454,8 +1454,8 @@ namespace Xylem.Common.Ui.GenesisToolBox
foreach (var VARIABLE in List)
{
if ((VARIABLE.RegisterDetail.Privilege.Lvl8 == Access.Ro
|| VARIABLE.RegisterDetail.Privilege.Lvl8 == Access.Rw)
if ((VARIABLE.RegisterDetail.Privilege.Lvl8 == Access.RO
|| VARIABLE.RegisterDetail.Privilege.Lvl8 == Access.RW)
)
{
var a = _currentGenesis.ReadRegister(VARIABLE.GetIdent());
@@ -117,10 +117,6 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\MJK\Code\C#\modbus_master_csharp\src\modbus_master_csharp\modbus_master_csharp.csproj">
<Project>{F14940F8-3C86-4BB7-A915-B021E4B3052D}</Project>
<Name>modbus_master_csharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\CommonCore\CommonCore.csproj">
<Project>{1B02C79E-0B19-43E2-8F6B-71EF0C786C97}</Project>
<Name>CommonCore</Name>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
@@ -0,0 +1,111 @@
using XYLEM.Base.Files;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace XYLEM.Base
{
internal static class AppConst
{
static ProgramLogCSVFileClass _Logger = new ProgramLogCSVFileClass();
internal static ProgramLogCSVFileClass Logger { get { return _Logger; } }
internal static bool IsBeta
{
get
{
return true;
//return false;
}
}
//
// Summary:
// Gets the product version associated with this application.
//
// Returns:
// The product version.
internal static string ProductVersion
{
get { return "1.0.0.1"; }
}
/// <summary>
/// Return application MJK No.
/// Have to be manuel changed by programmer for every application to fit install!
/// </summary>
/// <returns>return ex. "840126" </returns>
internal static string ProductMainMJKNo()
{
return "MJK_MAGFLUX_MODBUS";
}
/// <summary>
/// Return MJK Programs standard folder in My documents.
/// </summary>
/// <returns>return ex. "c:\...\My Documents\MJK Automation\" </returns>
internal static string ProgramsUserFolderRootPath()
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MJK Automation\\");
}
/// <summary>
/// Return application folder in My documents.
/// Have to be manuel changed by programmer for every application to fit install!
/// </summary>
/// <returns>return ex. "c:\...\My Documents\MJK Automation\840126\" </returns>
internal static string ProgramUserFolderRootPath()
{
return Path.Combine(ProgramsUserFolderRootPath(), ProductMainMJKNo() + "\\");
}
/// <summary>
/// Return application folder to use for user files.
/// Have to be manuel changed by programmer for every application to fit install!
/// </summary>
/// <returns>return ex. "c:\...\My Documents\MJK Automation\- UserFileSave\" </returns>
internal static string UserFileSavePath()
{
return Path.Combine(ProgramsUserFolderRootPath(), "- UserFileSave\\");
}
/// <summary>
/// Return application folder to use for program user settings .
/// Have to be manual changed by programmer for every application to fit install!
/// </summary>
/// <returns>return ex. "c:\...\My Documents\MJK Automation\840126\UserSettings\" </returns>
internal static string UserFileSettingsPath()
{
return Path.Combine(ProgramUserFolderRootPath(), "UserSettings\\");
}
/// <summary>
/// Try Create UserFileSavePath and SettingPath
/// </summary>
internal static void CreateStandardUserFolders()
{
try
{
if (!Directory.Exists(UserFileSavePath()))
{
Directory.CreateDirectory(UserFileSavePath());
}
if (!Directory.Exists(ProgramUserFolderRootPath()))
{
Directory.CreateDirectory(ProgramUserFolderRootPath());
}
}
catch (Exception ex)
{
Logger.AddToProgramLogFile(true, "Error creating default user folders ", ex.Message);
}
}
}
}
@@ -0,0 +1,314 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base
{
internal static class ByteArrayExtensionClass
{
/// <summary>
/// Compare if values in to array's is equal
/// </summary>
/// <param name="array 1"></param>
/// <param name="array 2"></param>
/// <returns></returns>
public static bool Compare(this byte[] b1, byte[] b2)
{
// Validate buffers are the same length.
// This also ensures that the count does not exceed the length of either buffer.
return b1.SequenceEqual<byte>(b2);
}
/// <summary>
/// Copy a chunk of bytes from start index to a specific LongLength
/// </summary>
/// <param name="from"></param>
/// <param name="startIndex">start offset 0..x</param>
/// <param name="LongLength">LongLength of returned byte data array</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Copy(this byte[] from, long startIndex, long LongLength)
{
try
{
byte[] bArray = new byte[LongLength];
Array.Copy(from, startIndex, bArray, 0, LongLength);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Copy()"));
}
}
/// <summary>
/// Copy a chunk of bytes to the end of array, starting from start offset
/// </summary>
/// <param name="from"></param>
/// <param name="startIndex">start offset 0..x</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Copy(this byte[] from, long startIndex)
{
try
{
long LongLength = from.LongLength - startIndex;
byte[] bArray = new byte[LongLength];
Array.Copy(from, startIndex, bArray, 0, LongLength);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Copy()"));
}
}
/// <summary>
/// Remove a chunk of bytes at the end of array, staring from offset index
/// </summary>
/// <param name="from"></param>
/// <param name="fromIndex">offset 0..x</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Remove(this byte[] from, long fromIndex)
{
try
{
byte[] bArray = new byte[fromIndex];
if (bArray.LongLength < fromIndex)
{
return from;
}
Array.Copy(from, 0, bArray, 0, fromIndex);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Remove()"));
}
}
/// <summary>
/// Copy bytes until this character
/// </summary>
/// <param name="toInSeach">bytes to find character in</param>
/// <param name="untilThisCharacter">detection character</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyUntil(this IEnumerable<byte> toInSeach, char untilThisCharacter)
{
try
{
if (toInSeach != null)
{
var withCharacter = toInSeach.TakeWhile(ch => ch != untilThisCharacter);
// has any data after this
if (withCharacter.Count() > 1)
{
return withCharacter;
}
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyUntil()"));
}
}
/// <summary>
/// Copy bytes after this character
/// </summary>
/// <param name="toInSeach">bytes to find character in</param>
/// <param name="afterFirstCharacterOfThis">detection character</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyAfterThis(this IEnumerable<byte> toInSeach, char afterFirstCharacterOfThis)
{
try
{
if (toInSeach != null)
{
var withCharacter = toInSeach.SkipWhile(ch => ch != afterFirstCharacterOfThis);
// has any data after this
if (withCharacter.Count() > 1)
{
return withCharacter.Skip(1);
}
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyAfterThis()"));
}
}
/// <summary>
/// Copy bytes after this sequence of bytes
/// </summary>
/// <param name="toSeachIn">bytes to find character in</param>
/// <param name="afterFirstCharacterOfThis">detection sequence</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyAfterThis(this IEnumerable<byte> toSeachIn, IEnumerable<byte> afterSequenceThis)
{
try
{
var toSeachNow = toSeachIn;
while ((toSeachNow != null) && (toSeachNow.Count() > 0) && (afterSequenceThis != null))
{
var startCh = afterSequenceThis.First();
var sequenceLng = afterSequenceThis.Count();
toSeachNow = toSeachNow.SkipWhile(ch => ch != startCh);
// If there is data after a possible sequence.. check if it have sequnece
if ((toSeachNow.Count() > sequenceLng) && afterSequenceThis.SequenceEqual(toSeachNow.Take(sequenceLng)))
{
if (toSeachNow.Count() > sequenceLng)
{
return toSeachNow.Skip(afterSequenceThis.Count());
}
return null; // nothing after sequence to return
}
// Not found
if ((toSeachNow == null) || (toSeachNow.Count() == 0))
{
return null; // nothing to return
}
// increase to next to find next start
toSeachNow = toSeachNow.Skip(1);
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyAfterThis()"));
}
}
/// <summary>
/// Swap high and low byte in a word(16bit) for all words in a byte array (use ex. to a line data correct for conversion to computer U16 from modbus u16)
/// </summary>
/// <param name="data">Data to swap (SWAP IS NOT DONE ON A COPY, BUT ON THE ARRAY GIVEN AS INPUT</param>
/// <returns>return swapped input array reference (done to help supporting single line code use ex. "var data = byteArrayNeedingSwap.SwapByteInWord();") </returns>
public static byte[] SwapByteInWord(this byte[] data)
{
try
{
if (data != null)
{
for (long i = 0; i < data.LongLength; i += 2)
{
byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
}
return data;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "SwapByteInWord()"));
}
}
/// <summary>
/// Compare if to array's has the same content (like array1 == array2)
/// </summary>
/// <param name="array1"></param>
/// <param name="array2"></param>
/// <returns>return true if the same</returns>
public static bool IsEqual(this byte[] array1, byte[] array2)
{
try
{
if ((array1 != null) && (array2 != null) && (array1.LongLength == array2.LongLength))
{
// To speed up
var result = array1.SequenceEqual(array2);
//{
//#if (!DEBUG)
//#error Test code!!!
//#endif
//if (!result) {
// var test = "Not the same!!";
// }
//}
return result;
}
return false;// not the same
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "IsEqual()"));
}
}
/// <summary>
/// Slice an array of bytes in the same sizes
/// </summary>
/// <param name="source">Data to slice an array of bytes from</param>
/// <param name="startIndex">start in data for beginning slice of bytes</param>
/// <param name="eachSliceLength">The length of each slice of bytes</param>
/// <returns>List of byte slices with the same size</returns>
public static List<byte[]> SliceSameSize(this byte[] source, long startIndex, long eachSliceLength)
{
try
{
if (source == null)
{
return null;
}
var LongLength = source.LongLength;
var slices = new List<byte[]>();
for (long offset = startIndex; offset < LongLength; offset += eachSliceLength)
{
slices.Add(Copy(source, offset, eachSliceLength));
}
return slices;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "SliceSameSize()"));
}
}
/// <summary>
/// Slice a single array with a specific length
/// </summary>
/// <param name="source">Data to slice an array of bytes from </param>
/// <param name="startIndex">start in data for beginning slice of bytes</param>
/// <param name="length">how long is the slice from start index</param>
/// <returns></returns>
public static byte[] Slice(this byte[] source, long startIndex, long length)
{
try
{
var returnValue = new byte[length];
Array.Copy(source, startIndex, returnValue, 0, length);
return returnValue;
}
catch (Exception ex)
{
throw new InvalidOperationException(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Slice()"));
}
}
/// <summary>
/// Fill or pad array with a specific value
/// </summary>
/// <param name="data"></param>
/// <param name="valueForFill"></param>
/// <returns></returns>
public static byte[] Fill(this byte[] data, byte valueForFill)
{
if (data != null)
{
for (long i = 0; i < data.LongLength; i++)
{
data[i] = valueForFill;
}
}
return data;
}
}
}
@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base
{
internal enum TimeType
{
UTC,
Local
};
internal static class TimeConvertClass
{
/// <summary>
/// convert to a text showing file time ex. [20151201-135917]
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
internal static string ToFileTimeTxt(this DateTime time)
{
return String.Format("[{0}{1:00}{2:00}-{3:00}{4:00}{5:00}]", time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);
}
/// <summary>
/// Convert 1970Sec to 32-bit time to Time
/// </summary>
/// <param name="timeSec1970"></param>
/// <returns></returns>
internal static TimeSpan ConvertTimeSpan(this UInt32 timeSec)
{
return new TimeSpan((int)(timeSec/3600), (int)(timeSec%3600/60), (int)(timeSec%60));
}
internal static string ConvertSecondsToTimeSpanTxt(this Int32 timeSec)
{
return (timeSec >= 0 ? "" : "-") + ((UInt32)Math.Abs(timeSec)).ConvertSecondsToTimeSpanTxt();
}
internal static string ConvertToTimeSpanTxt(this TimeSpan time)
{
if (time.Days > 0)
{
return string.Format((time.Days > 1 ? "{0} days " : "1 day ") + "{1:00}:{2:00}:{3:00}", time.Days, time.Hours, time.Minutes, time.Seconds);
}
return string.Format("{0:00}:{1:00}:{2:00}", time.Hours, time.Minutes, time.Seconds);
}
internal static string ConvertSecondsToTimeSpanTxt(this UInt32 timeSec)
{
TimeSpan time = new TimeSpan((int)(timeSec / 3600), (int)(timeSec % 3600 / 60), (int)(timeSec % 60));
return time.ConvertToTimeSpanTxt();
}
internal static string ConvertSecondsToTimeSpanTxt(this Int16 timeSec)
{
return ConvertSecondsToTimeSpanTxt((Int32)timeSec);
}
internal static string ConvertSecondsToTimeSpanTxt(this UInt16 timeSec)
{
return ConvertSecondsToTimeSpanTxt((UInt32)timeSec);
}
internal static string ConvertMinuteToTimeSpanTxt(this Int16 timeMin)
{
return ConvertSecondsToTimeSpanTxt((Int32)timeMin * 60);
}
internal static string ConvertMinuteToTimeSpanTxt(this UInt16 timeMin)
{
return ConvertSecondsToTimeSpanTxt((UInt32)timeMin * 60);
}
internal static string ConvertHourToTimeSpanTxt(this Int16 timeHour)
{
return ConvertSecondsToTimeSpanTxt((Int32)timeHour * 3600);
}
internal static string ConvertHourToTimeSpanTxt(this UInt16 timeHour)
{
return ConvertSecondsToTimeSpanTxt((UInt32)timeHour * 3600);
}
/// <summary>
/// Convert 1970Sec to 32-bit time to Time
/// </summary>
/// <param name="timeSec1970"></param>
/// <returns></returns>
internal static DateTime Convert1970SecToTime(this UInt32 timeSec1970, TimeType timetype)
{
return timetype == TimeType.Local ?
(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local)).AddSeconds(timeSec1970)
: (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(timeSec1970);
}
/// <summary>
/// Convert Time to 1970Sec
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
internal static UInt32 ConvertTimeTo1970Sec(this DateTime time, TimeType timetype)
{
TimeSpan ts = timetype == TimeType.Local ?
(time - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local))
: (time.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
return Convert.ToUInt32(ts.TotalSeconds);
}
/// <summary>
/// Convert 2000Sec to 32-bit time to Time
/// </summary>
/// <param name="timeSec2000"></param>
/// <returns></returns>
internal static DateTime Convert2000SecToTime(this UInt32 timeSec2000)
{
return (new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(timeSec2000);
}
/// <summary>
/// Convert Time to 2000Sec
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
internal static UInt32 ConvertTimeTo2000Sec(this DateTime time, TimeType timetype)
{
TimeSpan ts = timetype == TimeType.Local ?
(time - new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Local))
: (time.ToUniversalTime() - new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc));
return Convert.ToUInt32(ts.TotalSeconds);
}
/// <summary>
/// Convert time to a String
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public static String ToLocalDateTimeString(this DateTime time)
{
DateTime localTime;
localTime = (time.Kind == DateTimeKind.Utc) ? time.ToLocalTime() : time;
return (localTime.Year.ToString().PadLeft(4, '0') + "/" + localTime.Month.ToString().PadLeft(2, '0') + "/" + localTime.Day.ToString().PadLeft(2, '0') + " "
+ localTime.Hour.ToString().PadLeft(2, '0') + ":" + localTime.Minute.ToString().PadLeft(2, '0') + ":" + localTime.Second.ToString().PadLeft(2, '0'));
}
public static readonly bool IsLocalHourFormatAM_PM = new DateTime(2000, 1, 1, 13, 0, 0).ToLongTimeString().ToLower().Contains("pm");
}
}
@@ -0,0 +1,459 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base
{
public static class DataUnionTools
{
public static byte[] Reverse(this byte[] data)
{
Array.Reverse(data);
return data;
}
}
/// <summary>
/// Convert DataObjClass.DataType to Byte
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct DataUnion
{
//----------------------------- Data String to Convert Rx to ----------------------
#region ---- Inset Data Bytes in union --------
public enum DataByteLayoutType
{
Normal,
SwapAll,
SwapWords // KellerType
}
internal UInt32 Conv32BitToLowAdrHighValue(UInt32 input)
{
return (input >> 16) | (input << 16);
}
/// <summary>
/// Convert input byte data to union data
/// </summary>
/// <param name="u16Data"></param>
/// <returns></returns>
public DataUnion PutByteArray(Byte[] bInputArray, DataByteLayoutType byteType)
{
if (byteType == DataByteLayoutType.SwapAll)
{
Array.Reverse(bInputArray);
}
//dataRxText = "";
if ((bInputArray == null) || (bInputArray.Length == 0))
{
u64Data = 0;
return this;
}
bData = bInputArray[0];
if (bInputArray.Length == 1)
{
return this;
}
bData1 = bInputArray[1];
if (bInputArray.Length == 2)
{ // 16bit / 2 x 8bit
return this;
}
bData2 = bInputArray[2];
if (bInputArray.Length == 3)
{
if (byteType == DataByteLayoutType.SwapWords)
{
throw new Exception("SwapWords Not Supported!");
}
return this;
}
bData3 = bInputArray[3];
if (bInputArray.Length == 4)
{// 32bit / 4 x 8bit
if (byteType == DataByteLayoutType.SwapWords)
{
u32Data = Conv32BitToLowAdrHighValue(u32Data);
}
return this;
}
bData4 = bInputArray[4];
if (bInputArray.Length == 5)
{
if (byteType == DataByteLayoutType.SwapWords)
{
throw new Exception("SwapWords Not Supported!");
}
return this;
}
bData5 = bInputArray[5];
if (bInputArray.Length == 6)
{
if (byteType == DataByteLayoutType.SwapWords)
{
throw new Exception("SwapWords Not Supported!");
}
return this;
}
bData6 = bInputArray[6];
if (bInputArray.Length == 7)
{
if (byteType == DataByteLayoutType.SwapWords)
{
throw new Exception("SwapWords Not Supported!");
}
return this;
}
bData7 = bInputArray[7];
if (byteType == DataByteLayoutType.SwapWords)
{ // 64bit / 8 x 8bit
throw new Exception("SwapWords Not Supported!");
}
return this;
}
#endregion
#region ---- Put data as Value in to union -----
public void PutValue(UInt32 u32DataIn)
{
u32Data = u32DataIn;
}
public void PutValue(Int32 s32DataIn)
{
s32Data = s32DataIn;
}
public void PutValue(Single f32DataIn)
{
f32Data = f32DataIn;
}
public void PutValue(UInt64 u64DataIn)
{
u64Data = u64DataIn;
}
public void PutValue(Int64 s64DataIn)
{
s64Data = s64DataIn;
}
public void PutValue(double f64DataIn)
{
f64Data = f64DataIn;
}
#endregion
#region ---- Get ByteArray from input as a value ----
public byte[] GetByteArray()
{
return new byte[] { bData, bData1, bData2, bData3, bData4, bData5, bData6, bData7 };
}
void DoTxByteLayout(ref byte[] txData, DataByteLayoutType type)
{
try
{
if ((txData == null) || (txData.Length == 0))
{
throw new Exception("Has no txData");
}
switch (type)
{
case DataByteLayoutType.SwapAll: Array.Reverse(txData); break;
case DataByteLayoutType.SwapWords:
if (txData.Length == 4)
{ // 32bit / 2 x word
byte[] firstWord = new byte[2];
Array.Copy(txData, firstWord, 2);
Array.Copy(txData, 2, txData, 0, 2);
Array.Copy(firstWord, 0, txData, 2, 2);
}
else if (txData.Length == 8)
{ // 64bit / 2 x word
throw new Exception("SwapWords Not Supported!");
}
break;
case DataByteLayoutType.Normal: break; // Do nothing
default: throw new Exception("Unkown type = " + type.ToString());
}
}
catch (Exception ex)
{
throw new Exception("Error in " + this + " in func. DoTxByteLayout()! message = " + ex.Message);
}
}
/// <summary>
/// Convert to Tx data to unsigned 16bit
/// </summary>
/// <param name="u16Data"></param>
/// <returns></returns>
public byte[] GetByteArray(UInt16 u16DataIn, DataByteLayoutType byteType)
{
byte[] bDataRet = new byte[2];
u16Data = u16DataIn;
bDataRet[0] = bData;
bDataRet[1] = bData1;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to signed 16bit
/// </summary>
/// <param name="s16Data"></param>
/// <returns></returns>
public byte[] GetByteArray(Int16 s16DataIn, DataByteLayoutType byteType)
{
byte[] bDataRet = new byte[2];
s16Data = s16DataIn;
bDataRet[0] = bData;
bDataRet[1] = bData1;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to unsigned 32bit
/// </summary>
/// <param name="u32Data"></param>
/// <returns></returns>
public byte[] GetByteArray(UInt32 u32DataIn, DataByteLayoutType byteType)
{
PutValue(u32DataIn);
byte[] bDataRet = new byte[4];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to sign 32bit
/// </summary>
/// <param name="s32Data"></param>
/// <returns></returns>
public byte[] GetByteArray(Int32 s32DataIn, DataByteLayoutType byteType)
{
PutValue(s32DataIn);
byte[] bDataRet = new byte[4];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to Single 32bit
/// </summary>
/// <param name="f32Data"></param>
/// <returns></returns>
public byte[] GetByteArray(Single f32DataIn, DataByteLayoutType byteType)
{
PutValue(f32DataIn);
byte[] bDataRet = new byte[4];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to unsigned 64bit
/// </summary>
/// <param name="U64Data"></param>
/// <returns></returns>
public byte[] GetByteArray(UInt64 u64DataIn, DataByteLayoutType byteType)
{
PutValue(u64DataIn);
byte[] bDataRet = new byte[8];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
bDataRet[4] = bData4;
bDataRet[5] = bData5;
bDataRet[6] = bData6;
bDataRet[7] = bData7;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to double (F64bit)
/// </summary>
/// <param name="S64Data"></param>
/// <returns></returns>
public byte[] GetByteArray(Int64 s64DataIn, DataByteLayoutType byteType)
{
PutValue(s64DataIn);
byte[] bDataRet = new byte[8];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
bDataRet[4] = bData4;
bDataRet[5] = bData5;
bDataRet[6] = bData6;
bDataRet[7] = bData7;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
/// <summary>
/// Convert to Tx data to unsigned 64bit
/// </summary>
/// <param name="U64Data"></param>
/// <returns></returns>
public byte[] GetByteArray(double f64DataIn, DataByteLayoutType byteType)
{
PutValue(f64DataIn);
byte[] bDataRet = new byte[8];
bDataRet[0] = bData;
bDataRet[1] = bData1;
bDataRet[2] = bData2;
bDataRet[3] = bData3;
bDataRet[4] = bData4;
bDataRet[5] = bData5;
bDataRet[6] = bData6;
bDataRet[7] = bData7;
DoTxByteLayout(ref bDataRet, byteType);
return bDataRet;
}
#endregion
#region ---- Return Union data as a value ----
public byte U8Data { get { return bData; } set { u16Data = bData; } }
public byte U8Data0 { get { return bData; } }
public byte U8Data1 { get { return bData1; } }
public byte U8Data2 { get { return bData2; } }
public byte U8Data3 { get { return bData3; } }
public byte U8Data4 { get { return bData4; } }
public byte U8Data5 { get { return bData5; } }
public byte U8Data6 { get { return bData6; } }
public byte U8Data7 { get { return bData7; } }
public UInt16 U16Data { get { return u16Data; } set { u16Data = value; } }
public UInt16 U16Data0 { get { return u16Data; } }
public UInt16 U16Data1 { get { return u16Data1; } }
public UInt16 U16Data2 { get { return u16Data2; } }
public UInt16 U16Data3 { get { return u16Data3; } }
public Int16 S16Data { get { return s16Data; } }
public Int16 S16Data0 { get { return s16Data; } }
public Int16 S16Data1 { get { return s16Data1; } }
public Int16 S16Data2 { get { return s16Data2; } }
public Int16 S16Data3 { get { return s16Data3; } }
public UInt32 U32Data { get { return u32Data; } set { u32Data = value; } }
public UInt32 U32Data0 { get { return u32Data; } }
public UInt32 U32Data1 { get { return u32Data1; } }
public Int32 S32Data { get { return s32Data; } set { s32Data = value; } }
public Int32 S32Data0 { get { return s32Data; } }
public Int32 S32Data1 { get { return s32Data1; } }
public Single F32Data { get { return f32Data; } set { f32Data = value; } }
public UInt64 U64Data { get { return u64Data; } }
public Int64 S64Data { get { return s64Data; } }
public double F64Data { get { return f64Data; } }
#endregion
/// <summary>
/// Clear all data and return emptyunion
/// </summary>
/// <returns></returns>
public DataUnion ClearData()
{
u64Data = 0;
return this;
}
#region ---- Field Union Array ----
//----------------------------- Field Union array -----------------------------
[FieldOffset(0)]
private byte bData;
[FieldOffset(1)]
private byte bData1;
[FieldOffset(2)]
private byte bData2;
[FieldOffset(3)]
private byte bData3;
[FieldOffset(4)]
private byte bData4;
[FieldOffset(5)]
private byte bData5;
[FieldOffset(6)]
private byte bData6;
[FieldOffset(7)]
private byte bData7;
[FieldOffset(0)]
private UInt16 u16Data;
[FieldOffset(2)]
private UInt16 u16Data1;
[FieldOffset(4)]
private UInt16 u16Data2;
[FieldOffset(6)]
private UInt16 u16Data3;
[FieldOffset(0)]
private Int16 s16Data;
[FieldOffset(2)]
private Int16 s16Data1;
[FieldOffset(4)]
private Int16 s16Data2;
[FieldOffset(6)]
private Int16 s16Data3;
[FieldOffset(0)]
private UInt32 u32Data;
[FieldOffset(4)]
private UInt32 u32Data1;
[FieldOffset(0)]
private Int32 s32Data;
[FieldOffset(4)]
private Int32 s32Data1;
[FieldOffset(0)]
private Single f32Data;
[FieldOffset(4)]
private Single f32Data1;
[FieldOffset(0)]
private UInt64 u64Data;
[FieldOffset(0)]
private Int64 s64Data;
[FieldOffset(0)]
private double f64Data;
#endregion
};
}
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base.Files
{
internal class PathTools
{
/// <summary>
/// File path trunk
/// </summary>
/// <param name="dirPath"> ex. c:\mainDir\subDir\text.text</param>
/// <param name="trunkLength"> ex. 12 char </param>
/// <returns> ex. will return "...\subDir\text.text" because "subDir\text.text" is > 12 </returns>
public static string FilePathStartTrunk(string dirPath, int trunkLength)
{
try
{
if (!String.IsNullOrEmpty(dirPath) && (dirPath.Length > 40))
{ // if to big .. then trunk it
var pathSplits = dirPath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
if (pathSplits.Length > 0)
{ // are able to trunk
dirPath = "";
foreach (var item in pathSplits.Reverse())
{
dirPath = CombineDirAndFileSubPath(item, dirPath);
if (dirPath.Length > 40)
{
dirPath = CombineDirAndFileSubPath("...", dirPath);
break; // max length is now then just exit loop
}
}
}
}
return dirPath;
}
catch (Exception ex)
{
AppConst.Logger.AddFuncLog(true, "PathTools", "FilePathStartTrunk()", ex);
}
return "?";
}
/// <summary>
/// Create the directory path
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
public static Boolean CreateDirPath(string dirPath)
{
try
{
// Determine whether the directory exists.
if (Directory.Exists(dirPath))
{
//That path exists already
return false;
}
// Try to create the directory.
DirectoryInfo di = Directory.CreateDirectory(dirPath);
return false;
}
catch
{
return true;
}
}
/// <summary>
/// Create the directory for a file path
/// </summary>
/// <param name="pathForFile"></param>
/// <returns>return true on error</returns>
public static bool CreateDirPathForFile(string pathForFile)
{
try
{
return CreateDirPath(GetDirPath(pathForFile));
}
catch
{
return true;
}
}
/// <summary>
/// Combine a directory path and sub path to a compleate path
/// </summary>
/// <param name="dirPath"></param>
/// <param name="subFilePath"></param>
/// <returns></returns>
public static string CombineDirAndFileSubPath(string dirPath, string subFilePath)
{
dirPath = dirPath.Trim().EndsWith("\\") ?
dirPath.Trim().Remove(dirPath.LastIndexOf("\\")) :
dirPath.Trim();
return Path.Combine(dirPath, subFilePath.Trim());
}
/// <summary>
/// Get directory path
/// </summary>
/// <param name="filePath"></param>
/// <returns>return true on error</returns>
public static string GetDirPath(string filePath)
{
return filePath.Remove(filePath.Trim().LastIndexOf("\\"));
}
}
}
@@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base.Files
{
public class ProgramLogCSVFileClass
{
private int _LogCountErrors = -1;
private int _LogCountTotal = -1;
public int LogCountErrors { get { return _LogCountErrors; } }
public int LogCountTotal { get { return _LogCountTotal; } }
public string StdLogFilePath = null;
public event EventHandler OnErrorIsAdded;
#if (!DEBUG)
public bool DoTimeStamp = false;
#else
/*#warning DoTimeStamp is true!!!!!!!!!!!!!!!!
public bool DoTimeStamp = true;*/
public bool DoTimeStamp = false;
#endif
/// <summary>
/// init standard program logger
/// </summary>
/// <param name="stdLogFolderPath">use a custom log folder or null if use default</param>
/// <param name="filename">set a custom log file name without extension (ex. "UserCustomLogFile") or null if use default</param>
public ProgramLogCSVFileClass(string stdLogFolderPath = null, string filename = null)
{
if (String.IsNullOrEmpty(filename))
{
filename = $"{AppConst.ProductVersion}_program_log";
}
if (!string.IsNullOrEmpty(stdLogFolderPath))
{
if (!Directory.Exists(stdLogFolderPath))
{
PathTools.CreateDirPath(stdLogFolderPath);
}
StdLogFilePath=Path.Combine(stdLogFolderPath, filename + ".txt");
}
else
{
this.StdLogFilePath = Path.Combine(AppConst.ProgramUserFolderRootPath(), filename + ".txt");
#if (DEBUG)
Console.WriteLine($"Using standard program log path:\n{this.StdLogFilePath}");
#endif
}
}
/// <summary>
/// Automated get function name for the function calling this
/// Used for automating getting a function name to write in a log
/// </summary>
/// <param name="inclMsg">Add extra message to log with function name </param>
/// <returns>"[CALLING_FUNCTION_NAME]() -> [inclMsg]"</returns>
[MethodImpl(MethodImplOptions.NoInlining)]
public string GetCurrentMethod(string inclMsg = null)
{
var st = new StackTrace();
var sf = st.GetFrame(1);
var nameTxt = $"{sf.GetMethod().Name}()";
if (!String.IsNullOrEmpty(inclMsg))
{
nameTxt += " -> " + inclMsg;
}
return nameTxt;
}
internal void AddToLogFile(bool isError, string nameSingleLine, string infoMultibleLines)
{
AddToLogFile(isError, StdLogFilePath, nameSingleLine, infoMultibleLines);
}
internal void AddToLogFile(bool isError, string LogFilePath, string nameSingleLine, string infoMultibleLines)
{
try
{
if (isError)
{
_LogCountErrors++;
try
{
if (OnErrorIsAdded != null)
{
OnErrorIsAdded(null, null);
}
}
catch { } // Don't handle this if something breaks down
}
_LogCountTotal++;
if (System.IO.File.Exists(LogFilePath))
{
FileInfo f = new FileInfo(LogFilePath);
if (f.Length > (DoTimeStamp ? 1000000 : 10000))
{
f.Delete();
}
}
else
{
PathTools.CreateDirPathForFile(LogFilePath);
}
var message = infoMultibleLines;
var length = message.Length;
File.AppendAllText(LogFilePath, "¤¤¤ " + nameSingleLine.Trim() + " \"" + DateTime.Now.ToString() + "\" ¤¤¤ " + Environment.NewLine
+ message + Environment.NewLine);
#if (DEBUG)
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ") +
" ¤¤¤ " + nameSingleLine.Trim() + " ¤¤¤ " + Environment.NewLine
+ message
);
#endif
}
catch (Exception ex)
{ // Ups just to make sure that this don't result in program is closed
string test = ex.ToMessageText();
}
}
/// <summary>
/// Add a time stamp in program log file.. used to time differend code / controls load time
/// </summary>
/// <param name="processObj"> class or window / control obkject to make time stamp for</param>
/// <param name="desc">description text</param>
/// <param name="forceLog">Force making log and ignore DoTimeStamp setting</param>
internal void AddToTimestampLog(object processObj, string desc, bool forceLog = false)
{
try
{
if (DoTimeStamp || forceLog)
{
AddToLogFile(false, StdLogFilePath, processObj.ToString() + DateTime.Now.ToString(" [HH:mm:ss fff]"), desc);
}
}
catch { }
}
internal void AddToProgramLogFile(bool isError, string nameSingleLine, string infoMultibleLines)
{
AddToLogFile(isError, StdLogFilePath, nameSingleLine, infoMultibleLines);
}
/// <summary>
/// Add to program log
/// </summary>
/// <param name="ex">Exception to log</param>
/// <param name="isError">Is an error or just as log</param>
/// <param name="className">what class or where function is located in</param>
/// <param name="functionName">what function it was in like "myFunc()" and null if not used</param>
/// <param name="dataInfo">Additional information also to include like "while doing x and y..."</param>
internal void ToLog(Exception ex, bool isError, string className, string functionName = null, string dataInfo = null)
{
AddToProgramLogFile(isError, LogMessageTool.ToFuncText(isError, className, functionName),
(String.IsNullOrEmpty(dataInfo) ? "" : dataInfo + ((ex != null) ? Environment.NewLine : "")) // Add data info if used
+ ((ex != null) ? ex.ToMessageText() : ""));
}
internal void AddFuncLog(bool isError, string className, string functionName, string dataInfo, Exception ex)
{
ToLog(ex, isError, className, functionName, dataInfo);
}
internal void AddFuncLog(bool isError, string className, string functionName, Exception ex)
{
AddFuncLog(isError, className, functionName, null, ex);
}
internal void AddFuncLog(bool isError, string className, string functionName, string dataInfo)
{
AddFuncLog(isError, className, functionName, dataInfo, null);
}
internal void AddClassInitLog(bool isError, string className, Exception ex)
{
AddToProgramLogFile(isError, LogMessageTool.ToInitText(isError, className), ((ex != null) ? ex.ToMessageText() : ""));
}
internal void AddClassInitLog(bool isError, string className, string dataInfo, Exception ex)
{
AddToProgramLogFile(isError, LogMessageTool.ToInitText(isError, className, dataInfo), ((ex != null) ? ex.ToMessageText() : ""));
}
internal void OpenProgramLogFile()
{
OpenLogFile(StdLogFilePath);
}
internal void OpenLogFile(string LogFilePath)
{
try
{
Process.Start(LogFilePath);
}
catch (Exception ex)
{
Console.WriteLine("Error Open Log " + Environment.NewLine + ex.ToMessageText());
}
}
}
}
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base
{
public static class LogMessageTool
{
/// <summary>
/// Return Type Name as a string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
static public string TypeName<T>(this T obj)
{
Type t;
if (obj == null)
{
t = typeof(T);
}
else
{
t = obj.GetType();
}
return t.Name;
}
public static string ToMessageText(this Exception ex)
{
if (ex != null)
{
var message = "";
var innerMessage = "";
if (ex.InnerException != null)
{
innerMessage = ToMessageText(ex.InnerException);
}
if ((ex.Message != null) && !String.IsNullOrEmpty(ex.Message))
{
message = ex.Message;
}
if (!String.IsNullOrEmpty(innerMessage))
{
message += (!String.IsNullOrEmpty(message) ? Environment.NewLine : "") + innerMessage;
}
return message;
}
return "";
}
public static string ToFuncText(bool isError, string className, string functionName)
{
var message = (isError ? "Error in class" : "Class ") + className + " and func. " + functionName;
#if(DEBUG)
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ") + message);
#endif
return message;
}
public static string ToInitText(bool isError, string className)
{
var message = (isError ? "Error in init of " : "Init of ") + className;
#if(DEBUG)
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ") + message);
#endif
return message;
}
public static string ToInitText(bool isError, string className, string dataInfo)
{
return ToInitText(isError, className + " info = " + dataInfo);
}
public static string ToFuncErrorText(this Exception ex, string className, string functionName)
{
return ToFuncText(true, className, functionName + ((ex == null) ? "" : Environment.NewLine + "Message = " + ex.ToMessageText()));
}
public static string ToFuncErrorText(this Exception ex, string className, string functionName, string dataInfo)
{
return ToFuncText(true, className, functionName + Environment.NewLine + dataInfo + ((ex == null) ? "" : Environment.NewLine + "Message = " + ex.ToMessageText()));
}
public static string ToFuncErrorText(string className, string functionName, string dataInfo)
{
return ToFuncText(true, className, functionName + Environment.NewLine + dataInfo);
}
public static string ToFuncErrorText(string className, string functionName)
{
return ToFuncText(true, className, functionName);
}
public static string ToInitErrorText(this Exception ex, string className)
{
return ToInitText(true, className + ((ex == null) ? "" : Environment.NewLine + "Message = " + ex.ToMessageText()));
}
}
}
@@ -0,0 +1,602 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace XYLEM.Base
{
public static class NumberConvert
{
public static readonly string ColumnSeperatorCSV = ((2.3).ToString().Contains(".") ? "," : ";");
private static readonly int base10 = 10;
private static readonly char[] cHexa = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
private static readonly int[] iHexaNumeric = new int[] { 10, 11, 12, 13, 14, 15 };
private static readonly int[] iHexaIndices = new int[] { 0, 1, 2, 3, 4, 5 };
private static readonly int asciiDiff = 48;
public static string PadLeft(this String text, int minLength)
{
int iCount = minLength - text.Length;
String textRet = "";
if (iCount > 0)
{
textRet = new String('0', iCount);
}
return textRet + text;
}
/// <summary>
/// Tag for values input is done as "decimal" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsDecimalTag = "decimal";
/// <summary>
/// Tag for values input is done as "binary" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryTag = "binary";
/// <summary>
/// Tag for values input is done as "octal" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsOctalEndTag = "octal";
/// <summary>
/// Tag for values input is done as "0o" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsOctalFrontTag = "0o";
/// <summary>
/// Tag for values input is done as "hex" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsHexEndTag = "hex";
/// <summary>
/// Tag for values input is done as "0x" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsHexFrontTag = "0x";
/// <summary>
/// Tag for values input is done as "bin" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryEndTag = "bin";
/// <summary>
/// Tag for values input is done as "0b" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryFrontTag = "0b";
/// <summary>
/// Convert byte values as in a string byte array
/// </summary>
/// <param name="byteValues"> must be like "0x12, 0x12, 0x12" or "1010bin; 1010bin; 1010bin" or "decimal 123, 123, 123"</param>
/// <returns></returns>
public static byte[] ValuesToBytes(this string byteValues)
{
try
{
List<byte> ret = new List<byte>();
var isHexadecimal = false;
var isDecimal = false;
var isBinary = false;
byteValues = byteValues.Trim().ToLower();
bool isBinaryMatch = (new Regex(@"^[01 ]+$")).IsMatch(byteValues);
bool isHexMatch = (new Regex(@"^[0-9a-f ]+$")).IsMatch(byteValues);
if (!string.IsNullOrEmpty(byteValues) && (byteValues.Contains(ValueInputAsHexEndTag) || byteValues.Contains("0x") || (isHexMatch && !isBinaryMatch)))
{
byteValues = byteValues.ToLower().Replace(ValueInputAsHexEndTag, "");
isHexadecimal = true;
}
else if (!string.IsNullOrEmpty(byteValues) && (byteValues.Contains(ValueInputAsDecimalTag) || isBinaryMatch))
{
byteValues = byteValues.Replace(ValueInputAsDecimalTag, "");
isDecimal = true;
}
else if (!string.IsNullOrEmpty(byteValues) && byteValues.Contains(ValueInputAsBinaryTag))
{
byteValues = byteValues.Replace(ValueInputAsBinaryTag, "");
isBinary = true;
}
var chunks = byteValues.Trim(new char[] { ' ' }).Split(new string[] { ",", ";", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (var value in chunks)
{
var toConvert = value.Trim();
if (!string.IsNullOrEmpty(toConvert))
{
if (isHexadecimal || !isBinary && !isDecimal && (toConvert.StartsWith(ValueInputAsHexFrontTag) || toConvert.ToLower().Contains(ValueInputAsHexEndTag)))
{
ret.Add(Convert.ToByte(toConvert.Replace(ValueInputAsHexFrontTag, "").ToLower().Replace(ValueInputAsHexEndTag, ""), 16));
}
else if (isBinary || !isDecimal && (toConvert.StartsWith(ValueInputAsBinaryFrontTag) || toConvert.ToLower().Contains(ValueInputAsBinaryEndTag)))
{
ret.Add(Convert.ToByte(toConvert.Replace(ValueInputAsBinaryFrontTag, "").ToLower().Replace(ValueInputAsBinaryEndTag, ""), 2));
}
else
{
ret.Add(Convert.ToByte(toConvert, 10));
}
}
}
return ret.ToArray();
}
catch
{
return null; // Error
}
}
public static string UnsignedHexToDecimal(this string Hex)
{
try
{
return Convert.ToUInt64(Hex, 16).ToString();
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this string iDec, int padLeft, bool Add_0x)
{
try
{
return UnsignedDecimalToHex(Convert.ToUInt64(iDec), padLeft, Add_0x);
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this UInt32 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string DecimalToHex(this Int32 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this UInt64 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string DecimalToHex(this Int64 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToBin(this string dec, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(Convert.ToUInt64(dec), 2);
}
catch
{
return "?";
}
}
static string DoAutoPadLeft(this string valueAsStr)
{
var numberToPad = (valueAsStr.Length <= 8) ? 8 : (valueAsStr.Length <= 16) ? 16 : (valueAsStr.Length <= 32) ? 32 : 64;
return valueAsStr.PadLeft(numberToPad, '0');
}
static string DoAutoSpcaePadEvery4Char(this string ValueAsStr)
{
if (String.IsNullOrEmpty(ValueAsStr))
{
return ValueAsStr;
}
else
{
ValueAsStr = ValueAsStr.Trim();
var MissingChar = ValueAsStr.Length % 4;
ValueAsStr = ValueAsStr.PadLeft(ValueAsStr.Length + 4 - MissingChar, '0');
return Regex.Replace(ValueAsStr.Trim(), @"(.{4})", "$1 ").Trim();
}
}
public static string ToUnsignedBin(this int value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase((UInt32)value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToUnsignedBin(this uint value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToUnsignedBin(this Int64 value)
{
try
{
return UnsignedDecimalToBase((UInt32)value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
/// <summary>
/// To string like 0bxxxxxxx depending of selection
/// </summary>
/// <param name="value">what value to show</param>
/// <param name="Add_0b">add 0b in front to indicate it is binary</param>
/// <param name="DoAutoPadLeft">"true" if pad left front with all 0 for the actual value type else "false" only pad with up to 4 bits 0 to easy read</param>
/// <returns></returns>
public static string ToUnsignedBin(this UInt64 value, bool Add_0b, bool DoAutoPadLeft = true)
{
try
{
var ret = UnsignedDecimalToBase(value, 2);
if (ret.Length == 0)
{
ret += "0"; // Always show 0 if no 1 is set
}
if (DoAutoPadLeft)
{
ret = ret.DoAutoPadLeft();
}
else
{
ret = ret.DoAutoSpcaePadEvery4Char();
}
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + ret;
}
catch
{
return "?";
}
}
public static string ToBin(this byte value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToDec(this byte value)
{
return value.ToString("D3");
}
public static string ToHex(this byte value, bool Add_0x)
{
return DecimalToHex(value, 2, Add_0x);
}
public static string ToHex(this byte[] values, bool Add_0x, bool seperatorForCSV)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? (seperatorForCSV ? ColumnSeperatorCSV + " " : ", ") : "") + value.ToHex(Add_0x);
}
return ret;
}
public static string ToDec(this byte[] values)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? ", " : "") + value.ToDec();
}
return ret;
}
public static string ToBin(this byte[] values, bool Add_0b)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? ", " : "") + value.ToBin(Add_0b);
}
return ret;
}
public static string ToHex(this Int16 value, bool Add_0x)
{
return DecimalToHex(value, 4, Add_0x);
}
public static string ToHex(this UInt16 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 4, Add_0x);
}
public static string ToHex(this Int32 value, bool Add_0x)
{
return DecimalToHex(value, 8, Add_0x);
}
public static string ToHex(this UInt32 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 8, Add_0x);
}
public static string ToHex(this Int64 value, bool Add_0x)
{
return DecimalToHex(value, 16, Add_0x);
}
public static string ToHex(this UInt64 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 16, Add_0x);
}
public static string UnsignedDecimalToBase(this string iDec, int numbase)
{
try
{
return UnsignedDecimalToBase(Convert.ToUInt64(iDec), numbase);
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToBase(this UInt64 iDec, int numbase)
{
try
{
String strBin = "";
int[] result = new int[64];
int MaxBit = 64;
for (; iDec > 0; iDec /= (UInt64)numbase)
{
int rem = (int)(iDec % Convert.ToUInt64(numbase));
result[--MaxBit] = rem;
}
for (int i = 0; i < result.Length; i++)
{
if ((int)result.GetValue(i) >= base10)
{
strBin += cHexa[(int)result.GetValue(i) % base10];
}
else
{
strBin += result.GetValue(i);
}
}
strBin = strBin.TrimStart(new char[] { '0' });
return strBin;
}
catch
{
return "?";
}
}
/// <summary>
/// Converter string to a value (0x or 0b is not legal)
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static UInt64 UnsignedBaseToDecimal(this String sBase, int numbase)
{
UInt64 result = 0;
UInt64 b;
UInt64 iProduct = 1;
String sHexa = "";
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (UInt64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (UInt64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (UInt64)sBase[i] - (UInt64)asciiDiff;
}
result += (b * iProduct);
}
return result;
}
/// <summary>
/// Converter string to a value use 0x or 0b
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static UInt64 ToUInt64(this String sBase)
{
UInt64 result = 0;
UInt64 b;
UInt64 iProduct = 1;
String sHexa = "";
int numbase;
sBase = sBase.Trim().ToLower();
if (sBase.StartsWith(ValueInputAsOctalFrontTag))
{
numbase = 8;
sBase = sBase.Replace(ValueInputAsOctalFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsHexFrontTag))
{
numbase = 16;
sBase = sBase.Replace(ValueInputAsHexFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsBinaryFrontTag))
{
numbase = 2;
sBase = sBase.Replace(ValueInputAsBinaryFrontTag, "");
}
else
{
return Convert.ToUInt64(sBase);
}
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (UInt64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (UInt64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (UInt64)sBase[i] - (UInt64)asciiDiff;
}
result += (b * iProduct);
}
return result;
}
/// <summary>
/// Converter string to a value use 0x or 0b
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static Int64 ToInt64(this String sBase)
{
Int64 result = 0;
Int64 b;
Int64 iProduct = 1;
String sHexa = "";
int numbase;
bool isNegative = false;
sBase = sBase.Trim().ToLower();
if (sBase.StartsWith("-"))
{
sBase = sBase.TrimStart('-');
isNegative = true;
}
else if (sBase.StartsWith("+"))
{
sBase = sBase.TrimStart('+');
}
if (sBase.StartsWith(ValueInputAsOctalFrontTag))
{
numbase = 8;
sBase = sBase.Replace(ValueInputAsOctalFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsHexFrontTag))
{
numbase = 16;
sBase = sBase.Replace(ValueInputAsHexFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsBinaryFrontTag))
{
numbase = 2;
sBase = sBase.Replace(ValueInputAsBinaryFrontTag, "");
}
else
{
return isNegative ? -Convert.ToInt64(sBase) : Convert.ToInt64(sBase);
}
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (Int64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (Int64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (Int64)sBase[i] - (Int64)asciiDiff;
}
result += (b * iProduct);
}
return isNegative ? -result : result;
}
public static UInt16 SwapByte(this UInt16 value)
{
return (UInt16)(value >> 8 | (value & 0xFF) << 8);
}
public static UInt64 SwapWord(this UInt64 value)
{
return (UInt64)(value >> 16 | (value & 0xFFFF) << 16);
}
}
}
@@ -0,0 +1,474 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace XYLEM.Base {
#region ---- SMS Char Convert ----
internal class UniCode {
internal UInt32 Value { get; set; }
internal char Ch {
get { return (char)Value; }
set { Value = (UInt32)value; }
}
internal string InfoTxt { get; set; }
public UniCode(UInt32 value, string infoTxt) {
Value = value;
InfoTxt = infoTxt;
}
public override string ToString( ) {
return String.Format( "\"{0}\"=0x{1x} ({2})", (char)Value, Value, InfoTxt );
}
}
// Look at /DOC/Siemens MC55i GSM-charset.pdf
// And http://www.unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT
static class StringConvertToSMSClass {
readonly static Dictionary<byte[], UniCode> ConvTable = new Dictionary<byte[], UniCode>( ){
//{ new Byte[]{0x00}, new UniCode( 0x0040 , "COMMERCIAL AT") }, TMO NOT IN USE
{ new Byte[]{0x40}, new UniCode( 0x0040, "@ Converted to \"INVERTED EXCLAMATION MARK\", Device then TX \"0x00\"") },
//{ new Byte[]{0x40}, new UniCode( 0x00A1 , "INVERTED EXCLAMATION MARK") }, TMO NOT IN USE
{ new Byte[]{0x21,0x2A}, new UniCode( 0x00A1 , "INVERTED EXCLAMATION MARK to \"!*\"") },
{ new Byte[]{0x00}, new UniCode( 0x0000 , "NULL (see note above)") },
{ new Byte[]{0x01}, new UniCode( 0x00A3 , "POUND SIGN") },
{ new Byte[]{0x02}, new UniCode( 0x0024 , "DOLLAR SIGN") },
{ new Byte[]{0x03}, new UniCode( 0x00A5 , "YEN SIGN") },
{ new Byte[]{0x04}, new UniCode( 0x00E8 , "LATIN SMALL LETTER E WITH GRAVE") },
{ new Byte[]{0x05}, new UniCode( 0x00E9 , "LATIN SMALL LETTER E WITH ACUTE") },
{ new Byte[]{0x06}, new UniCode( 0x00F9 , "LATIN SMALL LETTER U WITH GRAVE") },
{ new Byte[]{0x07}, new UniCode( 0x00EC , "LATIN SMALL LETTER I WITH GRAVE") },
{ new Byte[]{0x08}, new UniCode( 0x00F2 , "LATIN SMALL LETTER O WITH GRAVE") },
{ new Byte[]{0x09}, new UniCode( 0x00E7 , "LATIN SMALL LETTER C WITH CEDILLA") },
{ new Byte[]{0x09}, new UniCode( 0x00C7 , "LATIN CAPITAL LETTER C WITH CEDILLA (see note above)") },
{ new Byte[]{0x0A}, new UniCode( 0x000A , "LINE FEED") },
{ new Byte[]{0x0B}, new UniCode( 0x00D8 , "LATIN CAPITAL LETTER O WITH STROKE") },
{ new Byte[]{0x0C}, new UniCode( 0x00F8 , "LATIN SMALL LETTER O WITH STROKE") },
{ new Byte[]{0x0D}, new UniCode( 0x000D , "CARRIAGE RETURN") },
{ new Byte[]{0x0E}, new UniCode( 0x00C5 , "LATIN CAPITAL LETTER A WITH RING ABOVE") },
{ new Byte[]{0x0F}, new UniCode( 0x00E5 , "LATIN SMALL LETTER A WITH RING ABOVE") },
{ new Byte[]{0x10}, new UniCode( 0x0394 , "GREEK CAPITAL LETTER DELTA") },
{ new Byte[]{0x11}, new UniCode( 0x005F , "LOW LINE") },
{ new Byte[]{0x12}, new UniCode( 0x03A6 , "GREEK CAPITAL LETTER PHI") },
{ new Byte[]{0x13}, new UniCode( 0x0393 , "GREEK CAPITAL LETTER GAMMA") },
{ new Byte[]{0x14}, new UniCode( 0x039B , "GREEK CAPITAL LETTER LAMDA") },
{ new Byte[]{0x15}, new UniCode( 0x03A9 , "GREEK CAPITAL LETTER OMEGA") },
{ new Byte[]{0x16}, new UniCode( 0x03A0 , "GREEK CAPITAL LETTER PI") },
{ new Byte[]{0x17}, new UniCode( 0x03A8 , "GREEK CAPITAL LETTER PSI") },
{ new Byte[]{0x18}, new UniCode( 0x03A3 , "GREEK CAPITAL LETTER SIGMA") },
{ new Byte[]{0x19}, new UniCode( 0x0398 , "GREEK CAPITAL LETTER THETA") },
{ new Byte[]{0x1A}, new UniCode( 0x039E , "GREEK CAPITAL LETTER XI") },
{ new Byte[]{0x1B}, new UniCode( 0x00A0 , "ESCAPE TO EXTENSION TABLE (or displayed as NBSP, see note above)") },
{ new Byte[]{0x1B,0x0A}, new UniCode( 0x000C , "FORM FEED") },
{ new Byte[]{0x1B,0x14}, new UniCode( 0x005E , "CIRCUMFLEX ACCENT") },
{ new Byte[]{0x1B,0x28}, new UniCode( 0x007B , "LEFT CURLY BRACKET") },
{ new Byte[]{0x1B,0x29}, new UniCode( 0x007D , "RIGHT CURLY BRACKET") },
{ new Byte[]{0x1B,0x2F}, new UniCode( 0x005C , "REVERSE SOLIDUS") },
{ new Byte[]{0x1B,0x3C}, new UniCode( 0x005B , "LEFT SQUARE BRACKET") },
{ new Byte[]{0x1B,0x3D}, new UniCode( 0x007E , "TILDE") },
{ new Byte[]{0x1B,0x3E}, new UniCode( 0x005D , "RIGHT SQUARE BRACKET") },
{ new Byte[]{0x1B,0x40}, new UniCode( 0x007C , "VERTICAL LINE") },
{ new Byte[]{0x1B,0x65}, new UniCode( 0x20AC , "EURO SIGN") },
{ new Byte[]{0x1C}, new UniCode( 0x00C6 , "LATIN CAPITAL LETTER AE") },
{ new Byte[]{0x1D}, new UniCode( 0x00E6 , "LATIN SMALL LETTER AE") },
{ new Byte[]{0x1E}, new UniCode( 0x00DF , "LATIN SMALL LETTER SHARP S (German)") },
{ new Byte[]{0x1F}, new UniCode( 0x00C9 , "LATIN CAPITAL LETTER E WITH ACUTE") },
{ new Byte[]{0x20}, new UniCode( 0x0020 , "SPACE") },
{ new Byte[]{0x21}, new UniCode( 0x0021 , "EXCLAMATION MARK") },
{ new Byte[]{0x22}, new UniCode( 0x0022 , "QUOTATION MARK") },
{ new Byte[]{0x23}, new UniCode( 0x0023 , "NUMBER SIGN") },
{ new Byte[]{0x24}, new UniCode( 0x00A4 , "CURRENCY SIGN") },
{ new Byte[]{0x25}, new UniCode( 0x0025 , "PERCENT SIGN") },
{ new Byte[]{0x26}, new UniCode( 0x0026 , "AMPERSAND") },
{ new Byte[]{0x27}, new UniCode( 0x0027 , "APOSTROPHE") },
{ new Byte[]{0x28}, new UniCode( 0x0028 , "LEFT PARENTHESIS") },
{ new Byte[]{0x29}, new UniCode( 0x0029 , "RIGHT PARENTHESIS") },
{ new Byte[]{0x2A}, new UniCode( 0x002A , "ASTERISK") },
{ new Byte[]{0x2B}, new UniCode( 0x002B , "PLUS SIGN") },
{ new Byte[]{0x2C}, new UniCode( 0x002C , "COMMA") },
{ new Byte[]{0x2D}, new UniCode( 0x002D , "HYPHEN-MINUS") },
{ new Byte[]{0x2E}, new UniCode( 0x002E , "FULL STOP") },
{ new Byte[]{0x2F}, new UniCode( 0x002F , "SOLIDUS") },
{ new Byte[]{0x30}, new UniCode( 0x0030 , "DIGIT ZERO") },
{ new Byte[]{0x31}, new UniCode( 0x0031 , "DIGIT ONE") },
{ new Byte[]{0x32}, new UniCode( 0x0032 , "DIGIT TWO") },
{ new Byte[]{0x33}, new UniCode( 0x0033 , "DIGIT THREE") },
{ new Byte[]{0x34}, new UniCode( 0x0034 , "DIGIT FOUR") },
{ new Byte[]{0x35}, new UniCode( 0x0035 , "DIGIT FIVE") },
{ new Byte[]{0x36}, new UniCode( 0x0036 , "DIGIT SIX") },
{ new Byte[]{0x37}, new UniCode( 0x0037 , "DIGIT SEVEN") },
{ new Byte[]{0x38}, new UniCode( 0x0038 , "DIGIT EIGHT") },
{ new Byte[]{0x39}, new UniCode( 0x0039 , "DIGIT NINE") },
{ new Byte[]{0x3A}, new UniCode( 0x003A , "COLON") },
{ new Byte[]{0x3B}, new UniCode( 0x003B , "SEMICOLON") },
{ new Byte[]{0x3C}, new UniCode( 0x003C , "LESS-THAN SIGN") },
{ new Byte[]{0x3D}, new UniCode( 0x003D , "EQUALS SIGN") },
{ new Byte[]{0x3E}, new UniCode( 0x003E , "GREATER-THAN SIGN") },
{ new Byte[]{0x3F}, new UniCode( 0x003F , "QUESTION MARK") },
{ new Byte[]{0x41}, new UniCode( 0x0041 , "LATIN CAPITAL LETTER A") },
{ new Byte[]{0x41}, new UniCode( 0x0391 , "GREEK CAPITAL LETTER ALPHA") },
{ new Byte[]{0x42}, new UniCode( 0x0042 , "LATIN CAPITAL LETTER B") },
{ new Byte[]{0x42}, new UniCode( 0x0392 , "GREEK CAPITAL LETTER BETA") },
{ new Byte[]{0x43}, new UniCode( 0x0043 , "LATIN CAPITAL LETTER C") },
{ new Byte[]{0x44}, new UniCode( 0x0044 , "LATIN CAPITAL LETTER D") },
{ new Byte[]{0x45}, new UniCode( 0x0045 , "LATIN CAPITAL LETTER E") },
{ new Byte[]{0x45}, new UniCode( 0x0395 , "GREEK CAPITAL LETTER EPSILON") },
{ new Byte[]{0x46}, new UniCode( 0x0046 , "LATIN CAPITAL LETTER F") },
{ new Byte[]{0x47}, new UniCode( 0x0047 , "LATIN CAPITAL LETTER G") },
{ new Byte[]{0x48}, new UniCode( 0x0048 , "LATIN CAPITAL LETTER H") },
{ new Byte[]{0x48}, new UniCode( 0x0397 , "GREEK CAPITAL LETTER ETA") },
{ new Byte[]{0x49}, new UniCode( 0x0049 , "LATIN CAPITAL LETTER I") },
{ new Byte[]{0x49}, new UniCode( 0x0399 , "GREEK CAPITAL LETTER IOTA") },
{ new Byte[]{0x4A}, new UniCode( 0x004A , "LATIN CAPITAL LETTER J") },
{ new Byte[]{0x4B}, new UniCode( 0x004B , "LATIN CAPITAL LETTER K") },
{ new Byte[]{0x4B}, new UniCode( 0x039A , "GREEK CAPITAL LETTER KAPPA") },
{ new Byte[]{0x4C}, new UniCode( 0x004C , "LATIN CAPITAL LETTER L") },
{ new Byte[]{0x4D}, new UniCode( 0x004D , "LATIN CAPITAL LETTER M") },
{ new Byte[]{0x4D}, new UniCode( 0x039C , "GREEK CAPITAL LETTER MU") },
{ new Byte[]{0x4E}, new UniCode( 0x004E , "LATIN CAPITAL LETTER N") },
{ new Byte[]{0x4E}, new UniCode( 0x039D , "GREEK CAPITAL LETTER NU") },
{ new Byte[]{0x4F}, new UniCode( 0x004F , "LATIN CAPITAL LETTER O") },
{ new Byte[]{0x4F}, new UniCode( 0x039F , "GREEK CAPITAL LETTER OMICRON") },
{ new Byte[]{0x50}, new UniCode( 0x0050 , "LATIN CAPITAL LETTER P") },
{ new Byte[]{0x50}, new UniCode( 0x03A1 , "GREEK CAPITAL LETTER RHO") },
{ new Byte[]{0x51}, new UniCode( 0x0051 , "LATIN CAPITAL LETTER Q") },
{ new Byte[]{0x52}, new UniCode( 0x0052 , "LATIN CAPITAL LETTER R") },
{ new Byte[]{0x53}, new UniCode( 0x0053 , "LATIN CAPITAL LETTER S") },
{ new Byte[]{0x54}, new UniCode( 0x0054 , "LATIN CAPITAL LETTER T") },
{ new Byte[]{0x54}, new UniCode( 0x03A4 , "GREEK CAPITAL LETTER TAU") },
{ new Byte[]{0x55}, new UniCode( 0x0055 , "LATIN CAPITAL LETTER U") },
{ new Byte[]{0x56}, new UniCode( 0x0056 , "LATIN CAPITAL LETTER V") },
{ new Byte[]{0x57}, new UniCode( 0x0057 , "LATIN CAPITAL LETTER W") },
{ new Byte[]{0x58}, new UniCode( 0x0058 , "LATIN CAPITAL LETTER X") },
{ new Byte[]{0x58}, new UniCode( 0x03A7 , "GREEK CAPITAL LETTER CHI") },
{ new Byte[]{0x59}, new UniCode( 0x0059 , "LATIN CAPITAL LETTER Y") },
{ new Byte[]{0x59}, new UniCode( 0x03A5 , "GREEK CAPITAL LETTER UPSILON") },
{ new Byte[]{0x5A}, new UniCode( 0x005A , "LATIN CAPITAL LETTER Z") },
{ new Byte[]{0x5A}, new UniCode( 0x0396 , "GREEK CAPITAL LETTER ZETA") },
{ new Byte[]{0x5B}, new UniCode( 0x00C4 , "LATIN CAPITAL LETTER A WITH DIAERESIS") },
{ new Byte[]{0x5C}, new UniCode( 0x00D6 , "LATIN CAPITAL LETTER O WITH DIAERESIS") },
{ new Byte[]{0x5D}, new UniCode( 0x00D1 , "LATIN CAPITAL LETTER N WITH TILDE") },
{ new Byte[]{0x5E}, new UniCode( 0x00DC , "LATIN CAPITAL LETTER U WITH DIAERESIS") },
{ new Byte[]{0x5F}, new UniCode( 0x00A7 , "SECTION SIGN") },
{ new Byte[]{0x60}, new UniCode( 0x00BF , "INVERTED QUESTION MARK") },
{ new Byte[]{0x61}, new UniCode( 0x0061 , "LATIN SMALL LETTER A") },
{ new Byte[]{0x62}, new UniCode( 0x0062 , "LATIN SMALL LETTER B") },
{ new Byte[]{0x63}, new UniCode( 0x0063 , "LATIN SMALL LETTER C") },
{ new Byte[]{0x64}, new UniCode( 0x0064 , "LATIN SMALL LETTER D") },
{ new Byte[]{0x65}, new UniCode( 0x0065 , "LATIN SMALL LETTER E") },
{ new Byte[]{0x66}, new UniCode( 0x0066 , "LATIN SMALL LETTER F") },
{ new Byte[]{0x67}, new UniCode( 0x0067 , "LATIN SMALL LETTER G") },
{ new Byte[]{0x68}, new UniCode( 0x0068 , "LATIN SMALL LETTER H") },
{ new Byte[]{0x69}, new UniCode( 0x0069 , "LATIN SMALL LETTER I") },
{ new Byte[]{0x6A}, new UniCode( 0x006A , "LATIN SMALL LETTER J") },
{ new Byte[]{0x6B}, new UniCode( 0x006B , "LATIN SMALL LETTER K") },
{ new Byte[]{0x6C}, new UniCode( 0x006C , "LATIN SMALL LETTER L") },
{ new Byte[]{0x6D}, new UniCode( 0x006D , "LATIN SMALL LETTER M") },
{ new Byte[]{0x6E}, new UniCode( 0x006E , "LATIN SMALL LETTER N") },
{ new Byte[]{0x6F}, new UniCode( 0x006F , "LATIN SMALL LETTER O") },
{ new Byte[]{0x70}, new UniCode( 0x0070 , "LATIN SMALL LETTER P") },
{ new Byte[]{0x71}, new UniCode( 0x0071 , "LATIN SMALL LETTER Q") },
{ new Byte[]{0x72}, new UniCode( 0x0072 , "LATIN SMALL LETTER R") },
{ new Byte[]{0x73}, new UniCode( 0x0073 , "LATIN SMALL LETTER S") },
{ new Byte[]{0x74}, new UniCode( 0x0074 , "LATIN SMALL LETTER T") },
{ new Byte[]{0x75}, new UniCode( 0x0075 , "LATIN SMALL LETTER U") },
{ new Byte[]{0x76}, new UniCode( 0x0076 , "LATIN SMALL LETTER V") },
{ new Byte[]{0x77}, new UniCode( 0x0077 , "LATIN SMALL LETTER W") },
{ new Byte[]{0x78}, new UniCode( 0x0078 , "LATIN SMALL LETTER X") },
{ new Byte[]{0x79}, new UniCode( 0x0079 , "LATIN SMALL LETTER Y") },
{ new Byte[]{0x7A}, new UniCode( 0x007A , "LATIN SMALL LETTER Z") },
{ new Byte[]{0x7B}, new UniCode( 0x00E4 , "LATIN SMALL LETTER A WITH DIAERESIS") },
{ new Byte[]{0x7C}, new UniCode( 0x00F6 , "LATIN SMALL LETTER O WITH DIAERESIS") },
{ new Byte[]{0x7D}, new UniCode( 0x00F1 , "LATIN SMALL LETTER N WITH TILDE") },
{ new Byte[]{0x7E}, new UniCode( 0x00FC , "LATIN SMALL LETTER U WITH DIAERESIS") },
{ new Byte[]{0x7F}, new UniCode( 0x00E0 , "LATIN SMALL LETTER A WITH GRAVE") },
};
readonly static string[][] ConvertCh = new string[][]{
new string[]{ "\r", ""},
new string[]{ Environment.NewLine, "\n"},
};
internal static string RemoveIllegalATCh(this string value) {
string ret = value;
foreach (string[] replaceTxt in ConvertCh) {
if (!String.IsNullOrEmpty( replaceTxt[ 0 ] )) {
ret = ret.Replace( replaceTxt[ 0 ], "" );
}
}
return ret;
}
internal static string ReplaceIllegalATCh(this string value) {
string ret = value;
foreach (string[] replaceTxt in ConvertCh) {
if (!String.IsNullOrEmpty( replaceTxt[ 0 ] )) {
ret = ret.Replace( replaceTxt[ 0 ], replaceTxt[ 1 ] );
}
}
return ret;
}
internal static UniCode[] GetUniCodes(this byte[] data) {
try {
List<UniCode> list = new List<UniCode>( );
for (int offset = 0; offset < data.Length; offset++) {
bool found = false;
// check if byte sequens is in convert table
foreach (var code in ConvTable) {
if (data[ offset ] == code.Key.First( )) {
if (code.Key.Length == 1) {
list.Add( code.Value );
found = true;
break;
// Check if it is a combination of to bytes
} else if ((code.Key.Length == 2) && (offset + 1 < data.Length) && (data[ offset + 1 ] == code.Key[ 1 ])) {
offset++;
list.Add( code.Value );
found = true;
break;
}
}
}
if (!found) {
list.Add( new UniCode( data[ offset ], "(The Same)" ) );
}
}
return list.ToArray( );
} catch (Exception ex) {
throw new Exception( "Unable to convert data to " + typeof( UniCode ).ToString( ), ex );
}
}
internal static string ToPcChFromSmsTxt(this byte[] data) {
string txt = "";
try {
for (int offset = 0; offset < data.Length; offset++) {
bool found = false;
// check if byte sequens is in convert table
foreach (var code in ConvTable) {
if (data[ offset ] == code.Key.First( )) {
if (code.Key.Length == 1) {
txt += code.Value.Ch;
found = true;
break;
// Check if it is a combination of to bytes
} else if ((code.Key.Length == 2) && (offset + 1 < data.Length) && (data[ offset + 1 ] == code.Key[ 1 ])) {
offset++;
txt += code.Value.Ch;
found = true;
break;
}
}
}
if (!found) {
txt += (char)data[ offset ];
}
}
return txt.Replace( "\n", Environment.NewLine );
} catch (Exception ex) {
throw new Exception( "Unable to convert char after this \"" + txt + "\"", ex );
}
}
internal static byte[] ToByteFromPcChSMS(this String Txt) {
List<byte> ret = new List<byte>( );
try {
foreach (var ch in Txt.ReplaceIllegalATCh( )) {
bool found = false;
// check if byte sequens is in convert table
foreach (var code in ConvTable) {
if (ch == code.Value.Ch) {
ret.AddRange( code.Key );
found = true;
break;
}
}
if (!found) {
ret.AddRange( ASCIIEncoding.Default.GetBytes( ch.ToString( ) ) );
}
}
return ret.ToArray( );
} catch (Exception ex) {
throw new Exception( "Unable to convert char after this \"" + (ret.Count > 0 ? ret.ToArray( ).ToPcChFromSmsTxt( ) : "None, Is Empty!!") + "\"", ex );
}
}
internal static string ToStringFromPcChSMS(this String Txt) {
string ret = "";
try {
foreach (var ch in Txt.ReplaceIllegalATCh( )) {
bool found = false;
// check if byte sequens is in convert table
foreach (var code in ConvTable) {
if (ch == code.Value.Ch) {
foreach (var cdByte in code.Key) {
ret += (char)cdByte;
}
found = true;
break;
}
}
if (!found) {
foreach (var cdByte in ASCIIEncoding.Default.GetBytes( ch.ToString( ) )) {
ret += (char)cdByte;
}
}
}
return ret;
} catch (Exception ex) {
throw new Exception( "Unable to convert char after this \"" + ret + "\"", ex );
}
}
#region ---- To String ----
private static string ToInfoTxt(byte[] data, UniCode unicode) {
return string.Format( "SMS Ch = 0x{0x}{1} \t\t unicode Ch = {2}",
data.First( ), // 0
((data.Length > 1) ? string.Format( "0x{0x}", data[ 0 ] ) : ""), //1
unicode.ToString( ) ); // 2
}
public static string GetInfoTable( ) {
string txt = "";
foreach (var data in ConvTable) {
txt += ToInfoTxt( data.Key, data.Value ) + Environment.NewLine;
}
return txt;
}
#endregion
}
#endregion
internal static class StringConvert {
/// <summary>
/// Combine string array to a single text
/// </summary>
/// <param name="array">items that is null or empty will be removed</param>
/// <param name="joinWithText">inset string to join between to items (set to null if none)</param>
/// <returns></returns>
internal static string ToSingleString(this string[] array, string joinWithText) {
string ret = "";
if (array != null) {
ret = array.Select( item => (String.IsNullOrEmpty( item ) ? "" : item) ).Aggregate( (current, next) => current + ((joinWithText != null) ? joinWithText : "") + next );
}
return ret;
}
/// <summary>
/// Combine string array to a single text
/// </summary>
/// <param name="array">items that is null or empty will be removed</param>
/// <param name="addNewLine"> new line or a single space is use to join between to item</param>
/// <returns></returns>
internal static string ToSingleString(this string[] array, bool addNewLine) {
return ToSingleString( array, (addNewLine ? Environment.NewLine : " ") );
}
internal static string ToSingleString(this List<string> list, bool addNewLine) {
return ToSingleString( list.ToArray( ), addNewLine );
}
internal static string ToSingleString(this IEnumerable<string> list, bool addNewLine) {
return ToSingleString( list.ToArray( ), addNewLine );
}
internal static byte[] ToBytes(this string value) {
return ASCIIEncoding.Default.GetBytes( value );
}
/// <summary>
/// Convert PC string to at AT OK string (No new line)
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
internal static byte[] ToBytesOkATCh(this string value) {
return ASCIIEncoding.Default.GetBytes( value.RemoveIllegalATCh( ) );
}
internal static string ToPcCh(this byte[] value) {
return ASCIIEncoding.Default.GetString( value );
}
/// <summary>
/// Convert and remove all none printable char
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
internal static string ToPcPrintableCh(this byte[] value) {
return ToPcPrintableCh( value as IEnumerable<byte> );
}
/// <summary>
/// Convert and remove all none printable char
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
internal static string ToPcPrintableCh(this IEnumerable<byte> value) {
string ret = "";
if (value != null) {
foreach (var b in value) {
if (b >= 32) {
ret += ASCIIEncoding.Default.GetString( new byte[] { b } );
} else if (b == '\r') {
ret += Environment.NewLine;
}
}
}
return ret;
}
internal static string ToPcChFromATCh(this byte[] value) {
return ASCIIEncoding.Default.GetString( value ).Replace( "\r", "" ).Replace( "\n", Environment.NewLine );
}
/// <summary>
/// Get all digit sequence in a string and return it as strings
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
internal static string[] GetDecValues(this string values) {
//http://regexhero.net/tester/
//COM8.45 78.463 -676,67 6.454.54.45,4545,4545 (Selecting only the values)
//
MatchCollection matches = Regex.Matches( values, @"[-]|[.]|[-.]|[0-9][0-9]*[.]|[,]*[0-9]+" ); // ([0,1]|([0,1]?\.[0-9]+)) or "^[0-9]*[.]?[0-9]+$"
if (matches.Count != 0) {
List<string> ret = new List<string>( );
foreach (Match value in matches) {
ret.Add( value.Value );
}
return ret.ToArray( );
}
return null;
}
/// <summary>
/// Get first digit sequence in a string and return it as strings
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
internal static string GetDecValue(this string value) {
string[] values = GetDecValues( value );
if (values != null) {
return values.First( );
}
return null;
}
internal static string RemoveZeroTerm(this string value) {
if (!string.IsNullOrEmpty( value ) && value.Contains( '\0' )) {
return value.Remove( value.IndexOf( '\0' ) );
}
return value;
}
}
}
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace XYLEM.Base.XML
{
public static class XMLStringClass
{
public enum XMLVersion
{
V1_0,
V1_1
}
/// <summary>
/// Strips non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// </summary>
/// <param name="txtToClean"></param>
/// <returns></returns>
public static string StripIllegalXMLChars(this string txtToClean)
{
return StripIllegalXMLChars(txtToClean, XMLVersion.V1_1);
}
/// <summary>
/// Strips non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// Refer to http://www.w3.org/TR/2006/REC-xml-20060816/#charsets for XML 1.0
/// </summary>
/// <param name="txtToClean"></param>
/// <param name="version"></param>
/// <returns></returns>
public static string StripIllegalXMLChars(this string txtToClean, XMLVersion version)
{
try
{
string pattern = String.Empty;
txtToClean = txtToClean.
Replace("&", "&amp;").
Replace("<", "&lt;").
Replace(">", "&gt;").
Replace("\"", "&quot;").
Replace("'", "&apos;").
Replace("\r", "&#xD;").
Replace("\n", "&#xA;");
switch (version)
{
case XMLVersion.V1_0:
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|7F|8[0-46-9A-F]9[0-9A-F])";
break;
case XMLVersion.V1_1:
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|[19][0-9A-F]|7F|8[0-46-9A-F]|0?[1-8BCEF])";
break;
}
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(txtToClean))
{
txtToClean = regex.Replace(txtToClean, String.Empty);
}
if (txtToClean.Contains('\0'))
{
txtToClean = txtToClean.Remove(txtToClean.IndexOf('\0'));
}
if (txtToClean.Contains((char)0x1E))
{
txtToClean = txtToClean.Replace((char)0x1E, ' ');
}
{
// Replace any character that has survived this done before
// Replace illegal character in XML documents with blank
// See here for reference http://www.w3.org/TR/xml/#charsets
txtToClean = Regex.Replace(txtToClean, "[\x00-\x08\x0B\x0C\x0E-\x1F]", String.Empty, RegexOptions.Compiled);
}
return txtToClean;
}
catch (Exception ex)
{
throw new Exception("Error in XMLFileIOClass and StripIllegalXMLChars() " + (txtToClean != null ? " txtToClean = " + txtToClean.ToString() : "txtToClean is null"), ex);
}
}
/// <summary>
/// reinset non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// </summary>
/// <param name="txtToClean"></param>
/// <returns></returns>
public static string ReinsetIllegalXMLChars(this string txtToClean)
{
return ReinsetIllegalXMLChars(txtToClean, XMLVersion.V1_1);
}
/// <summary>
/// reinset non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// Refer to http://www.w3.org/TR/2006/REC-xml-20060816/#charsets for XML 1.0
/// </summary>
/// <param name="txtToClean"></param>
/// <param name="version"></param>
/// <returns></returns>
public static string ReinsetIllegalXMLChars(string txtToReinset, XMLVersion version)
{
try
{
string pattern = String.Empty;
txtToReinset = txtToReinset.
Replace("&amp;", "&").
Replace("&lt;", "<").
Replace("&gt;", ">").
Replace("&quot;", "\"").
Replace("&apos;", "'").
Replace("&#xD;", "\r").
Replace("&#xA;", "\n");
return txtToReinset;
}
catch (Exception ex)
{
throw new Exception("Error in XMLFileIOClass and StripIllegalXMLChars() " + (txtToReinset != null ? " txtToClean = " + txtToReinset.ToString() : "txtToClean is null"), ex);
}
}
}
}
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml;
namespace XYLEM.Base.XML
{
internal class XMLWriteFuncClass
{
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
// from https://stackoverflow.com/questions/6115721/how-to-save-restore-serializable-object-to-from-file
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
// from https://stackoverflow.com/questions/6115721/how-to-save-restore-serializable-object-to-from-file
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
}
}
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Communication
{
/// <summary>
/// Class to contain data for a exception
/// </summary>
public struct DeviceExceptionData
{
/// <summary>
/// Special function has to be done when this com
/// https://mjksvn.world.fluidtechnology.net:4443/svn/development/- MJK Standards/- Communication protocols/Modbus/Modbus Specifications.doc
/// "2.2.1 MODBUS Exception Responses:"
/// </summary>
public enum SpecialType
{
DriverError = -1,
WaitForReset = 14, // Wait x sec befor next tx
WaitForFinishMax5s = 252, // Wait Exception OK (max 5s)
OnlyAnInforead = 253, // Used internal to only make an info read about data to read / write (Not intentet for normal TX)
WaitForFinishMax60s = 254, // Wait Exception OK (max 60s)
WaitForFinishMax5Min = 255, // Wait Exception OK (max 5min)
}
/// <summary>
/// Exception No.
/// </summary>
private int _ExcNo;
/// <summary>
/// Exception Info
/// </summary>
private string _Info;
/// <summary>
/// Preload All data.. used when init data array
/// </summary>
/// <param name="iExcNo"></param>
/// <param name="info"></param>
public DeviceExceptionData(int excNo, string info)
{
this._ExcNo = excNo;
this._Info = info;
}
/// <summary>
/// Exception code number
/// </summary>
public int ExcNo
{
get { return _ExcNo; }
set { _ExcNo = value; }
}
/// <summary>
/// Info text to exception no.
/// </summary>
public String Info
{
get { return _Info; }
set { _Info = value; }
}
}
}
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Communication
{
public enum Func_RD : int
{
NoSupport = -1,
No3 = 3,
No4 = 4,
};
public enum Func_WR : int
{
NoSupport = -1,
No15 = 15,
No16 = 16,
};
}
@@ -0,0 +1,634 @@
using MagFlux6200_metrology_reg_list;
using XYLEM.Device;
using XYLEM.Communication.ValueEncoders;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
using XYLEM.Base;
using System.Text.RegularExpressions;
using System.Data;
using System.Security.Policy;
using System.Threading;
namespace XYLEM.Communication
{
/// <summary>
/// Modbus read and write return data type
/// </summary>
/// <typeparam name="T"></typeparam>
public class ModbusDataResult<T> where T : IComparable, IFormattable, IComparable<T>, IEquatable<T>/*, IConvertible is not compatible with BigInteger*/
{
/// <summary>
/// Has the task succeded
/// </summary>
internal bool IsOkay;
/// <summary>
/// Data readed from or written to device
/// </summary>
internal T Data;
/// <summary>
/// What device value info for Data
/// </summary>
internal Device_value Info;
public ModbusDataResult(bool IsOkay, T DataRW, Device_value Info)
{
this.IsOkay = IsOkay;
this.Data = DataRW;
this.Info = Info;
}
}
public class ModbusDataRequest
{
/// <summary>
/// Has the task succeded
/// </summary>
internal bool IsOkay;
/// <summary>
/// Data for return read in from device
/// </summary>
internal object Data;
/// <summary>
/// What device value info for Data
/// </summary>
internal Device_value Info;
public ModbusDataRequest(bool IsOkay, object returnReadIn, Device_value Info)
{
this.IsOkay = IsOkay;
this.Data = returnReadIn;
this.Info = Info;
}
}
public class ModbusCom
{
const int ch_lng_dv = -15;
const int ch_lng_Version = -3;
const int ch_lng_MD_adr = -7;
const int dig_value = 10;
/// <summary>
/// Min delay before a DUT message is expected faild
// Is 1s for testing out that default modbus settings com don't fail
/// </summary>
private readonly int _MaxWaitForComRX_ms = 1000;
/// <summary>
/// Message ended detection delay
/// Min delay before bytes count received and haven't changed result in modbus message ended
/// The 50ms is found to be needed when using DUT RS485 and modbus messages is transparent to Metrology
/// </summary>
private readonly int _DelayBetweenRxByteCheck_ms = 50;
SerialPort _serial;
int _retry;
public int MsgErrorCount { get; private set; }
public int MsgCount { get; private set; }
public void ResetMsgCounters()
{
MsgCount = MsgErrorCount = 0;
}
public ModbusCom(string serial_port, int baudRate, Parity parity, int retry = 3)
{
ResetMsgCounters();
this._serial = new SerialPort();
_serial.PortName = serial_port;
_serial.BaudRate = baudRate;
_serial.Parity= parity;
_serial.DtrEnable = _serial.RtsEnable = true; // Need to be on for Application USB Serial com to detect a connection
//_serial.Handshake = Handshake.RequestToSendXOnXOff;
_serial.ReadTimeout = 100;
if (!_serial.IsOpen)
{
_serial.Open();
}
_retry=retry;
Console.WriteLine($"Serial connection {_serial.PortName}, {_serial.BaudRate}, {_serial.Parity}, retry = {_retry}");
}
/// <summary>
/// Is communication port connected
/// </summary>
/// <returns></returns>
public bool IsConnected()
{
return _serial.IsOpen;
}
/// <summary>
/// Generic value Read of a modbus value ex. "var ret = await Read(_serial, _device_id, req, new Single());"
/// </summary>
/// <typeparam name="T">UInt16, Single ...</typeparam>
/// <param name="device_id"> device ID to use for read</param>
/// <param name="dv"> device value to read</param>
/// <param name="retValue"> a new value of the type to read, to use for init and return</param>
/// <returns>as ModbusDataResult<T> where Item1 is true if okay and Item2 is the value read</returns>
public ModbusDataResult<T> Read<T>(int device_id, Device_value dv, T retValue) where T : IComparable, IFormattable, IComparable<T>, IEquatable<T>/*, IConvertible is not compatible with BigInteger*/
{
ModbusDataResult<T> ret = null;
try
{
byte[] answer = Read_bytes(device_id, dv.MD_adr, dv.Datatype.Length());
retValue = (T)DeviceValueEncoder.Decode(answer, dv.Datatype);
ret = new ModbusDataResult<T>(true, retValue, dv); // Okay
}
catch (Exception ex)
{
var message = $"Read error! from ID={device_id} name={dv.Name} adr={dv.MD_adr} with {dv.Datatype.Length()}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Read()", message);
ret = new ModbusDataResult<T>(false, retValue, dv); // Error
}
return ret;
}
/// <summary>
/// Read multiple value optimized in one or more telegrams from device
/// </summary>
/// <param name="device_id"> Device ID to use for read</param>
/// <param name="dvList"> A list of values to read</param>
/// <returns>List with read okay or failed values</returns>
public List<ModbusDataRequest> Read(int device_id, List<Device_value> dvList)
{
List<ModbusDataRequest> ret = null;
try
{
// ----------- Generate blocks to read -----------
dvList.Sort((dvA, dvB) =>
{
return dvA.MD_adr.CompareTo(dvB.MD_adr);
});
List<List<ModbusDataRequest>> blocks = new List<List<ModbusDataRequest>>();
foreach (var dv in dvList)
{
// if first item, just add it
if ((blocks.Count == 0) || (blocks.Last().Count == 0))
{
if (blocks.Count == 0)
{
blocks.Add(new List<ModbusDataRequest>());
}
blocks.Last().Add(new ModbusDataRequest(false, null, dv));
}
else
{
var dvLast = blocks.Last().Last().Info;
// Only add it if a new value not already to be read
if (dvLast.Name != dv.Name)
{
var nextAdr = dvLast.MD_adr + (dvLast.Datatype.Length()/2);
// If not next to read in current block
if (dv.MD_adr != nextAdr)
{
// then add it to the next read block
blocks.Add(new List<ModbusDataRequest>());
}
blocks.Last().Add(new ModbusDataRequest(false, null, dv));
}
}
}
// ----------- Read blocks -----------
foreach (var dv_group in blocks)
{
try
{
var dvi_first = dv_group.First().Info;
var dvi_last = dv_group.Last().Info;
var startAdr = dvi_first.MD_adr;
var LenBytes = (dvi_last.MD_adr+(dvi_last.Datatype.Length()/2)-startAdr)*2;
if ((LenBytes < 0) || (LenBytes > 250))
{
throw new Exception($"Block length limit Error is {LenBytes}");
}
byte[] answer = Read_bytes(device_id, startAdr, LenBytes);
if (answer == null)
{
throw new Exception($"Read block error! from ID={device_id} from {dvi_first} to {dvi_last}");
}
foreach (var dv_data in dv_group)
{
var dv = dv_data.Info;
var start_idx = (dv.MD_adr-startAdr)*2;
var value_bytes = answer.Copy(start_idx, dv.Datatype.Length());
var value = DeviceValueEncoder.Decode(value_bytes, dv.Datatype);
if (ret == null)
{
ret = new List<ModbusDataRequest>();
}
ret.Add(new ModbusDataRequest(true, value, dv)); // Okay
}
}
//catch (Exception ex)
catch
{
// Retry read it as single values
foreach (var dv_data in dv_group)
{
var dv = dv_data.Info;
byte[] answer = Read_bytes(device_id, dv.MD_adr, dv.Datatype.Length());
var value = DeviceValueEncoder.Decode(answer, dv.Datatype);
if (ret == null)
{
ret = new List<ModbusDataRequest>();
}
ret.Add(new ModbusDataRequest(true, value, dv)); // Okay
}
}
}
return ret;
}
catch (Exception ex)
{
if ((dvList != null) && (dvList.Count() > 0))
{
foreach (var dv in dvList)
{
var message = $"Read error! from ID={device_id} name={dv.Name} adr={dv.MD_adr}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Read()", message);
}
}
else
{
var message = $"Read error! from ID={device_id}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Read()", message);
}
ret = null; // Error
}
return ret;
}
/// <summary>
/// Generic value Write of a modbus value ex. "await Write(_serial, _device_id, req, value)"
/// </summary>
/// <typeparam name="T">UInt16, Single ..</typeparam>
/// <param name="device_id"> device ID to use for write</param>
/// <param name="dv"> device value to write</param>
/// <param name="value"> the value to write</param>
/// <returns></returns>
public bool Write<T>(int device_id, Device_value dv, T value) where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
bool isOkay = true;
try
{
byte[] tx_data = DeviceValueEncoder.Encode(value, dv.Datatype);
if (!Write_bytes(device_id, dv.MD_adr, tx_data))
{
var message = $"Write failed={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={value,dig_value}";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Write()", message);
isOkay = false;
}
}
catch (Exception ex)
{
var message = $"Write error! to ID={device_id} name={dv.Name} adr={dv.MD_adr} with {dv.Datatype.Length()}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Write()", message);
isOkay = false;
}
return isOkay;
}
/// <summary>
/// Write multiple value optimized in one or more telegrams to device
/// </summary>
/// <param name="device_id"> device ID to use for write </param>
/// <param name="reqList"> a list of values to write</param>
/// <returns>A list of values written okay or failed to device</returns>
public List<ModbusDataRequest> Write(int device_id, List<ModbusDataRequest> reqList)
{
List<ModbusDataRequest> ret = null;
try
{
// ----------- Generate blocks to write -----------
reqList.Sort((dvA, dvB) =>
{
return dvA.Info.MD_adr.CompareTo(dvB.Info.MD_adr);
});
List<List<ModbusDataRequest>> blocks = new List<List<ModbusDataRequest>>();
foreach (var req in reqList)
{
// if first item, just add it
if ((blocks.Count == 0) || (blocks.Last().Count == 0))
{
if (blocks.Count == 0)
{
blocks.Add(new List<ModbusDataRequest>());
}
blocks.Last().Add(req);
}
else
{
var req_Last = blocks.Last().Last();
// Only add it if a new value not already written
if (req_Last.Info.Name != req.Info.Name)
{
var nextAdr = req_Last.Info.MD_adr + (req_Last.Info.Datatype.Length()/2);
// If not next to read in current block
if (req.Info.MD_adr != nextAdr)
{
// then add it to the next read block
blocks.Add(new List<ModbusDataRequest>());
}
blocks.Last().Add(req);
}
else
{
throw new Exception($"Only a single Write object to {req_Last.Info.Name} is allowed!");
}
}
}
// ----------- Write blocks -----------
foreach (var req_group in blocks)
{
try
{
var dvi_first = req_group.First().Info;
var dvi_last = req_group.Last().Info;
var startAdr = dvi_first.MD_adr;
var LenBytes = (dvi_last.MD_adr+(dvi_last.Datatype.Length()/2)-startAdr)*2;
if ((LenBytes < 0) || (LenBytes > 250))
{
throw new Exception($"Block length limit Error is {LenBytes}");
}
var tx_group_data = new List<byte>();
foreach (var wr in req_group)
{
byte[] tx_data = DeviceValueEncoder.Encode(wr.Data, wr.Info.Datatype);
if (tx_data == null)
{
throw new Exception($"Fail getting write byte data for {wr.Info.Name}");
}
tx_group_data.AddRange(tx_data);
}
if (LenBytes != tx_group_data.Count)
{
throw new Exception($"Group write from {dvi_first.Name} to {dvi_last.Name} expected={LenBytes} bytes, encoded was={tx_group_data.Count} bytes");
}
var isOkay = Write_bytes(device_id, startAdr, tx_group_data.ToArray());
if (!isOkay)
{
throw new Exception($"Write block error! from ID={device_id} from {dvi_first} to {dvi_last}");
}
ret = new List<ModbusDataRequest>();
foreach (var req in req_group)
{
req.IsOkay = true;
ret.Add(req); // add request that succeed
}
}
//catch (Exception ex) //For debugging
catch
{
ret = new List<ModbusDataRequest>();
// Retry write as single values
foreach (var req in req_group)
{
var dv = req.Info;
byte[] tx_data = DeviceValueEncoder.Encode(req.Data, req.Info.Datatype);
req.IsOkay = Write_bytes(device_id, dv.MD_adr, tx_data);
ret.Add(req); //
}
}
}
return ret;
}
catch (Exception ex)
{
if ((reqList != null) && (reqList.Count() > 0))
{
foreach (var dv in reqList)
{
var message = $"Write error! from ID={device_id} name={dv.Info.Name} adr={dv.Info.MD_adr}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Write()", message);
}
}
else
{
var message = $"Write error! from ID={device_id}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Write()", message);
}
ret = null; // Error
}
return ret;
}
/// <summary>
/// A general modbus read function for just a bunch of bytes
/// </summary>
/// <param name="device_id"> device ID to use for modbus command </param>
/// <param name="md_adr">Start address to data accessed </param>
/// <param name="num_of_bytes">Number of bytes to request</param>
/// <returns>byte data read from device and is null if none / error </returns>
public byte[] Read_bytes(int device_id, int md_adr, int num_of_bytes)
{
var is_write = false;
try
{
// Read address 0 device
var p_transate = new ProtocolTranslateModbusRTUClass();
byte[] tx_data = p_transate.CreateTxData(device_id, (int)Func_RD.No3, md_adr, num_of_bytes, null, is_write);
return modbus_com(md_adr, tx_data, is_write, p_transate);
}
catch (Exception ex)
{
var message = $"!error No data received from ID={device_id} adr={md_adr} with {num_of_bytes} to {(is_write ? "Write" : "Read")}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Read_bytes()", message);
return null;
}
}
/// <summary>
/// A general modbus write function for just a bunch of bytes
/// </summary>
/// <param name="device_id"> device ID to use for modbus command </param>
/// <param name="md_adr">Start address to data accessed </param>
/// <param name="write_data">Byte data to Write</param>
/// <returns> Is true on write is okay </returns>
public bool Write_bytes(int device_id, int md_adr, byte[] write_data)
{
var is_write = true;
try
{
// Read address 0 device
var p_transate = new ProtocolTranslateModbusRTUClass();
byte[] tx_data = p_transate.CreateTxData(device_id, (int)Func_WR.No16, md_adr, write_data.Length, write_data, is_write);
var result = modbus_com(md_adr, tx_data, is_write, p_transate);
if (result != null)
{
return true; // Okay
}
}
catch (Exception ex)
{
var message = $"!error writting data to ID={device_id} adr={md_adr} to {(is_write ? "Write" : "Read")}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "Write_bytes()", message);
}
return false; // Error
}
/// <summary>
/// A general modbus read / write function for just a bunch of bytes
/// </summary>
/// <param name="md_adr">Start address to data accessed </param>
/// <param name="tx_data"> a complet modbus telegram byte data to transmit</param>
/// <param name="is_write"> is the modbus telegram a write or read type to use for eval received result</param>
/// <param name="p_transate">Modbus protocol translater for eval received result</param>
/// <returns>will return null on error or received message on okay</returns>
public byte[] modbus_com(int md_adr, byte[] tx_data, bool is_write, ProtocolTranslateModbusRTUClass p_transate)
{
lock (_serial)
{
try
{
byte[] answer = null;
var retry = 0;
do
{
MsgCount++;
if (!_serial.IsOpen)
{
_serial.Open();
}
_serial.DiscardInBuffer();
_serial.Write(tx_data, 0, tx_data.Length);
int received = 0;
int max_count = _MaxWaitForComRX_ms/_DelayBetweenRxByteCheck_ms;
do
{
received = _serial.BytesToRead;
Thread.Sleep(_DelayBetweenRxByteCheck_ms);
} while (((received == 0) || (received != _serial.BytesToRead)) && (--max_count>0));
if (_serial.BytesToRead <= 0)
{
MsgErrorCount++;
}
} while ((_serial.BytesToRead <= 0) && (++retry < _retry));
if (_serial.BytesToRead <= 0)
{
throw new Exception("!error No data received from device");
}
#if (DEBUG)
// TODO just testing
if (retry > 1)
{
Console.WriteLine($"Warning modbus com {retry-1} retry needed for ID={md_adr} to {(is_write ? "Write" : "Read")}");
}
#endif //#if (DEBUG)
var bytesToRead = _serial.BytesToRead;
var rx_data = new byte[bytesToRead];
var rx_data_len = _serial.Read(rx_data, 0, bytesToRead);
bool isRxRW = p_transate.IsDataRW(rx_data, true);
// Check data func is Read or write
if (isRxRW)
{
// Read
if (!is_write)
{
if (p_transate.IsRead(rx_data, true))
{
answer = p_transate.GetReadData(rx_data, true);
//buf.CallBackOK(bDataTemp, txData, CallBackOK_Single);
}
else
{
throw new Exception("Data Rx Wrong");
}
}
else // Write
{
bool isWrite = p_transate.IsWrite(rx_data, true);
int adr = p_transate.GetRxAdr(rx_data, true);
if (isWrite && (!p_transate.IsAdrPossible(rx_data, true) ? true : (adr == md_adr)))
{
//buf.CallBackOK(null, txData, CallBackOK_Single);
return rx_data; // Is okay return received message
}
else
{
throw new Exception("Data Rx Wrong");
}
}
}
else // Exception received
{
// Normal
if (!p_transate.IsRxWaitForCommand(rx_data, true))
{
int exception = p_transate.GetRxAcknowledgeCode(rx_data, true);
//buf.CallBackError(exception, txData, "");
// If read .. try again after wait
}
else
{
if (!is_write)
{
//buf.Add(txData);
// if Write.. then all must be okay and put event on delay
}
else
{
//buf.CallBackOK(null, txData, CallBackOK_Single);
}
if (p_transate.IsRxWaitForFinishMax60S(rx_data, true))
{
Thread.Sleep((int)(60 * 1000));
}
else if (p_transate.IsRxWaitForFinishMax5Min(rx_data, true))
{
Thread.Sleep((int)(5 * 60 * 1000));
}
else if (p_transate.IsRxWaitForFinishMax5S(rx_data, true))
{
Thread.Sleep((int)(5 * 1000));
}
else
{
int waitTime = 5 * 1000; // default
Thread.Sleep(waitTime); // Wait for reset
}
}
}
return answer;
}
catch (Exception ex)
{
var message = "Error: \n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "modbus_com()", message);
return null;
}
finally
{
_serial.Close();
}
}
}
}
}
@@ -0,0 +1,572 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using XYLEM.Base;
namespace XYLEM.Communication
{
public class ProtocolTranslateModbusRTUClass
{
public enum FunctionNumber : byte
{
NoSupport = 0,
Read_No3 = 3,
Read_No4 = 4,
Write_No15 = 15,
Write_No16 = 16,
};
/// <summary>
/// Modbus Byte Offset for write data telegram
/// </summary>
private enum BaseOffset
{
ID = 0,
FuncCode
}
/// <summary>
/// Modbus Byte Offset for write data telegram
/// </summary>
private enum TxOffset_W
{
AdrHigh = (int)BaseOffset.FuncCode + 1,
AdrLow,
RegCount_High,
RegCount_Low,
ByteCount,
Data_Start
};
/// <summary>
/// Modbus Byte Offset for read data telegram
/// </summary>
private enum TxOffset_R
{
AdrHigh = (int)BaseOffset.FuncCode + 1,
AdrLow,
RegCount_High, RegCount_Low
};
/// <summary>
/// Modbus Byte Offset for read data telegram
/// </summary>
private enum RxOffset_R
{
ByteCount = (int)BaseOffset.FuncCode + 1,
Data_Start
};
/// <summary>
/// Modbus Byte Offset for read data telegram
/// </summary>
private enum RxOffset_W
{
AdrHigh = (int)BaseOffset.FuncCode + 1,
AdrLow,
RegCount_High, RegCount_Low
};
/// <summary>
/// Modbus Byte Offset for exception data telegram
/// </summary>
private enum TxRxOffset_Exc
{
ExceptionCode = (int)BaseOffset.FuncCode + 1
};
/// <summary>
/// Calc CRC
/// </summary>
/// <param name="bByteData"></param>
/// <param name="iDataCount"></param>
/// <returns></returns>
private UInt16 CalcCrc(Byte[] bByteData, int iDataCount)
{
int u8CountByte;
byte u8Temp, u8CountBit;
UInt16 u16RetCRCvalue;
u16RetCRCvalue = 0xffff;
for (u8CountByte = 0; u8CountByte < iDataCount; u8CountByte++)
{ // Udregn CRC værdien
u16RetCRCvalue ^= bByteData[u8CountByte];
for (u8CountBit = 0; u8CountBit < 8; u8CountBit++)
{
u8Temp = (Byte)(u16RetCRCvalue & 1);
u16RetCRCvalue >>= 1;
if (u8Temp == 1)
{
u16RetCRCvalue ^= 0xa001;
}
}
}
return u16RetCRCvalue;
}
#region IProtocolTranslateClass Members
public int MaxDataReadBSize()
{
return 250; ////(252-1"Number of bytes to read")/2=125 MODBUS over _serial line specification and implementation guide V1.02 (Page 13) + Func 4/3
}
public int MaxDataWriteBSize()
{
return 230; //
}
public void StampReset() { }
public byte StampNow
{
get { return 0; } // Off
}
/// <summary>
/// Create a tx modbus message
/// </summary>
/// <param name="slaveID"></param>
/// <param name="rwFuncNo"></param>
/// <param name="adr"></param>
/// <param name="dataByteSize"></param>
/// <param name="writeData"></param>
/// <param name="IsDeviceResponse"></param>
/// <returns></returns>
public byte[] CreateTxData(int slaveID, int rwFuncNo, int adr, int dataByteSize, Byte[] writeData, bool IsDeviceResponse)
{
try
{
Byte bTemp;
Byte[] txData = null;
int count = 0, iCRC;
// Convert to modb us func number
FunctionNumber funcNo;
switch (rwFuncNo)
{
case (int)Func_RD.No3: funcNo = FunctionNumber.Read_No3; break;
case (int)Func_RD.No4: funcNo = FunctionNumber.Read_No4; break;
case (int)Func_WR.No15: funcNo = FunctionNumber.Write_No15; break;
case (int)Func_WR.No16: funcNo = FunctionNumber.Write_No16; break;
default: throw new Exception(LogMessageTool.ToFuncErrorText(this.ToString(), "CreateTxData()", "Incorrect func = " + rwFuncNo.ToString()));
}
#region ---- Read ----
if ((funcNo == FunctionNumber.Read_No3) || (funcNo == FunctionNumber.Read_No4))
{
if (IsDeviceResponse)
{
if ((writeData == null) && (dataByteSize != writeData.Length))
{
var dataBLng = (writeData == null ? 0 : writeData.Length);
throw new Exception("Data length is not the same expected " + dataByteSize + " but is " + dataBLng);
}
count = (int)RxOffset_R.Data_Start + dataByteSize;
txData = new Byte[count + 2/*to crc*/ ];
txData[(int)BaseOffset.ID] = (byte)slaveID;
txData[(int)BaseOffset.FuncCode] = (byte)funcNo;
txData[(int)RxOffset_R.ByteCount] = (byte)dataByteSize;
// Copy and Swap High And Low byte in word
for (int offset = 0; offset < dataByteSize; offset += 2)
{
bTemp = writeData[offset];
txData[(int)RxOffset_R.Data_Start + offset] = writeData[offset + 1];
txData[(int)RxOffset_R.Data_Start + offset + 1] = bTemp;
}
}
else
{
dataByteSize = (dataByteSize == 1) ? 2 : dataByteSize;
txData = new Byte[(int)TxOffset_R.RegCount_Low + 3];
txData[(int)BaseOffset.ID] = (byte)slaveID;
txData[(int)BaseOffset.FuncCode] = (byte)funcNo;
txData[(int)TxOffset_R.AdrHigh] = (byte)(adr >> 8);
txData[(int)TxOffset_R.AdrLow] = (byte)adr;
txData[(int)TxOffset_R.RegCount_High] = (byte)0;
txData[(int)TxOffset_R.RegCount_Low] = (byte)(dataByteSize >> 1);
count = (int)TxOffset_R.RegCount_Low + 1;
}
}
#endregion// Read
#region ---- Write ----
if ((funcNo == FunctionNumber.Write_No16) || (funcNo == FunctionNumber.Write_No15))
{
dataByteSize = writeData.Length;
dataByteSize = (dataByteSize == 1) ? 2 : dataByteSize;
txData = new Byte[(int)TxOffset_W.Data_Start + dataByteSize + 2];
txData[(int)BaseOffset.ID] = (byte)slaveID;
txData[(int)BaseOffset.FuncCode] = (byte)funcNo;
txData[(int)TxOffset_W.AdrHigh] = (byte)(adr >> 8);
txData[(int)TxOffset_W.AdrLow] = (byte)adr;
txData[(int)TxOffset_W.RegCount_High] = (byte)0;
txData[(int)TxOffset_W.RegCount_Low] = (byte)(dataByteSize >> 1);
txData[(int)TxOffset_W.ByteCount] = (byte)dataByteSize;
// Copy and Swap High And Low byte in word
for (count = 0; count < dataByteSize; count += 2)
{
bTemp = writeData[count];
txData[(int)TxOffset_W.Data_Start + count] = writeData[count + 1];
txData[(int)TxOffset_W.Data_Start + count + 1] = bTemp;
}
count = dataByteSize + (int)TxOffset_W.Data_Start;
}
#endregion// Write
iCRC = CalcCrc(txData, count);
txData[count] = (byte)iCRC;
txData[count + 1] = (byte)(iCRC >> 8);
return txData; // OK
}
catch
{
return null; // Error
}
}
public bool IsDataOkay(byte[] data, bool IsDeviceResponse)
{
int iCRC;
int length = (data != null) ? data.Length : 0;
iCRC = data[length - 1];
iCRC = data[length - 2] + (iCRC << 8);
return (CalcCrc(data, length - 2) == iCRC) || (CalcCrc(data, length - 2) == (((iCRC & 0xff) << 8) | (iCRC >> 8))); // Keller Fix
}
public bool IsRxDataOkay(byte[] data)
{
return IsDataOkay(data, true);
}
public bool IsDataRW(byte[] data, bool IsDeviceResponse)
{
return (data[(int)BaseOffset.FuncCode] < 0x80);
}
public bool IsRead(byte[] data, bool IsDeviceResponse)
{
return data[(int)BaseOffset.FuncCode] == (int)FunctionNumber.Read_No3
|| data[(int)BaseOffset.FuncCode] == (int)FunctionNumber.Read_No4;
}
public byte[] GetReadData(byte[] data, bool IsDeviceResponse)
{
try
{
Byte[] retData = new Byte[(int)data[(int)RxOffset_R.ByteCount]];
int offset = 0, length = 0, func = data[(int)BaseOffset.FuncCode];
if ((func == (int)FunctionNumber.Read_No3) || (func == (int)FunctionNumber.Read_No4))
{
offset = (int)RxOffset_R.Data_Start;
length = retData.Length;
if (data.Count() < length)
{
throw new Exception($"Data lng ={data.Count()} is expecting min. {length}");
}
if (length == 0)
{
return null; // Error
}
for (int iTemp = 0; (iTemp < length); iTemp += 2)
{
retData[iTemp + 1] = data[offset + iTemp];
retData[iTemp] = data[offset + iTemp + 1];
}
}
else
{
return null; // Error
}
return retData;
}
catch (Exception ex)
{
var dataAsTxt = (data==null) ? "Data is null" : data.ToHex(true, false);
var message = $"Error: data={dataAsTxt}\n\r" + ex.Message + "\n\r";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "GetReadData()", message);
throw new Exception(message);
}
}
public bool IsWrite(byte[] data, bool IsDeviceResponse)
{
return (data[(int)BaseOffset.FuncCode] == (int)FunctionNumber.Write_No16);
}
public bool IsAdrPossible(byte[] data, bool IsDeviceResponse)
{
return false;
}
public int GetRxAdr(byte[] data, bool IsDeviceResponse)
{
return ((int)data[(int)RxOffset_W.AdrHigh] << 8) | (int)data[(int)RxOffset_W.AdrLow];
}
public bool IsRxWaitForCommand(byte[] data, bool IsDeviceResponse)
{
return
(data[(int)TxRxOffset_Exc.ExceptionCode] == (int)DeviceExceptionData.SpecialType.WaitForReset)
|| IsRxWaitForFinishMax5S(data, IsDeviceResponse)
|| IsRxWaitForFinishMax60S(data, IsDeviceResponse)
|| IsRxWaitForFinishMax5Min(data, IsDeviceResponse);
}
public bool IsRxWaitForFinishMax5S(byte[] data, bool IsDeviceResponse)
{
return data[(int)TxRxOffset_Exc.ExceptionCode] == (int)DeviceExceptionData.SpecialType.WaitForFinishMax5s;
}
public bool IsRxWaitForFinishMax60S(byte[] data, bool IsDeviceResponse)
{
return data[(int)TxRxOffset_Exc.ExceptionCode] == (int)DeviceExceptionData.SpecialType.WaitForFinishMax60s;
}
public bool IsRxWaitForFinishMax5Min(byte[] data, bool IsDeviceResponse)
{
return data[(int)TxRxOffset_Exc.ExceptionCode] == (int)DeviceExceptionData.SpecialType.WaitForFinishMax5Min;
}
public bool IsAcknowledge(byte[] data, bool IsDeviceResponse)
{
return data[(int)BaseOffset.FuncCode] >= 0x80;
}
public int GetRxAcknowledgeCode(byte[] data, bool IsDeviceResponse)
{
return data[(int)TxRxOffset_Exc.ExceptionCode];
}
public ProtocolType Protocol
{
get { return ProtocolType.ModbusRTU; }
}
public int GetFuncNo(byte[] rx_data, bool IsDeviceResponse)
{
return (int)rx_data[(int)BaseOffset.FuncCode];
}
public int GetStartAdr(byte[] rx_data, bool IsDeviceResponse)
{
if (IsWrite(rx_data, IsDeviceResponse))
{
return GetRxAdr(rx_data, IsDeviceResponse);
}
else if (IsRead(rx_data, IsDeviceResponse))
{
return GetRxAdr(rx_data, IsDeviceResponse); // Is master read
}
throw new Exception("Unknown protocol type and location for start adr.");
}
public int GetNumberOfDataBytes(byte[] rx_data, bool IsDeviceResponse)
{
if (IsWrite(rx_data, IsDeviceResponse))
{
return rx_data[(int)RxOffset_W.RegCount_Low] * 2;
}
else if (IsRead(rx_data, IsDeviceResponse))
{
if (IsDeviceResponse)
{
return rx_data[(int)RxOffset_R.ByteCount];
}
else
{
return rx_data[(int)RxOffset_W.RegCount_Low] * 2;
}
}
throw new Exception("Unknown protocol type and location for number of bytes");
}
public int GetComID(byte[] rx_data, bool IsDeviceResponse)
{
return rx_data[(int)BaseOffset.ID];
}
public byte[] GetWriteData(byte[] rx_data, bool IsDeviceResponse)
{
var bytesToWrite = GetNumberOfDataBytes(rx_data, IsDeviceResponse);
try
{
var data = Base.ByteArrayExtensionClass.SwapByteInWord(rx_data.Copy((int)TxOffset_W.Data_Start, bytesToWrite));
return data;
}
catch (Exception)
{
throw new Exception("Fail to copy write data! data byte size = " + bytesToWrite);
}
}
public byte[] CreateTxData(int slaveID, int rwFuncNo, int adr, int writeResponse, bool IsDeviceResponse)
{
throw new NotImplementedException();
}
public string ToInfo(byte[] input, bool IsDeviceResponse)
{
string ret = "";
try
{
bool isOkay = IsDataOkay(input, IsDeviceResponse);
if (isOkay)
{
int id = GetComID(input, IsDeviceResponse);
int func = GetFuncNo(input, IsDeviceResponse);
ret += string.Format("Type {0}" + Environment.NewLine, IsDeviceResponse ? "Response" : "Request");
ret += string.Format("ID {0}" + Environment.NewLine, id);
bool isExeption = !IsDataRW(input, IsDeviceResponse);
try
{
var func2Test = func;
if (isExeption)
{
func2Test -= 0x80; // Get function from exeption code
ret += "Exception ";
}
ret += string.Format("Func. {0} / {1} hex", func2Test, func2Test.ToString("x"));
switch (func2Test)
{
case (int)FunctionNumber.Read_No3:
case (int)FunctionNumber.Read_No4:
ret += " is Read";
break;
case (int)FunctionNumber.Write_No15:
case (int)FunctionNumber.Write_No16:
if (IsDeviceResponse)
{
ret += " Incorrect write replay from slave!!!!";
}
else
{
ret += " is Write";
}
break;
default: ret += " Unknown func. type!"; break;
}
}
catch { ret += string.Format(" Unknown func. type!"); }
ret += Environment.NewLine;
if (isExeption)
{
var exeptioncode = (int)input[(int)BaseOffset.FuncCode + 1];
ret += string.Format("Exception code {0} / {1} hex", exeptioncode, exeptioncode.ToString("x"));
}
else
{
ret += string.Format("Number of Bytes {0}" + Environment.NewLine, GetNumberOfDataBytes(input, IsDeviceResponse));
if (IsDeviceResponse)
{
byte[] data = null;
if (IsRead(input, IsDeviceResponse))
{
data = GetReadData(input, IsDeviceResponse);
}
if (data != null)
{
data = Base.ByteArrayExtensionClass.SwapByteInWord(data);
ret += string.Format("Data is = {0}", Base.NumberConvert.ToHex(data, true, false));
}
}
else
{
byte[] data = null;
ret += string.Format("Start Address {0}" + Environment.NewLine, GetStartAdr(input, IsDeviceResponse));
if (IsWrite(input, IsDeviceResponse))
{
data = GetWriteData(input, IsDeviceResponse);
}
if (data != null)
{
data = Base.ByteArrayExtensionClass.SwapByteInWord(data);
ret += string.Format("Data is = {0}\n", Base.NumberConvert.ToHex(data, true, false));
}
}
}
//No44, // or 68 as a Special myconnect IO module telegram for https://mjksvn.world.fluidtechnology.net:4443/svn/development/8440XX Connect and myConnect/myConnect/trunk/docs/IO modules communication.docx
}
else if ((input != null) && (input.Length >= (16 + 2)))
{ // Check if it is
var telegrams = input.SliceSameSize(0, (16 + 2));
foreach (var telegram in telegrams)
{
if (IsDataOkay(telegram, IsDeviceResponse))
{
ret += "¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤" + Environment.NewLine;
int offset = 0;
ret += "ID[" + telegram[offset++] + "]";
ret += " func[" + telegram[offset++] + "]";
int Quantity = telegram[offset++];
int[] Descriptors = new int[] { telegram[offset++], 0 };
{ // print out Status
ret += Environment.NewLine;
int Status = telegram[offset++];
switch (Status)
{
case 0x11: ret += "Both recognized"; break;
case 0x01: ret += "Lower OK, upper ERROR"; break;
case 0x10: ret += "Lower ERROR, upper OK"; break;
case 0x00: ret += "Both ERROR"; break;
default: ret += "Unknown status" + Status.ToHex(true); break;
}
}
{// Print out Descriptor
ret += Environment.NewLine;
Descriptors[1] = telegram[offset++];
foreach (var Descriptor in Descriptors)
{
ret += " Type[";
switch (Descriptor)
{
case 0: ret += "none"; break;
case 1: ret += "6DI"; break;
case 2: ret += "6DO"; break;
case 3: ret += "3AI"; break;
case 4: ret += "3AO"; break;
default: ret += "Unknown" + Descriptor.ToHex(true); break;
}
ret += "]";
}
}
{// Print out data
ret += Environment.NewLine + "Raw[" + telegram.Slice(offset, telegram.Length - offset).ToHex(true, false) + "]";
var u32Values = telegram.SliceSameSize(offset, 4);
foreach (var u32Value in u32Values)
{
ret += Environment.NewLine;
ret += " DI&DO[" + u32Value[0].ToBin(true) + "]/AI&AO[" + (new DataUnion()).PutByteArray(u32Value, DataUnion.DataByteLayoutType.SwapWords).F32Data + "]";
}
}
}
else
{
ret += string.Format("Message is {0} is wrong!" + Environment.NewLine, telegram.ToHex(true, false));
}
ret += Environment.NewLine;
}
}
else
{
ret += string.Format("Message is {0}" + Environment.NewLine, isOkay ? "okay" : "CRC is wrong!");
}
}
catch (Exception ex)
{
ret += "Error = " + ex.Message;
}
return ret;
}
/// <summary>
/// Added to IProtocolTranslateClass to use in Comli
/// </summary>
public byte[] CreateTxData(int slaveID, int rwFuncNo, int adr, int dataByteSize, byte[] writeData, bool IsDeviceResponse, ref int pageNumberNow)
{
throw new NotImplementedException();
}
#endregion
}
}
@@ -0,0 +1,11 @@
using System;
namespace XYLEM.Communication
{
//------------------------------------- Define ------------------------------------------------
public enum ProtocolType : int
{
ModbusRTU = 0,
None,
};
}
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XYLEM.Communication.ValueEncoders
{
static class ArrayManipulator
{
public static byte[] SwapPairWise(byte[] input)
{
byte[] swapped = new byte[input.Length];
for (int i = 0; i < input.Length; i = i+2)
{
swapped[i + 1] = input[i];
swapped[i] = input[i + 1];
}
return swapped;
}
}
}
@@ -0,0 +1,952 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XYLEM.Communication;
using System.Xml;
using System.Xml.Linq;
using XYLEM.Base;
using XYLEM.Base.Files;
using XYLEM.Device.Value;
using System.Numerics;
using XYLEM.Communication.ValueEncoders;
using XYLEM.Base.XML;
namespace XYLEM.Communication.ValueEncoders
{
/// <summary>
/// Return used character set used for email or empty if not Loaded from setup
/// </summary>
/// <returns>ex. "iso-8859-1"</returns>
public delegate string GetEmailCharacterSetToUse();
public static class DeviceValueEncoder
{
public static object Default(this ValueDataType dataType)
{
try
{
switch (dataType)
{
case ValueDataType.U8:
case ValueDataType.B8: return (byte)0;
case ValueDataType.S8: return (sbyte)0;
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
return (UInt16)0;
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC: return ((UInt32)0).Convert1970SecToTime(TimeType.UTC);
case ValueDataType.U32TIME_Y2000: return ((UInt32)0).Convert2000SecToTime();
case ValueDataType.U32MJK_SN: return ((UInt32)0);
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return ((UInt32)0);
//case DeviceValueDataType.U24:
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
case ValueDataType.B32:
case ValueDataType.U32: return (UInt32)0;
case ValueDataType.B64:
case ValueDataType.U64: return (UInt64)0;
case ValueDataType.F64: return (double)0;
case ValueDataType.U128: return (BigInteger)0;
case ValueDataType.S16: return (Int16)0;
case ValueDataType.F32: return (Single)0;
//case DeviceValueDataType.U32IPV4: return "0.0.0.0"; // handled as a string
default:
if (dataType.IsText())
{ // Do this as the last check to save CPU power
return "";
}
throw new Exception(dataType.ToString() + "has no default value)");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Default()", "dataType = " + dataType.ToString()));
}
}
public static string EncodeXML(this object value, ValueDataType type)
{
try
{
string valueAsTxt = value.ToString();
switch (type)
{
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC:
if (value is DateTime)
{
var value32bit = ((DateTime)value).ConvertTimeTo1970Sec(TimeType.Local);
return XmlConvert.ToString(value32bit);
}
return XmlConvert.ToString((Double)value);
case ValueDataType.U32TIME_Y2000:
if (value is DateTime)
{
var value32bit = ((DateTime)value).ConvertTimeTo2000Sec(TimeType.Local);
return XmlConvert.ToString(value32bit);
}
return XmlConvert.ToString((Double)value);
case ValueDataType.U8:
case ValueDataType.B8:
case ValueDataType.S8:
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS:
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U24:
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.B64:
case ValueDataType.U64:
case ValueDataType.S16:
case ValueDataType.S32:
case ValueDataType.S64:
case ValueDataType.F32:
case ValueDataType.F64:
case ValueDataType.U32MJK_SN:
{
if (typeof(Double) == value.GetType())
{
valueAsTxt = XmlConvert.ToString((Double)value);
}
else if (typeof(Single) == value.GetType())
{
valueAsTxt = XmlConvert.ToString((Single)value);
}
return valueAsTxt;
}
case ValueDataType.U128:
if (typeof(BigInteger) == value.GetType())
{
valueAsTxt = ((BigInteger)value).ToString("X"); // enclode as hex
}
else
{
throw new Exception($"{value.GetType()} is not supported for U128 xml convert");
}
return valueAsTxt;
//case DeviceValueDataType.U32IPV4: return valueAsTxt.Trim( ).StripIllegalXMLChars( );// handled as a string
default:
if (type.IsText())
{ // Do this as the last check to save CPU power
return valueAsTxt.Trim().StripIllegalXMLChars();
}
throw new NotImplementedException("DataType '" + type + "' not recognized.");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "EncodeXML()", "dataType = " + type.ToString() + " Value is = " + value.ToString()));
}
}
public static Object DecodeXML(this string valueInXml, ValueDataType type)
{
try
{
switch (type)
{
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC:
return XmlConvert.ToUInt32(valueInXml).Convert1970SecToTime(TimeType.Local);
case ValueDataType.U32TIME_Y2000:
return XmlConvert.ToUInt32(valueInXml).Convert2000SecToTime();
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: return XmlConvert.ToUInt32( valueInXml );
case ValueDataType.B8:
case ValueDataType.U8:
return XmlConvert.ToByte(valueInXml);
case ValueDataType.S8:
return XmlConvert.ToSByte(valueInXml);
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
return XmlConvert.ToUInt16(valueInXml);
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS:
//case DeviceValueDataType.U24:
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
return XmlConvert.ToUInt32(valueInXml);
case ValueDataType.B64:
case ValueDataType.U64: return XmlConvert.ToUInt64(valueInXml);
case ValueDataType.S16: return XmlConvert.ToInt16(valueInXml);
case ValueDataType.S32: return XmlConvert.ToInt32(valueInXml);
case ValueDataType.S64: return XmlConvert.ToInt64(valueInXml);
case ValueDataType.F32: return XmlConvert.ToSingle(valueInXml);
case ValueDataType.F64: return XmlConvert.ToDouble(valueInXml);
case ValueDataType.U128: return BigInteger.Parse(valueInXml, System.Globalization.NumberStyles.HexNumber);
//case DeviceValueDataType.U32IPV4: return valueInXml.ReinsetIllegalXMLChars( );// handled as a string
default:
if (type.IsText())
{ // Do this as the last check to save CPU power
return valueInXml.ReinsetIllegalXMLChars();
}
throw new NotImplementedException("DataType '" + type + "' not recognized.");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "DecodeXML()", "dataType = " + type.ToString() + " Value is = " + valueInXml));
}
}
/// <summary>
/// do layout changes on byte stream
/// </summary>
/// <param name="bytes"></param>
/// <param name="layout"></param>
/// <returns></returns>
static byte[] DoLayout(this byte[] bytes, LayoutType layout = LayoutType.Normal)
{
try
{
switch (layout)
{
case LayoutType.Normal: return bytes; ; // Do nothing
case LayoutType.SwapAll: return bytes.Reverse();
default:
throw new NotSupportedException(layout + " is not supported");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "DoLayout", "layout = " + layout));
}
}
/// <summary>
/// Encode data with normal data layout
/// </summary>
/// <param name="value"></param>
/// <param name="dataType"></param>
/// <param name="EmailCharacterSet">Null if not used</param>
/// <returns></returns>
public static byte[] Encode(this object value, ValueDataType dataType, GetEmailCharacterSetToUse emailCharacterSet = null)
{
try
{
if (value == null)
{
throw new Exception("Value is null");
}
switch (dataType)
{
case ValueDataType.B8:
case ValueDataType.U8:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(byte));// Try set type if not the correct one
return BitConverter.GetBytes((byte)value);
}
case ValueDataType.S8:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(sbyte));// Try set type if not the correct one
return BitConverter.GetBytes((sbyte)value);
}
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
return BitConverter.GetBytes((UInt16)value);
case ValueDataType.U32TIME_Y1970:
if (value is DateTime)
{
return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo1970Sec(TimeType.Local));
}
return BitConverter.GetBytes((UInt32)value); // Work around on olde types
case ValueDataType.U32TIME_Y1970_UTC:
if (value is DateTime)
{
return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo1970Sec(TimeType.UTC));
}
return BitConverter.GetBytes((UInt32)value); // Work around on olde types
case ValueDataType.U32TIME_Y2000:
if (value is DateTime)
{
return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo2000Sec(TimeType.Local));
}
return BitConverter.GetBytes((UInt32)value);
// Work around on olde types
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
// return BitConverter.GetBytes( TimeConvertClass.ToMidnightSecOffsetUTC( (UInt32)value ) );
//case DeviceValueDataType.U24DateHH_MM_SS: {
// var timeSpan = TimeConvertClass.ConvertTimeSpan( (UInt32)value );
// return new byte[] { (byte)timeSpan.Seconds, (byte)timeSpan.Minutes, (byte)timeSpan.Hours };
// }
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: {
// var date = ((UInt32)value).Convert1970SecToTime( TimeType.Local );
// return new byte[] {
// (byte)date.Second,
// (byte)date.Minute,
// (byte)date.Hour,
// (byte)date.Day,
// (byte)date.Month,
// (byte)(date.Year - 2000)
// };
// }
//case DeviceValueDataType.U24: {
// value = CorrectTypeIfNotTheSame( value, dataType, typeof( UInt32 ) );// Try set type if not the correct one
// return BitConverter.GetBytes( (UInt32)value ).Remove( 3 );
// }
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(UInt32));// Try set type if not the correct one
return BitConverter.GetBytes((UInt32)value);
}
case ValueDataType.B64:
case ValueDataType.U64:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(UInt64));// Try set type if not the correct one
return BitConverter.GetBytes((UInt64)value);
}
case ValueDataType.S16:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(Int16));// Try set type if not the correct one
return BitConverter.GetBytes((Int16)value);
}
case ValueDataType.S32:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(Int32));// Try set type if not the correct one
return BitConverter.GetBytes((Int32)value);
}
case ValueDataType.F32:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(Single));// Try set type if not the correct one
return BitConverter.GetBytes((Single)value);
}
case ValueDataType.F64:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(double));// Try set type if not the correct one
return BitConverter.GetBytes((double)value);
}
case ValueDataType.U128:
{
value = CorrectTypeIfNotTheSame(value, dataType, typeof(BigInteger));// Try set type if not the correct one
return ((BigInteger)value).ToByteArray(); // TODO: Is this okay or need always to be the 16 byte in size?
}
//case DeviceValueDataType.U32IPV4: return U32_IP_Encoder.Encode( value.ToString( ) );
default:
if (dataType.IsText())
{ // Do this as the last check to save CPU power
var typeAsText = dataType.ToString();
// is Email
if (dataType.IsEmailText())
{
return StringEncoderEmail.Encode(value.ToString(), Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet()));
}
// is SMS
if (dataType.IsSMSText())
{
return StringEncoderUnicode.Encode(value.ToString(), Length(dataType));
}
// is Windows 1252
if (dataType.IsWindows1252Text())
{
return StringEncoder_W1252.Encode(value.ToString(), Length(dataType));
}
// is Windows 1252, but needs to have "<>" in frond and end
// Ex. end result is "<tmo@xyleminc.com>,<tmo@mjk.dk>" or "<tmo@xyleminc.com>"
if (dataType.IsWindows1252TextRecipient())
{
var valueAsText = value.ToString().Trim();
if (!String.IsNullOrEmpty(valueAsText))
{
// Remove manual added brackets or " if user has done it in the past
if (valueAsText.Contains("\""))
{
valueAsText = valueAsText.Replace("\"", "");
}
//// work arround if user has already used "," as separation
//if (valueAsText.Contains( "," )) {
// valueAsText = valueAsText.Replace( ",", ">,<" ); //old modem firmware V1.003 and TDC NO
//}
// Replace ";" with correct "," as separation and add bracked ">" "<" to support RCF821
if (valueAsText.Contains(";"))
{
//valueAsText = valueAsText.Replace( ";", ">,<" ); old modem firmware V1.003 and TDC NO
valueAsText = valueAsText.Replace(";", ",");//new modem firmware V1.3 using mail.mjk-link.dk
}
// Trim
valueAsText = valueAsText.Trim();
// Add brackets "<>" around address / addresses and end with " to tell modem where it starts and end in MC55I at command
//Ex. end result is "<tmo@xyleminc.com>,<tmo@mjk.dk>" or "<tmo@xyleminc.com>"
if (!String.IsNullOrEmpty(valueAsText))
{
//valueAsText = "\"<" + valueAsText + "\">"; old modem firmware V1.003 and TDC NO
valueAsText = "\"" + valueAsText + "\""; //new modem firmware V1.3 using mail.mjk-link.dk
}
}
return StringEncoder_W1252.Encode(valueAsText, Length(dataType));
}
// is Quoted Printable Text
if (dataType.IsEmailQuotedPrintableText())
{
return StringEncoderEmail_Q_Types.Encode(value.ToString(), Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet()));
}
// Is is normal utf8
return StringEncoder.Encode(value.ToString(), Length(dataType));
}
throw new NotImplementedException("DataType '" + dataType + "' not recognized.");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString()));
}
}
private static object CorrectTypeIfNotTheSame(object value, ValueDataType correctTypeTag, Type typeUsedForCast)
{
try
{
if (value.GetType() == typeUsedForCast)
{
return value; // Nothing to change
}
{
AppConst.Logger.AddFuncLog(
#if DEBUG //
true // log as error
#else
false // Log silent in log
#endif //#if DEBUG
, typeof(DeviceValueEncoder).ToString(), "CorrectTypeIfNotTheSame()",
"Warning! correction was needed. Is this a older setting else not okay? " + MakeCorrectTypeValueInfoText(value, correctTypeTag, typeUsedForCast)
);
}
return ToValue(value.ToString(), correctTypeTag);
}
catch (Exception ex)
{
var valueInfo = MakeCorrectTypeValueInfoText(value, correctTypeTag, typeUsedForCast);
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "CorrectTypeIfNotTheSame", valueInfo));
}
}
/// <summary>
/// Generate the value info possible to get for a value to convert
/// </summary>
/// <param name="value">Value to correct</param>
/// <param name="correctTypeTag">correct value type tag</param>
/// <param name="typeUsedForCast">type used for cast</param>
/// <returns>Text to show in log</returns>
private static string MakeCorrectTypeValueInfoText(object value, ValueDataType correctTypeTag, Type typeUsedForCast)
{
var ValueInfo = "";
try
{
if (ValueInfo == null)
{
ValueInfo += " Value= IS NULL and not possible to correct!";
}
else
{
ValueInfo += " Value=\"" + value.ToString() + "\"";
ValueInfo += " From Type=\"" + value.GetType() + "\"";
}
ValueInfo += " To Type=\"" + correctTypeTag.ToString() + "\"";
}
catch { ValueInfo += " [Fail to get info ?] "; }
return ValueInfo;
}
/// <summary>
/// Encode data with data layout setting
/// </summary>
/// <param name="value"></param>
/// <param name="dataType"></param>
/// <param name="layout"></param>
/// <param name="emailCharacterSet">Null if not used</param>
/// <returns></returns>
public static byte[] Encode(this object value, ValueDataType dataType, LayoutType layout, GetEmailCharacterSetToUse emailCharacterSet = null)
{
try
{
var bytes = Encode(value, dataType, emailCharacterSet);
if (bytes == null)
{
return bytes;
}
return bytes.DoLayout(layout);
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString()));
}
}
/// <summary>
/// Decode data with normal data layout
/// </summary>
/// <param name="value"></param>
/// <param name="dataType"></param>
/// <param name="emailCharacterSet">Null if not used</param>
/// <returns></returns>
public static object Decode(this byte[] value, ValueDataType dataType, GetEmailCharacterSetToUse emailCharacterSet = null)
{
try
{
if (value == null)
{
throw new Exception("Value is null");
}
if (value.Count() == 0)
{
throw new Exception("Value Has no values in array");
}
switch (dataType)
{
case ValueDataType.B8:
case ValueDataType.U8:
return (byte)value.First();
case ValueDataType.S8:
return (sbyte)value.First();
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
return BitConverter.ToUInt16(value, 0);
case ValueDataType.U32TIME_Y1970:
return BitConverter.ToUInt32(value, 0).Convert1970SecToTime(TimeType.Local);
case ValueDataType.U32TIME_Y1970_UTC:
return BitConverter.ToUInt32(value, 0).Convert1970SecToTime(TimeType.UTC).ToLocalTime();
case ValueDataType.U32TIME_Y2000:
return BitConverter.ToUInt32(value, 0).Convert2000SecToTime();
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
// return TimeConvertClass.FromMidnightSecOffsetUTC( BitConverter.ToUInt32( value, 0 ) );
//case DeviceValueDataType.U24DateHH_MM_SS: {
// return (UInt32)((UInt32)value[ 2 ] * 3600) + ((UInt32)value[ 1 ] * 60 + (UInt32)value[ 0 ]);
// }
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: {
// var date = new DateTime( (int)value[ 5 ] + 2000, value[ 4 ], value[ 3 ], value[ 2 ], value[ 1 ], value[ 0 ] );
// return date.ConvertTimeTo1970Sec( TimeType.Local );
// }
//case DeviceValueDataType.U24: {
// var as32bitValue = new byte[] { value[ 0 ], value[ 1 ], value[ 2 ], 0 };
// return BitConverter.ToUInt32( as32bitValue, 0 );
// }
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
return BitConverter.ToUInt32(value, 0);
case ValueDataType.B64:
case ValueDataType.U64: return BitConverter.ToUInt64(value, 0);
case ValueDataType.S16: return BitConverter.ToInt16(value, 0);
case ValueDataType.S32: return BitConverter.ToInt32(value, 0);
case ValueDataType.F32: return BitConverter.ToSingle(value, 0);
case ValueDataType.F64: return BitConverter.ToDouble(value, 0);
case ValueDataType.U128:
{
// Need a zero in msb to avoid value is handled as signed
var valueConverted = new BigInteger((value).Concat(new byte[1]).ToArray());
return valueConverted;
}
case ValueDataType.Array6B:
case ValueDataType.Array10B:
case ValueDataType.Array12B:
case ValueDataType.Array64B:
case ValueDataType.Array128B:
case ValueDataType.Array136B:
case ValueDataType.Array250B: return value;
//case DeviceValueDataType.U32IPV4: return U32_IP_Encoder.Decode( value );
default:
if (dataType.IsText())
{ // Do this as the last check to save CPU power
var typeAsText = dataType.ToString();
if (dataType.IsEmailText())
{ // is Email
return StringEncoderEmail.Decode(value, Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet()));
}
if (dataType.IsSMSText())
{ // is SMS
return StringEncoderUnicode.Decode(value, Length(dataType));
}
if (dataType.IsWindows1252Text())
{ // is Windows 1252
return StringEncoder_W1252.Decode(value, Length(dataType));
}
if (dataType.IsWindows1252TextRecipient())
{ // is Windows 1252, but needs to have "<>" in frond and end
var valueAsText = StringEncoder_W1252.Decode(value, Length(dataType));
if (!String.IsNullOrEmpty(valueAsText))
{
// Remove added brackets or " nessesarry that is only to be
// Ex. end result is "<tmo@xyleminc.com>,<tmo@mjk.dk>" or "<tmo@xyleminc.com>"
if (valueAsText.Contains("\""))
{
valueAsText = valueAsText.Replace("\"", "");
}
if (valueAsText.Contains("<"))
{
valueAsText = valueAsText.Replace("<", "");
}
if (valueAsText.Contains(">"))
{
valueAsText = valueAsText.Replace(">", "");
}
// Replace email seperation and replace it with correct the standard ";"
if (valueAsText.Contains(","))
{
valueAsText = valueAsText.Replace(",", ";");
}
}
return valueAsText;
}
if (dataType.IsEmailQuotedPrintableText())
{
return StringEncoderEmail_Q_Types.Decode(value, Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet()));
}
// Is allowed to have a variable length on a string / text
var maxLng = dataType.Length();
if (value.Length > maxLng)
{
throw new Exception(String.Format("Size of text is {0} and more than max {1}", value.Length, maxLng));
}
// Is is normal utf8
return StringEncoder.Decode(value, value.Length);
}
throw new NotImplementedException("DataType '" + dataType + "' not recognized.");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Decode", "dataType = " + dataType.ToString()));
}
}
/// <summary>
/// Decode data with data layout setting
/// </summary>
/// <param name="value"></param>
/// <param name="dataType"></param>
/// <param name="emailCharacterSet">Null if not used</param>
/// <param name="layout"></param>
/// <returns></returns>
public static object Decode(this byte[] value, ValueDataType dataType, LayoutType layout, GetEmailCharacterSetToUse emailCharacterSet = null)
{
try
{
var bytes = value.DoLayout(layout);
return Decode(value, dataType, emailCharacterSet);
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString()));
}
}
/// <summary>
/// Convert a local defined string value to the correct value object according to dataType ("DeviceValueType")
/// </summary>
/// <param name="value">Value as string (floating point must use local setting for "," or ".") and DateTime as local time </param>
/// <param name="dataType"></param>
/// <returns></returns>
public static object ToValue(this string value, ValueDataType dataType)
{
try
{
if (value == null)
{
throw new Exception("Value is null");
}
switch (dataType)
{
case ValueDataType.B8:
case ValueDataType.U8:
return (byte)Convert.ToUInt16(value);
case ValueDataType.S8:
return (sbyte)Convert.ToInt16(value);
case ValueDataType.B16:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
return Convert.ToUInt16(value);
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC:
case ValueDataType.U32TIME_Y2000:
// Always expect this as local time
return new DateTime(Convert.ToDateTime(value).Ticks, DateTimeKind.Local);
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U24:
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
return Convert.ToUInt32(value);
case ValueDataType.B64:
case ValueDataType.U64: return Convert.ToUInt64(value);
case ValueDataType.S16: return Convert.ToInt16(value);
case ValueDataType.S32: return Convert.ToInt32(value);
case ValueDataType.F32: return Convert.ToSingle(value);
case ValueDataType.F64: return Convert.ToDouble(value);
case ValueDataType.U128:
// Need a zero in msb to avoid value is handled as signed
return BigInteger.Parse("0"+value, System.Globalization.NumberStyles.HexNumber);
//case DeviceValueDataType.U32IPV4: {
// if (dataType.IsText( )) {
// return value.ToString( );
// }
// throw new NotImplementedException( "DataType '" + dataType + "' not recognized." );
// }
default:
if (dataType.IsText())
{ // Do this as the last check to save CPU power
var typeAsText = dataType.ToString();
if (dataType.IsEmailText())
{ // is Email
return value;
}
if (dataType.IsSMSText())
{ // is SMS
return value;
}
if (dataType.IsWindows1252Text())
{ // is Windows 1252
return value;
}
if (dataType.IsWindows1252TextRecipient())
{ // is Windows 1252, but needs to have "<>" in frond and end
return value;
}
if (dataType.IsEmailQuotedPrintableText())
{ // is Special Email Quoted Printable
return value;
}
// Is is normal utf8
return value; //TODO: No converting is done. may have to be converted to utf8?
}
throw new NotImplementedException("DataType '" + dataType + "' not recognized.");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "ToValue()", "dataType = " + dataType.ToString()));
}
}
/// <summary>
/// Return data Byte Length (1x8bit)
/// </summary>
/// <returns></returns>
public static int Length(this ValueDataType DataType)
{
try
{
switch (DataType)
{
case ValueDataType._Empty: return 0;
#region ---- 8 Bit ----
case ValueDataType.Bool:
case ValueDataType.B8:
case ValueDataType.S8:
case ValueDataType.U8: return 1;
#endregion // #region ---- 8 Bit ----
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U24: return 3;
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return 6;
default:
return WLength(DataType) << 1;
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Length"));
}
}
/// <summary>
/// Return data Word Length (2x8bit)
/// </summary>
/// <returns></returns>
public static int WLength(this ValueDataType DataType)
{
try
{
switch (DataType)
{
case ValueDataType._Empty: return 0;
#region ---- 8 / 16 Bit ----
case ValueDataType.Bool:
case ValueDataType.B8:
case ValueDataType.S8:
case ValueDataType.U8:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
case ValueDataType.B16:
case ValueDataType.S16:
case ValueDataType.U16TEXTID:
case ValueDataType.U16UNIT:
case ValueDataType.U16UNITGROUP: return 1;
#endregion
//case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return 3;
//case DeviceValueDataType.U24DateHH_MM_SS:
//case DeviceValueDataType.U24: return 2;
#region ---- 32 Bit ----
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
case ValueDataType.S32:
case ValueDataType.F32:
//case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC:
case ValueDataType.U32TIME_Y2000:
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC:
//case DeviceValueDataType.U32IPV4:
return 2;
#endregion
#region ---- 12 x 8 Bit Time Types ----
case ValueDataType.TIME_ASCII_12B:
case ValueDataType.TIME_ymdhms:
return 6;
#endregion
#region ---- 64 Bit ----
case ValueDataType.B64:
case ValueDataType.U64:
case ValueDataType.S64:
case ValueDataType.F64:
return 4;
#endregion
#region ---- 128 Bit ----
case ValueDataType.U128:
return 8;
#endregion
#region ---- Bit Arrays ----
case ValueDataType.Array6B: return (6 / 2);
case ValueDataType.Array10B: return (10 / 2);
case ValueDataType.Array12B: return (12 / 2);
case ValueDataType.Array64B: return (64 / 2);
case ValueDataType.Array128B: return (128 / 2);
case ValueDataType.Array136B: return (136 / 2);
case ValueDataType.Array250B: return (250 / 2);
#endregion
#region ---- Strings / Text ----
//6bytes
case ValueDataType.STR6E:
case ValueDataType.STR6S:
//case DeviceValueDataType.STR6Q:
//case DeviceValueDataType.STR6W1252:
case ValueDataType.STR6: return 3;
//8bytes
case ValueDataType.STR8E:
case ValueDataType.STR8S:
//case DeviceValueDataType.STR8Q:
//case DeviceValueDataType.STR8W1252:
case ValueDataType.STR8: return 4;
//10bytes
case ValueDataType.STR10E:
case ValueDataType.STR10S:
//case DeviceValueDataType.STR10Q:
//case DeviceValueDataType.STR10W1252:
case ValueDataType.STR10: return 5;
//16bytes
case ValueDataType.STR16E:
case ValueDataType.STR16S:
//case DeviceValueDataType.STR16Q:
//case DeviceValueDataType.STR16W1252:
case ValueDataType.STR16: return 8;
//18bytes
case ValueDataType.STR18E:
case ValueDataType.STR18S:
//case DeviceValueDataType.STR18Q:
//case DeviceValueDataType.STR18W1252:
case ValueDataType.STR18: return 9;
//20bytes
case ValueDataType.STR20E:
case ValueDataType.STR20S:
//case DeviceValueDataType.STR20Q:
//case DeviceValueDataType.STR20W1252:
case ValueDataType.STR20: return 10;
//22bytes
case ValueDataType.STR22E:
case ValueDataType.STR22S:
//case DeviceValueDataType.STR22Q:
//case DeviceValueDataType.STR22W1252:
case ValueDataType.STR22: return 11;
//30bytes
case ValueDataType.STR30E:
case ValueDataType.STR30S:
//case DeviceValueDataType.STR30Q:
//case DeviceValueDataType.STR30W1252:
case ValueDataType.STR30: return 15;
//32bytes
case ValueDataType.STR32E:
case ValueDataType.STR32S:
//case DeviceValueDataType.STR32Q:
//case DeviceValueDataType.STR32W1252:
case ValueDataType.STR32: return 16;
//64bytes
case ValueDataType.STR64E:
case ValueDataType.STR64S:
//case DeviceValueDataType.STR64Q:
//case DeviceValueDataType.STR64W1252:
case ValueDataType.STR64: return 32;
//100bytes
case ValueDataType.STR100E:
case ValueDataType.STR100S:
//case DeviceValueDataType.STR100Q:
//case DeviceValueDataType.STR100W1252:
case ValueDataType.STR100: return 50;
//128bytes
case ValueDataType.STR128E:
case ValueDataType.STR128S:
//case DeviceValueDataType.STR128Q:
//case DeviceValueDataType.STR128W1252:
//case DeviceValueDataType.STR128W1252rec:
case ValueDataType.STR128: return 64;
//160bytes
//case DeviceValueDataType.STR160E:
//case DeviceValueDataType.STR160S:
//case DeviceValueDataType.STR160Q:
//case DeviceValueDataType.STR160W1252:
//case DeviceValueDataType.STR160: return 80;
//240bytes
case ValueDataType.STR240E:
case ValueDataType.STR240S:
//case DeviceValueDataType.STR240Q:
//case DeviceValueDataType.STR240W1252:
case ValueDataType.STR240: return 240;
#endregion
default:
throw (new Exception("No known length for tag = " + DataType.ToString()));
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "WLength"));
}
}
/// <summary>
/// Return the text length for value type if it is a text
/// </summary>
/// <returns></returns>
public static int StringLength(this ValueDataType DataType)
{
try
{
switch (DataType)
{
//case DeviceValueDataType.U32IPV4: return (4 * 3 + 3);
default:
if (DataType.IsSMSText())
{ // is SMS
return DataType.Length() / 2; // is always 16bit
}
return Length(DataType);
}
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "StringLength"));
}
}
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Communication.ValueEncoders {
public enum LayoutType {
Normal,
SwapAll,
}
}
@@ -0,0 +1,92 @@
using System;
using System.Text;
using XYLEM.Communication;
namespace XYLEM.Communication.ValueEncoders {
public static class StringEncoder {
public static Encoding GetDefaultEncoding( ) {
try {
return Encoding.GetEncoding( "Windows-1252"/*Strings._CONFIG_STD_String_DefaultCharacterEncoding*/ );
} catch (Exception ex) {
throw new Exception( typeof( StringEncoder ).ToString( )+ "\n\rGetDefaultEncoding"+ "\n\rError when making default encoding with = "+ "\n\rWindows-1252"/*Strings._CONFIG_STD_String_DefaultCharacterEncoding*/, ex );
}
//Legacy code return Encoding.GetEncoding( 1252 );
}
/// <summary>
/// Standard Windows iso-8859-1-encoding page.
/// </summary>
static Encoding s_Encoder = GetDefaultEncoding( ); // Default Fallback
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght, string CharacterSet) {
if (value.Length > lenght) {
throw new ArgumentException( "value.Length is too long", "value" );
}
var result = new byte[ lenght ];
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
Encoding.GetEncoding( CharacterSet ).GetBytes( value ).CopyTo( result, 0 );
return result;
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoder ).ToString( )+ "\n\rEncode"+ "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/ + Environment.NewLine + ex.Message );
}
// Use defalt
s_Encoder.GetBytes( value ).CopyTo( result, 0 );
return result;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght) { return Encode( value, lenght, null ); }
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght, string CharacterSet) {
if (value.Length != lenght) {
throw new ArgumentException( "value.Length wrong lenght", "value" );
}
string result = null;
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
result = Encoding.GetEncoding( CharacterSet ).GetString( value );
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoder ).ToString( )+ "\n\rDecode()"+ "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/ + Environment.NewLine + ex.Message );
}
// Use defalt
if (result == null) {
result = s_Encoder.GetString( value );
}
var index = result.IndexOf( '\0' );
if (index >= 0)
return result.Substring( 0, result.IndexOf( '\0' ) );
else
return result;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght) { return Decode( value, lenght, null ); }
}
}
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XYLEM.Communication.ValueEncoders {
public static class StringEncoderEmail {
public static Encoding GetDefaultEncoding( ) {
try {
return Encoding.GetEncoding( "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/ );
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString( )+ "\n\rGetDefaultEncoding"+ "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/, ex );
}
// Legacy code return Encoding.GetEncoding( "iso-8859-1" );
}
/// <summary>
/// Standard Windows iso-8859-1-encoding page.
/// </summary>
static Encoding s_Encoder = GetDefaultEncoding( ); // Default Fallback
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght, string CharacterSet) {
if (value.Length > lenght) {
throw new ArgumentException( "value.Length is too long", "value" );
}
var result = new byte[ lenght ];
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
Encoding.GetEncoding( CharacterSet ).GetBytes( value ).CopyTo( result, 0 );
return result;
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString( )+ "\n\rEncode()"+ "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/,ex );
}
// Use defalt
s_Encoder.GetBytes( value ).CopyTo( result, 0 );
return result;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght) { return Encode( value, lenght, null ); }
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght, string CharacterSet) {
if (value.Length != lenght) {
throw new ArgumentException( "value.Length wrong lenght", "value" );
}
string result = null;
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
result = Encoding.GetEncoding( CharacterSet ).GetString( value );
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString()+ "\n\rDecode()"+ "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/, ex );
}
// Use defalt
if (result == null) {
result = s_Encoder.GetString( value );
}
var index = result.IndexOf( '\0' );
if (index >= 0) {
return result.Substring( 0, result.IndexOf( '\0' ) );
}
return result;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght) { return Decode( value, lenght, null ); }
}
}
@@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
namespace XYLEM.Communication.ValueEncoders {
public static class StringEncoderEmail_Q_Types {
static string DefaultEncoding = "iso-8859-1";
public static Encoding GetDefaultEncoding( ) {
try {
return Encoding.GetEncoding( "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/ );
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString( ) + "\n\rGetDefaultEncoding" + "\n\rError when making default encoding with = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/, ex );
}
// Legacy code return Encoding.GetEncoding( DefaultEncoding );
}
#region Converting to Quoted Printable
//http://stackoverflow.com/questions/11793734/code-for-encode-decode-quotedprintable
public static byte[] EncodeQ(byte[] value, int lenght) {
if (value.First( ) == 0) {
return value;
}
List<byte> ret = new List<byte>( );
foreach (byte v in value) {
// The following are not required to be encoded:
// - Tab (ASCII 9)
// - Space (ASCII 32)
// - Characters 33 to 126, except for the equal sign (61).
if ((v == 9) || ((v >= 32) && (v <= 60)) || ((v >= 62) && (v <= 126))) {
if (ret.Count + 1 > lenght) { // Check for length is not over max
break; // Stop converting
}
ret.Add( (byte)Convert.ToChar( v ) );
} else {
if (ret.Count + 3 > lenght) { // Check for length is not over max
break; // Stop converting
}
if (v == 0) {
ret.Add( 0 );
break; // Stop terminate string
}
ret.AddRange( Encoding.UTF8.GetBytes( "=" + v.ToString( "X2" ) ) );
}
}
char lastChar = (char)ret.Last( );
if (char.IsWhiteSpace( lastChar )) {
ret.RemoveAt( ret.Count( ) - 1 );
if (!(ret.Count + 3 > lenght)) { // Check for length is not over max
ret.AddRange( Encoding.UTF8.GetBytes( "=" + ((byte)lastChar).ToString( "X2" ) ) );
}
}
if (ret.Count < lenght) { // Make sure length is correct
ret.AddRange( new byte[ lenght - ret.Count ] );
}
return ret.ToArray( );
}
public static string DecodeQ(byte[] inputBytes, string charSet) {
var input = (new UTF8Encoding( )).GetString( inputBytes );
Encoding enc;
try {
enc = Encoding.GetEncoding( charSet );
} catch {
enc = new UTF8Encoding( );
}
var occurences = new Regex( @"(=[0-9A-Z]{2}){1,}", RegexOptions.Multiline );
var matches = occurences.Matches( input );
foreach (Match match in matches) {
try {
byte[] b = new byte[ match.Groups[ 0 ].Value.Length / 3 ];
for (int i = 0; i < match.Groups[ 0 ].Value.Length / 3; i++) {
b[ i ] = byte.Parse( match.Groups[ 0 ].Value.Substring( i * 3 + 1, 2 ), System.Globalization.NumberStyles.AllowHexSpecifier );
}
char[] hexChar = enc.GetChars( b );
input = input.Replace( match.Groups[ 0 ].Value, new String( hexChar ) );
} catch { ;}
}
input = input.Replace( "?=", "" ).Replace( "\r\n", "" );
return input;
}
#endregion
/// <summary>
/// Standard Windows iso-8859-1-encoding page.
/// </summary>
static Encoding s_Encoder = GetDefaultEncoding( ); // Default Fallback
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght, string CharacterSet) {
byte[] ret = null;
if (value.Length > lenght) {
throw new ArgumentException( "value.Length is too long", "value" );
}
var result = new byte[ lenght ];
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
Encoding.GetEncoding( CharacterSet ).GetBytes( value ).CopyTo( result, 0 );
ret = EncodeQ( result, lenght );
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString( )+ "\n\rEncode()" + "\n\rWith = " + "\n\riso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/, ex );
}
if (ret == null) {
// Use defalt
s_Encoder.GetBytes( value ).CopyTo( result, 0 );
ret = EncodeQ( result, lenght );
}
/*#warning "!!!!!!!!!!!!!!!!! Testing !!!!!!!!!!!!!!!!!!!!!!!"
string test = new UTF8Encoding( ).GetString( ret );*/
return ret;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static byte[] Encode(string value, int lenght) { return Encode( value, lenght, null ); }
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <param name="CharacterSet">ex. "iso-8859-1"</param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght, string CharacterSet) {
if (value.Length != lenght) {
throw new ArgumentException( "value.Length wrong lenght", "value" );
}
/*#warning "!!!!!!!!!!!!!!!!! Testing !!!!!!!!!!!!!!!!!!!!!!!"
string test = new UTF8Encoding( ).GetString( value );*/
string result = null;
try {
if (!String.IsNullOrEmpty( CharacterSet )) {
result = DecodeQ( value, CharacterSet );
}
} catch (Exception ex) {
throw new Exception( typeof( StringEncoderEmail ).ToString() + "\n\rDecode()" + "\n\rWith = " + "iso-8859-1"/*Strings._CONFIG_STD_Email_DefaultCharacterEncoding*/, ex );
}
// Use defalt
if (result == null) {
result = DecodeQ( value, DefaultEncoding );
}
var index = result.IndexOf( '\0' );
if (index >= 0) {
return result.Substring( 0, result.IndexOf( '\0' ) );
}
return result;
}
/// <summary>
/// Use default characterSet
/// </summary>
/// <param name="value"></param>
/// <param name="lenght"></param>
/// <returns></returns>
public static string Decode(byte[] value, int lenght) { return Decode( value, lenght, null ); }
}
}
@@ -0,0 +1,41 @@
using System;
using System.Text;
using XYLEM.Communication;
namespace XYLEM.Communication.ValueEncoders
{
public static class StringEncoderUnicode
{
/// <summary>
/// Standard Windows 1252-encoding page.
/// </summary>
static Encoding s_Unicode = Encoding.BigEndianUnicode;
public static byte[] Encode(string value, int lenght)
{
if (value.Length > lenght)
{
throw new ArgumentException("value.Length is too long", "value");
}
var result = new byte[lenght];
s_Unicode.GetBytes(value).CopyTo(result, 0);
return result;
}
public static string Decode(byte[] value, int lenght)
{
if (value.Length > lenght)
{
throw new ArgumentException("value.Length wrong lenght", "value");
}
var result = s_Unicode.GetString(value);
var index = result.IndexOf('\0');
if (index >= 0)
return result.Substring(0, result.IndexOf('\0'));
else
return result;
}
}
}
@@ -0,0 +1,39 @@
using System;
using System.Text;
using XYLEM.Communication;
namespace XYLEM.Communication.ValueEncoders {
public static class StringEncoder_W1252 {
public static Encoding GetDefaultEncoding( ) {
return Encoding.GetEncoding( 1252 );
}
/// <summary>
/// Standard Windows 1252-encoding page.
/// </summary>
static Encoding s_Win1252 = GetDefaultEncoding( );
public static byte[] Encode(string value, int lenght) {
if (value.Length > lenght) {
throw new ArgumentException( "value.Length is too long", "value" );
}
var result = new byte[ lenght ];
s_Win1252.GetBytes( value ).CopyTo( result, 0 );
return result;
}
public static string Decode(byte[] value, int lenght) {
if (value.Length > lenght) {
throw new ArgumentException( "value.Length wrong lenght", "value" );
}
var result = s_Win1252.GetString( value );
var index = result.IndexOf( '\0' );
if (index >= 0)
return result.Substring( 0, result.IndexOf( '\0' ) );
else
return result;
}
}
}
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYLEM.Base;
namespace XYLEM.Communication.ValueEncoders {
/// <summary>
/// IP Address encoder when it has to be converted to a u32 value
/// </summary>
internal static class U32_IP_Encoder {
/// <summary>
/// Check if string is okay and possible to encode
/// </summary>
/// <param name="stringForCheck"></param>
/// <returns></returns>
internal static bool IsOkay(string stringForCheck) {
try {
if (string.IsNullOrEmpty( stringForCheck )) {
return false; // if string empty, then this is off and there is nothing to check
}
try {
var test = Encode( stringForCheck );
} catch {
return false; // Error is not possible to convert
}
return true; // Okay to convert
} catch (Exception ex) {
throw new Exception( ex.ToFuncErrorText( typeof( U32_IP_Encoder ).ToString( ), "IsOkay" ) );
}
}
/// <summary>
/// Encode xxx.xxx.xxx.xxx to bytes
/// </summary>
/// <param name="ip_XXX_XXX_XXX_XXX"></param>
/// <returns></returns>
static internal byte[] Encode(string ip_XXX_XXX_XXX_XXX) {
try {
var splited = ip_XXX_XXX_XXX_XXX.Split( '.' );
if (splited.Count( ) != 4) {
throw new Exception( "IP must be formated xxx.xxx.xxx.xxx but is " + ip_XXX_XXX_XXX_XXX.ToString( ) );
}
var values = splited.Select( value => byte.Parse( value ) );
return values.ToArray( );
} catch (Exception ex) {
throw new Exception( ex.ToFuncErrorText( typeof( U32_IP_Encoder ).ToString( ), "Encode" ) );
}
}
/// <summary>
/// decode bytes
/// </summary>
/// <param name="data"></param>
/// <returns>xxx.xxx.xxx.xxx</returns>
static internal string Decode(byte[] data) {
try {
if ((data == null) || (data.Count( ) != 4)) {
throw new Exception( "Must be 4 bytes" );
}
return String.Format( "{0}.{1}.{2}.{3}", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
} catch (Exception ex) {
throw new Exception( ex.ToFuncErrorText( typeof( U32_IP_Encoder ).ToString( ), "Decode" ) );
}
}
}
}
@@ -0,0 +1,120 @@
using System;
using System.Xml;
namespace XYLEM.Device
{
/// <summary>
/// A single calibration point
/// </summary>
[Serializable]
public class CalibrationPoint : IComparable<CalibrationPoint>, IEquatable<CalibrationPoint>
{
/// <summary>
/// Reference flow in liter / second
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/6661802342
/// </summary>
public Single ReferenceFlowRate_lps { get; set; }
/// <summary>
/// DUT Reported flow in liter / second
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/6661802342
/// </summary>
public Single ReportedFlowRate_lps { get; set; }
public CalibrationPoint()
{
ReferenceFlowRate_lps = ReportedFlowRate_lps = 0;
}
/// <summary>
/// Ctor
/// </summary>
/// <param name="referenceFlowRate_lps">reference flow rate [l/s] given by the flow-test-bench</param>
/// <param name="reportedFlowRate_lps">reported flow rate [l/s] by the DUT</param>
public CalibrationPoint(Single referenceFlowRate_lps, Single reportedFlowRate_lps)
{
ReferenceFlowRate_lps = referenceFlowRate_lps;
ReportedFlowRate_lps = reportedFlowRate_lps;
}
public override string ToString()
{
const int w1 = 10;
return $"Ref={ReferenceFlowRate_lps*3.6,w1:F3}m3/h DUT={ReportedFlowRate_lps*3.6,w1:F3}m3/h (Ref={ReferenceFlowRate_lps}L/s DUT={ReportedFlowRate_lps}L/s)";
}
public int CompareTo(CalibrationPoint other)
{
// If null, it can't be the same
if (System.Object.ReferenceEquals(other, null))
{
return -1;
}
// Any of them is not okay
if ((this.ReferenceFlowRate_lps!= other.ReferenceFlowRate_lps) || (this.ReportedFlowRate_lps!= other.ReportedFlowRate_lps))
{
return -1; // Not the same
}
return 0; // is the same
}
public bool Equals(CalibrationPoint other)
{
return this.CompareTo(other) == 0;
}
#region Operator == > < ! ..
public static bool operator ==(CalibrationPoint a, CalibrationPoint b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
// from https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type?redirectedfrom=MSDN
if (a is null)
{
// null == null = true.
if (b is null)
{
return true;
}
// Only the left side is null.
return false;
}
// Return true if the fields match:
return (a.Equals(b));
}
public static bool operator !=(CalibrationPoint a, CalibrationPoint b)
{
return !(a == b);
}
public static bool operator <(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) > 0;
}
public static bool operator >=(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator <=(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) <= 0;
}
#endregion
}
}
@@ -0,0 +1,198 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Xml;
using XYLEM.Base.XML;
namespace XYLEM.Device
{
[Serializable]
public class CalibrationPoints : IComparable<CalibrationPoints>, IEquatable<CalibrationPoints>
{
/// <summary>
/// calibrations to or from DUT
/// </summary>
public List<CalibrationPoint> calibrations { get; private set; }
public void SaveToFile(string filePath)
{
XMLWriteFuncClass.WriteToXmlFile(filePath, calibrations, false);
}
/// <summary>
///
/// </summary>
/// <param name="filePath"></param>
/// <returns>Is a valid calibration for DUT</returns>
public bool LoadFromFile(string filePath)
{
var pointsSaved = XMLWriteFuncClass.ReadFromXmlFile<List<CalibrationPoint>>(filePath);
calibrations = pointsSaved;
return IsOkay();
}
/// <summary>
/// Constructor for A empty list of calibrations, to use for loading calibrations from file
/// </summary>
public CalibrationPoints()
{
calibrations = new List<CalibrationPoint>();
}
/// <summary>
///
/// </summary>
/// <param name="cal_points"></param>
/// <param name="maxTotalPoints">Maximum numbers of calibration able to write to device</param>
public CalibrationPoints(List<CalibrationPoint> cal_points, int maxTotalPoints)
{
if (cal_points == null)
{
throw new ArgumentNullException("Calibrations points can't be zero");
}
if (cal_points.Count > maxTotalPoints)
{
throw new Exception($"Has {cal_points.Count} calibrations points and only support {maxTotalPoints}");
}
// Pad with zero if not the full size. Done to make a working writing and comparing two calibrations.
if (cal_points.Count < maxTotalPoints)
{
var missing = maxTotalPoints-cal_points.Count;
cal_points.AddRange(Enumerable.Range(0, missing).Select(_ => new CalibrationPoint(0, 0)));
}
calibrations = cal_points;
}
/// <summary>
/// Is a valid calibration to or from DUT
/// </summary>
/// <returns></returns>
public Boolean IsOkay()
{
if ((null == calibrations) || (0 > calibrations.Count))
{
return false; // Not okay
}
return true; // Is okay
}
/// <summary>
/// Number of calibrations to or from DUT
/// </summary>
/// <returns> is 0 or more if okay and -1 on error / not okay</returns>
public int Get_number_of_calibrations()
{
if (!IsOkay())
{
return -1;
}
return calibrations.Count;
}
public override string ToString()
{
if (!IsOkay())
{
return "No valide calibration to print out";
}
var ret_txt = "";
var idx = 0;
foreach (var cal in calibrations)
{
ret_txt += $"{idx++}: {cal}\n";
}
return ret_txt;
}
public int CompareTo(CalibrationPoints other)
{
// If null, it can't be the same
if (System.Object.ReferenceEquals(other, null))
{
return -1;
}
// Any of them is not okay
if (!this.IsOkay() || !other.IsOkay())
{
return -1; // Not the same
}
// if number of items is not the same
if (this.Get_number_of_calibrations() != other.Get_number_of_calibrations())
{
return -1; // Not the same
}
var num_of_cals = this.calibrations.Count;
var my_cals = this.calibrations;
var others_cals = other.calibrations;
for (int i = 0; i < num_of_cals; i++)
{
if (my_cals[i] != others_cals[i])
{
return -1; // Not the same
}
}
return 0; // is the same
}
public bool Equals(CalibrationPoints other)
{
return this.CompareTo(other) == 0;
}
#region Operator == > < ! ..
public static bool operator ==(CalibrationPoints a, CalibrationPoints b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
// from https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type?redirectedfrom=MSDN
if (a is null)
{
// null == null = true.
if (b is null)
{
return true;
}
// Only the left side is null.
return false;
}
// Return true if the fields match:
return (a.Equals(b));
}
public static bool operator !=(CalibrationPoints a, CalibrationPoints b)
{
return !(a == b);
}
public static bool operator <(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) > 0;
}
public static bool operator >=(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator <=(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) <= 0;
}
#endregion
}
}
@@ -0,0 +1,156 @@
using MagFlux6200_metrology_reg_list;
using XYLEM.Communication;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Device
{
/// <summary>
/// Command interface for MagFlux 6200
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft
/// </summary>
public interface IMagFluxRequestProtocol
{
/// <summary>
/// Is connected
/// </summary>
/// <returns>true if yes</returns>
Boolean IsConnected();
/// <summary>
/// Make communication connection to Meter
/// !!NOTE!! Only one meter is supported for each com port
/// </summary>
/// <param name="comport">Like "COM1"</param>
/// <returns>true on okay or false on error</returns>
Boolean Connect(string comport);
/// <summary>
/// Close communication connection to Meter
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean CloseConnection();
/// <summary>
/// Get printout of communication counters
/// </summary>
/// <returns></returns>
string GetComCounters();
/// <summary>
/// Set location for where log data can saved.
/// </summary>
/// <param name="path">path for where to log file should be saved</param>
/// <param name="filename">set a custom log file name without extension (ex. "UserCustomLogFile") or null if use default</param>
/// <returns>true on okay or false on error</returns>
Boolean SetLogLocation(String path, string filename = null);
/// <summary>
/// Open saved log file
/// </summary>
void OpenLogFile();
/// <summary>
/// MagFlux Sensor _serial number
/// </summary>
/// <param name="value_out">a decimal serial number ex. 12345678 or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetSensorSerialNo(out string value_out);
/// <summary>
/// Unique-ID for the MagFlux electronics
/// </summary>
/// <param name="value_out">a hex decimal string 0x1234ABCDEF or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetUniqueId(out string value_out);
/// <summary>
/// Get the firmware version
/// </summary>
/// <param name="value_out">like 1.2.4 (MAJOR.MINOR.REVISION)</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFirmwareVersion(out string value_out);
/// <summary>
/// Get the firmware build date
/// </summary>
/// <param name="value_out">like 2022/12/24 13:00:00 or 2022-12-24 13:45:10</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwBuildDate(out string value_out);
/// <summary>
/// Git Hash to Unique identify firmware
/// </summary>
/// <param name="value_out">like 0xABCDE123</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwGitHash(out string value_out);
/// <summary>
/// Flow rate calibrated
/// </summary>
/// <param name="value_out"> Actual flow rate [l/s] </param>
/// <returns>true on okay or false on error</returns>
Boolean GetFlowRate_lps(out Single value_out);
/// <summary>
/// MagFlux Sensor nominal DN size in millimeters
/// </summary>
/// <param name="value_out">DN size in [mm] is -1 on error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDn_mm(out Int32 value_out);
/// <summary>
/// Check if there is problem with the DUT
/// use <see cref="GetDeviceErrorMessages"/>" to get a list of error messages for debug problems
/// </summary>
/// <returns>>true if device operates correctly</returns>
Boolean GetDeviceHealthy();
/// <summary>
/// get a list of error messages for debug problem
/// </summary>
/// <param name="status_list_out">Will return a empty list if there is no messages to return</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDeviceErrorMessages(out List<string> status_list_out);
/// <summary>
/// This function prepares the DUT for the calibration.
///
/// ATTENTION:
/// This function needs to be called before the calibration process starts any flow of water.
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean PrepareDeviceForCalibration();
/// <summary>
/// This function will abort started or failed calibration to bring DUT back to normal calibration state
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean AbortDeviceForCalibration();
/// <summary>
/// The maximum calibration points that is supported by the device
/// </summary>
int CalibrationPointsMax { get; }
/// <summary>
/// Get list of calibration points saved in DUT
/// </summary>
/// <param name="values_read">The calibrations points from device</param>
/// <returns>true on okay or false on error</returns>
Boolean GetCalibrationPoints(out CalibrationPoints values_read);
/// <summary>
/// set calibration in DUT.
/// Remember to run <see cref="PrepareDeviceForCalibration"/> before the calibration process is started.
/// </summary>
/// <param name="new_calibration_points">A list of calibration points to write to DUT</param>
/// <returns>true on okay or false on error</returns>
Boolean SetCalibrationPoints(CalibrationPoints new_calibration_points);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,319 @@
using MagFlux6200_metrology_reg_list;
using System.Collections.Generic;
using System.Numerics;
using System;
using XYLEM.Communication;
using System.IO.Ports;
using XYLEM.Base.Files;
using System.Threading.Tasks;
using XYLEM.Base;
namespace XYLEM.Device
{
public abstract class ModbusDeviceCom
{
protected ProgramLogCSVFileClass _logger = null;
UInt16 _device_id = 1;
ModbusCom _md_com = null;
#if (!DEBUG)
public Boolean DoComDebugPrint = false;
#else
//public Boolean DoComDebugPrint = true;
public Boolean DoComDebugPrint = false;
#if (DoComDebugPrint)
#warning DoTxValuePrint is true!!!!!!!!!!!!!!!!
#endif
const int ch_lng_dv = -15;
const int ch_lng_Version = -3;
const int ch_lng_MD_adr = -7;
const int dig_value = 10;
#endif
public ModbusDeviceCom()
{
}
public Boolean SetLogLocation(string path, string filename)
{
try
{
// If already created a _logger then
if (_logger != null)
{
// TODO: nothing to do right now
throw new Exception("Logger path can only be set one time");
}
_logger = new ProgramLogCSVFileClass(path, filename);
return true; // Okay
}
catch (Exception ex)
{
Console.WriteLine($"Fail to setup program log path!\nPath:{path}\nMessage:{ex.Message}");
}
return false; // failed
}
public void OpenLogFile()
{
// If already created a _logger then
if (_logger != null)
{
_logger.OpenProgramLogFile();
}
}
public string GetComCounters()
{
if (_md_com == null)
{
return "T=? E=?";
}
return $"T={_md_com.MsgCount} E={_md_com.MsgErrorCount}";
}
public Boolean IsConnected()
{
if (_md_com == null)
{
return false;
}
return _md_com.IsConnected();
}
public Boolean CloseConnection()
{
try
{
StopBackgroundChecking();
if (_md_com != null)
{
/*There is nothing to close right now*/
}
return true; // is okay
}
catch (Exception ex)
{
_logger.AddFuncLog(true, this.ToString(), "CloseConnection", "Fail to close connection", ex);
}
return false; // failed
}
public virtual Boolean Connect(string comport, int baudRate, Parity parity)
{
try
{
{// Normal
if (IsConnected())
{
CloseConnection();
}
_md_com = new ModbusCom(comport, baudRate, parity);
return _md_com.IsConnected(); // return result
}
}
catch (Exception ex)
{
_logger.AddFuncLog(true, this.ToString(), "Connect", "Fail to open connection", ex);
}
return false; // failed
}
#region Background service
System.Timers.Timer _BackgroundCheckingTimer = null;
protected void StartBackgroundChecking()
{
StopBackgroundChecking(); // Make sure that a already running one is stopped
_BackgroundCheckingTimer = new System.Timers.Timer(1000);
_BackgroundCheckingTimer.Elapsed += (sender, e) => HandleBackgroundChecking();
_BackgroundCheckingTimer.Start();
}
protected void StopBackgroundChecking()
{
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Stop();
_BackgroundCheckingTimer.Close();
_BackgroundCheckingTimer = null;
}
}
/// <summary>
/// Handle checking DUT and background reading device values
/// </summary>
/// <returns></returns>
private void HandleBackgroundChecking()
{
// Don't continue background service before the first has been serviced
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Stop();
}
try
{
RunBackgroundReadServiceFunction();
}
catch (Exception ex)
{
#if (DEBUG)
var message = $"Fail background service handling";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "HandleBackgroundChecking()", message, ex);
#endif // #if (DEBUG)
}
// Don't continue background service before the first has been serviced
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Start();
}
}
/// <summary>
/// Need to be overwritten with a function for polling periodically read information from device for checking health etc.
/// </summary>
protected abstract void RunBackgroundReadServiceFunction();
#endregion // Background service
#region ---------------- Generic modbus communications ---------------------
protected UInt16? read_U16(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new UInt16());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected UInt32? read_U32(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new UInt32());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected Single? read_F32(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new Single());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected BigInteger? read_U128(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new BigInteger());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected List<ModbusDataRequest> read(List<Device_value> dvList)
{
var ret = _md_com.Read(_device_id, dvList);
if (ret.Count > 0)
{
#if (DEBUG)
foreach (var data in ret)
{
if (DoComDebugPrint)
{
var dv = data.Info;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={data.Data,dig_value}");
}
}
#endif // #if (DEBUG)
return ret;
}
return null; // Error in reading
}
protected bool write_U16(Device_value dv, UInt16 value)
{
var isOkay = _md_com.Write(_device_id, dv, value);
if (!isOkay)
{
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Failed Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
}
return isOkay; // Error in reading
}
/// <summary>
/// Write multiple values in a optimized number of telegrams
/// </summary>
/// <param name="reqList"></param>
/// <returns></returns>
protected List<ModbusDataRequest> write(List<ModbusDataRequest> reqList)
{
var ret = _md_com.Write(_device_id, reqList);
if ((ret!=null) && (ret.Count > 0))
{
#if (DEBUG)
foreach (var data in ret)
{
if (DoComDebugPrint)
{
var dv = data.Info;
Console.WriteLine($"Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={data.Data,dig_value} {data.IsOkay}");
}
}
#endif // #if (DEBUG)
return ret;
}
return null; // Error in reading
}
#endregion // #region ---------------- Generic modbus communications ---------------------
}
}
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Device.Value
{
/// <summary>
/// Possible Type to use
/// </summary>
public enum ValueDataType
{
_Empty,
B8,
S8,
U8,
Bool,
U16,
U16MJK_SN,
U16MJK_BRAND_ID,
B16,
S16,
B32,
U32,
U32MJK_SN,
S32,
F32,
B64,
U64,
S64,
F64,
U128,
Array6B,
Array10B,
Array12B,
Array64B,
Array128B,
Array136B,
Array250B,
STR6E,
STR6S,
STR6,
STR8E,
STR8S,
STR8,
STR10E,
STR10S,
STR10,
STR16E,
STR16S,
STR16,
STR18E,
STR18S,
STR18,
STR20E,
STR20S,
STR20,
STR22E,
STR22S,
STR22,
STR30E,
STR30S,
STR30,
STR32E,
STR32S,
STR32,
STR34E,
STR40E,
STR40S,
STR40,
STR64E,
STR64S,
STR64,
STR100E,
STR100S,
STR100,
STR128E,
STR128S,
STR128,
STR240E,
STR240S,
STR240,
U16TEXTID,
U16UNIT,
U16UNITGROUP,
U32TIME_Y2000,
U32TIME_Y1970,
U32TIME_Y1970_UTC,
TIME_ymdhms,
TIME_ASCII_12B
}
}
@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace XYLEM.Device.Value
{
public static class ValueDescriptionFunc
{
/// <summary>
/// Is data a text
/// </summary>
/// <returns></returns>
public static Boolean IsText(this ValueDataType DataType)
{
switch (DataType)
{
case ValueDataType._Empty:
case ValueDataType.B8:
case ValueDataType.S8:
case ValueDataType.U8:
case ValueDataType.Bool:
case ValueDataType.U16:
case ValueDataType.U16MJK_SN:
case ValueDataType.U16MJK_BRAND_ID:
case ValueDataType.B16:
case ValueDataType.S16:
case ValueDataType.B32:
case ValueDataType.U32:
case ValueDataType.U32MJK_SN:
case ValueDataType.S32:
case ValueDataType.F32:
case ValueDataType.B64:
case ValueDataType.U64:
case ValueDataType.S64:
case ValueDataType.F64:
case ValueDataType.U128:
case ValueDataType.U16TEXTID:
case ValueDataType.U16UNIT:
case ValueDataType.U16UNITGROUP:
case ValueDataType.U32TIME_Y2000:
case ValueDataType.U32TIME_Y1970:
case ValueDataType.U32TIME_Y1970_UTC:
case ValueDataType.TIME_ASCII_12B:
case ValueDataType.TIME_ymdhms:
case ValueDataType.Array6B:
case ValueDataType.Array10B:
case ValueDataType.Array12B:
case ValueDataType.Array64B:
case ValueDataType.Array128B:
case ValueDataType.Array136B:
case ValueDataType.Array250B:
return false;
default:
if (DataType.ToString().StartsWith("STR"))
{
return true; // Is text
}
throw (new Exception("No known tag = " + DataType.ToString()));
}
}
public static bool IsSMSText(this ValueDataType DataType)
{
if (DataType.IsText())
{
var typeAsText = DataType.ToString();
if (typeAsText.EndsWith("S"))
{ // is Email
return true;
}
}
return false;
}
public static bool IsEmailText(this ValueDataType DataType)
{
if (DataType.IsText())
{
var typeAsText = DataType.ToString();
if (typeAsText.EndsWith("E"))
{ // is Email
return true;
}
}
return false;
}
/// <summary>
/// Conversion has to be for string Quoted Printable Text
/// </summary>
/// <param name="DataType"></param>
/// <returns></returns>
public static bool IsEmailQuotedPrintableText(this ValueDataType DataType)
{
if (DataType.IsText())
{
var typeAsText = DataType.ToString();
if (typeAsText.EndsWith("Q"))
{ // is Email
return true;
}
}
return false;
}
/// <summary>
/// Conversion type for string is Windows 1252
/// </summary>
/// <param name="DataType"></param>
/// <returns></returns>
public static bool IsWindows1252Text(this ValueDataType DataType)
{
if (DataType.IsText())
{
var typeAsText = DataType.ToString();
if (typeAsText.EndsWith("W1252"))
{ // is Email
return true;
}
}
return false;
}
/// <summary>
/// Conversion type for string is Windows 1252 and for the email recipient address that needs special handling
/// Needs to have "<>" in frond and end
/// </summary>
/// <param name="DataType"></param>
/// <returns></returns>
public static bool IsWindows1252TextRecipient(this ValueDataType DataType)
{
if (DataType.IsText())
{
var typeAsText = DataType.ToString();
if (typeAsText.EndsWith("W1252rec"))
{ // is Email
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,155 @@
using XYLEM.Device.Value;
using MagFlux6200_metrology_reg_list;
using XYLEM.Communication;
using System;
using System.IO.Ports;
using System.Threading.Tasks;
namespace XYLEM.Device
{
public enum MD_Reg_list
{
APP,
MET
}
public class md_test
{
#region Access data from normal Application RS485
internal static readonly Device_value App_F32FlowRate_m3ps = new Device_value("App_F32FlowRate_m3ps", 600, ValueDataType.F32, ValueRW_Type.ReadOnly, "App read flow");
#endregion
const int ch_lng_dv = -15;
const int ch_lng_Version = -3;
const int ch_lng_MD_adr = -7;
const int dig_value = 10;
public void Go(MD_Reg_list md_reg_list_selection, string serial_port, int baudRate, Parity parity)
{
ModbusCom md = new ModbusCom(serial_port, baudRate, parity);
ReadTests(md_reg_list_selection, md);
}
public void ReadTests(MD_Reg_list md_reg_list_selection, ModbusCom md)
{
var device_id = 1;
//{ // Testing read of specific registers
// var test_rw_items = new[] { reg_list.Met_U32MdbsRegsVer, reg_list.Met_U16DeviceType, reg_list.Met_U32DeviceTypeDetail };
// foreach (var testRead in test_rw_items)
// {// Testing
// Device_value dv = null;
// if (md_reg_list_selection == MD_Reg_list.MET) // Metrology
// {
// dv = testRead;
// var ret = md.Read(device_id, dv, new UInt32());
// if (ret.IsOkay)
// {
// var value = ret.Data;
// Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={value,dig_value}");
// }
// }
// else // To application
// {
// dv = null; // Not yet supported
// }
// }
// return;
//}
{ // Read ID
Device_value dv = reg_list.Met_U16DeviceType;
var ret = md.Read(device_id, dv, new UInt16());
if (ret.IsOkay)
{
var value = ret.Data;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
}
{// Read Met_U32MdbsRegsVer
Device_value dv = null;
if (md_reg_list_selection == MD_Reg_list.MET) // Metrology
{
dv = reg_list.Met_U32MdbsRegsVer;
var ret = md.Read(device_id, dv, new UInt32());
if (ret.IsOkay)
{
var value = ret.Data;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={value,dig_value}");
}
}
else // To application
{
dv = null; // Not yet supported
}
}
{// Read flow
Device_value dv = null;
string unit = "m3/h";
Single scale = 1.0f;
if (md_reg_list_selection == MD_Reg_list.MET) // Metrology
{
dv = reg_list.Met_F32FlowRate_lps;
scale = 3.6f; // From l/s to m3/h
}
else // To application
{
dv = App_F32FlowRate_m3ps;
scale = 3600f; // From m3/s to m3/h
}
var ret = md.Read(device_id, dv, new Single());
if (ret.IsOkay)
{
var value = ret.Data;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={(value*scale),dig_value} {unit}");
}
}
{// Read / Write scratch
Device_value dv = null;
string unit = "";
Single scale = 1.0f;
if (md_reg_list_selection == MD_Reg_list.MET) // Metrology
{
dv = reg_list.Met_F32Scratch_F32;
Single value = Single.NaN;
{ // read
var ret = md.Read(device_id, dv, new Single());
if (ret.IsOkay)
{
value = ret.Data;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={(value*scale),dig_value} {unit}");
}
}
{ // write
value += 10;
if (!md.Write(device_id, dv, value))
{
Console.WriteLine($"Write failed={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={value,dig_value} {unit}");
}
else
{
Console.WriteLine($"Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={value,dig_value} {unit}");
}
}
{ // read back
var ret = md.Read(device_id, dv, new Single());
if (ret.IsOkay)
{
value = ret.Data; ;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,-7} value={(value*scale),dig_value} {unit}");
}
}
}
else // To application
{
dv = null; // Not yet supported
}
}
}
}
}

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