sync the state

This commit is contained in:
Stoyan Zlatev 2025-02-20 15:27:22 +01:00
parent ac50c18c06
commit ef8f1cf7cc
70 changed files with 1714 additions and 695 deletions

View File

@ -155,7 +155,7 @@
</site>
<site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\Users\drabesch_ro\Repo\lab\la_operations\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" />

View File

@ -356,6 +356,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaPackages.HttpClient", "L
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stichproben", "Stichproben\Stichproben.csproj", "{F69A79FA-548D-4E21-887E-01FABDAD9E73}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaaPackages.Features.Cordonel", "LaaPackages\LaaPackages.Features.Cordonel\LaaPackages.Features.Cordonel.csproj", "{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4
@ -5638,6 +5640,70 @@ Global
{F69A79FA-548D-4E21-887E-01FABDAD9E73}.XP32bit|x64.Build.0 = Release|Any CPU
{F69A79FA-548D-4E21-887E-01FABDAD9E73}.XP32bit|x86.ActiveCfg = Release|Any CPU
{F69A79FA-548D-4E21-887E-01FABDAD9E73}.XP32bit|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.COM|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|x64.ActiveCfg = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|x64.Build.0 = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|x86.ActiveCfg = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Debug|x86.Build.0 = Debug|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.PerformTest|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.Release|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.ReleaseTest|x86.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|Any CPU.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|x64.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|x64.Build.0 = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|x86.ActiveCfg = Release|Any CPU
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}.XP32bit|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -5783,6 +5849,7 @@ Global
{F90B940C-9A83-496D-AAE0-11CD02CE0A22} = {2E31C385-4FFC-473E-9C00-D7DC48140704}
{C9816412-7752-4F7A-8BD2-765DB6D58B3C} = {2E31C385-4FFC-473E-9C00-D7DC48140704}
{F69A79FA-548D-4E21-887E-01FABDAD9E73} = {696A94BE-7237-4AE2-9E36-6059DE519971}
{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB} = {2E31C385-4FFC-473E-9C00-D7DC48140704}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164}

View File

@ -57,11 +57,24 @@
<ItemGroup />
<ItemGroup>
<None Include="App.config" />
<None Include="configuration.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hardware\WaterMeter\eRegister\Common.Hardware.WaterMeter.eRegister\Common.Hardware.WaterMeter.eRegister.csproj">
<Project>{4E8BB839-D40A-488C-88CE-F21811F1F476}</Project>
<Name>Common.Hardware.WaterMeter.eRegister</Name>
<ProjectReference Include="..\Hardware\WaterMeter\Genesis\GenesisConfig\GenesisConfig.csproj">
<Project>{f013a56b-7be6-4852-9cd8-b971cd1add0c}</Project>
<Name>GenesisConfig</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\WaterMeter\Genesis\GenesisCore\GenesisCore.csproj">
<Project>{04201e95-90a0-4b73-a72f-379739b2a3ae}</Project>
<Name>GenesisCore</Name>
</ProjectReference>
<ProjectReference Include="..\Hardware\WaterMeter\Genesis\Registers\Registers.csproj">
<Project>{f4aaf7e6-7333-4284-b735-e32deb076c64}</Project>
<Name>Registers</Name>
</ProjectReference>
<ProjectReference Include="..\LaaPackages\LaaPackages.Features.Cordonel\LaaPackages.Features.Cordonel.csproj">
<Project>{8BEFD3AC-BB21-4B62-8D9A-CF8CBFD439EB}</Project>
<Name>LaaPackages.Features.Cordonel</Name>
</ProjectReference>
<ProjectReference Include="..\Stichproben\Stichproben.csproj">
<Project>{F69A79FA-548D-4E21-887E-01FABDAD9E73}</Project>

View File

@ -1,197 +1,10 @@
namespace CommonConsole
{
using Common.Hardware.WaterMeter.eRegister.Features;
using Common.Hardware.WaterMeter.eRegister.Models;
using Stichproben.Cordonel;
using System;
using System.Collections.Generic;
using System.Reflection;
public static class Program
{
public static void Main()
{
var stichproben = new Stichproben(typeof(Program).Assembly.Location);
var result = stichproben.ShouldBePressureTested(20250205);
}
public static void ___Main()
{
var features = new List<EregisterFeature>();
foreach (var featureInfo in typeof(EregisterFeatures).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var featurePamAttribute = featureInfo.GetCustomAttribute<PamAttribute>();
if (featurePamAttribute is null)
{
continue;
}
var featureType = featureInfo.PropertyType;
if (typeof(Pam).IsAssignableFrom(featureType))
{
var featurePam = Activator.CreateInstance(featureType) as Pam;
var feature = new EregisterFeature
{
FeatureType = featureType,
Cmd = featurePam.CmdHex,
IsSingleCmd = featurePamAttribute.IsSingleCmd,
OnlyProductionMode = featurePamAttribute.OnlyProductionMode,
AuthLevel = featurePamAttribute.AuthLevel,
};
foreach (var featurePropertyInfo in feature.FeatureType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!featurePropertyInfo.CanRead || !featureInfo.CanWrite)
{
continue;
}
feature.Add(new EregisterFeatureProperty
{
Name = featurePropertyInfo.Name,
Type = featurePropertyInfo.PropertyType,
Getter = featurePropertyInfo.GetValue,
Setter = featurePropertyInfo.SetValue,
});
}
features.Add(feature);
}
else if (featureType == typeof(EregisterDebugFeatures))
{
var feature = new EregisterDebugFeature
{
AuthLevel = AuthLevel.III,
Cmd = "F1",
FeatureType = featureType,
IsSingleCmd = true
};
foreach (var debugFeatureFeatureInfo in typeof(EregisterDebugFeatures).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var debugFeaturePamAttribute = debugFeatureFeatureInfo.GetCustomAttribute<PamAttribute>();
if (debugFeaturePamAttribute is null)
{
continue;
}
var debugFeatureType = debugFeatureFeatureInfo.PropertyType;
var debugFeaturePam = Activator.CreateInstance(debugFeatureType) as Pam;
var debugFeature = new EregisterDebugFeature
{
FeatureType = featureType,
Cmd = debugFeaturePam.CmdHex,
IsSingleCmd = featurePamAttribute.IsSingleCmd,
OnlyProductionMode = featurePamAttribute.OnlyProductionMode,
AuthLevel = featurePamAttribute.AuthLevel,
};
foreach (var debugFeaturePropertyInfo in debugFeatureType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!debugFeaturePropertyInfo.CanRead || !featureInfo.CanWrite)
{
continue;
}
debugFeature.Add(new EregisterFeatureProperty
{
Name = debugFeaturePropertyInfo.Name,
Type = debugFeaturePropertyInfo.PropertyType,
Getter = debugFeaturePropertyInfo.GetValue,
Setter = debugFeaturePropertyInfo.SetValue,
});
}
feature.Add(debugFeature);
}
features.Add(feature);
}
}
foreach (var feature in features)
{
foreach (var items in feature.GetItems())
{
Console.Write($"{items[0],40}");
Console.Write($"{items[1],5}");
Console.Write($"{items[2],5}");
Console.Write($"{items[3],5}");
Console.Write($"{items[4],5}");
Console.WriteLine();
}
}
}
}
public class EregisterFeature
{
private readonly ICollection<EregisterFeatureProperty> properties
= new List<EregisterFeatureProperty>();
public Type FeatureType { get; set; }
public string Cmd { get; set; }
public bool IsSingleCmd { get; set; }
public bool OnlyProductionMode { get; set; }
public AuthLevel AuthLevel { get; set; }
public virtual void Add(EregisterFeatureProperty eregisterFeatureProperty)
=> this.properties.Add(eregisterFeatureProperty);
public virtual IEnumerable<string[]> GetItems()
{
yield return new[]
{
this.FeatureType.Name,
this.Cmd,
$"{this.AuthLevel}",
this.IsSingleCmd ? "v" : " ",
this.OnlyProductionMode ? "v" : " "
};
}
}
public class EregisterDebugFeature : EregisterFeature
{
private readonly ICollection<EregisterFeature> features
= new List<EregisterFeature>();
public virtual void Add(EregisterFeature feature)
=> this.features.Add(feature);
public override IEnumerable<string[]> GetItems()
{
foreach (var feature in this.features)
{
foreach (var items in feature.GetItems())
{
yield return items;
}
}
}
}
public class EregisterFeatureProperty
{
public string Name { get; set; }
public Type Type { get; set; }
public Func<object, object> Getter { get; set; }
public Action<object, object> Setter { get; set; }
}
}

View File

@ -14,10 +14,10 @@
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>\\sla12file\auftrag\Aktuelle Anwendungen\CAL\</PublishUrl>
<IsWebBootstrapper>true</IsWebBootstrapper>
<PublishUrl>\\SLA12IIS01\LaaProductionWeb\Apps\CordonelAssembly\</PublishUrl>
<Install>true</Install>
<InstallFrom>Unc</InstallFrom>
<InstallFrom>Web</InstallFrom>
<UpdateEnabled>true</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
@ -25,12 +25,13 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<InstallUrl>\\sla12file\auftrag\Aktuelle Anwendungen\CAL\</InstallUrl>
<InstallUrl>http://sla12iis01.emea.sensus.net/LaaProductionWeb/Apps/CordonelAssembly/</InstallUrl>
<ProductName>Cordonel Assembly Line</ProductName>
<PublisherName>Xylem Sensus Laatzen</PublisherName>
<SuiteName>Cordonel Assembly Line</SuiteName>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.htm</WebPage>
<ApplicationRevision>6</ApplicationRevision>
<ApplicationRevision>8</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>

View File

@ -43,6 +43,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PamChanel.cs" />
<Compile Include="Parameters\BluetoothOperating.cs" />
<Compile Include="Parameters\OperatingModes.cs" />
<Compile Include="Parameters\P11.cs" />
@ -55,21 +56,20 @@
<Compile Include="Parameters\RSSI.cs" />
<Compile Include="Parameters\SirtOperating.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SerialDataExtensions.cs" />
<Compile Include="SerialPort.cs" />
<Compile Include="SIRTBroadcaster.Internal.cs" />
<Compile Include="SIRTFactory.cs" />
<Compile Include="SIRTBroadcaster.Public.cs" />
<Compile Include="SIRTKey.cs" />
<Compile Include="SIRTMessage.cs" />
<Compile Include="SIRTStream.cs" />
<Compile Include="SIRTStreamFactory.cs" />
<Compile Include="SIRTTask.Public.cs" />
<Compile Include="SIRTTaskState.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="SIRTTask.Internal.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common.Hardware.Ports\Common.Hardware.Ports.csproj">
<Project>{9ae071c0-db12-4e09-a3c7-43f6dcd518d6}</Project>
<Name>Common.Hardware.Ports</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,22 @@
namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Concurrent;
public class PamChanel
{
private readonly ConcurrentQueue<SIRTTask> tasks = new ConcurrentQueue<SIRTTask>();
public uint Address { get; set; }
public void Push(SIRTMessage message)
{
}
internal void Pop()
{
throw new NotImplementedException();
}
}
}

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
public class BluetoothOperating
{
private readonly byte[] bits;

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
using System.Text;
/// <summary>

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
using System;
/// <summary>

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
/// <summary>
/// Parameter P81-1 is the first modifier of "Write to PAM Pool" command and is placed at third position,
/// if telegram from PC -> SIRT begins with {0x55, 0x81}.

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
public class P821
{
private readonly byte[] bits;

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
using System.Text;
public class PAMStatus

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
using System;
public class RFModuleOperating

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT
namespace Common.Hardware.SIRT.Parameters
{
using Common.Hardware.Ports;
public class SirtOperating
{
private readonly byte[] bits;

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT
{
using Common.Hardware.Ports;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;
@ -13,6 +11,8 @@
{
private readonly ConcurrentDictionary<uint, ConcurrentQueue<SIRTTask>> tasks
= new ConcurrentDictionary<uint, ConcurrentQueue<SIRTTask>>();
private readonly ManualResetEventSlim tasksAwaiter = new ManualResetEventSlim();
private readonly IList<bool> tasksInPampool = new List<bool>();
private readonly SerialPort serialPort;
private CancellationTokenSource cancellationTokenSource;
@ -165,29 +165,41 @@
{
this.IsActivated = true;
this.processingTask = Task.Factory.StartNew(() =>
this.processingTask = Task.Factory.StartNew(async () =>
{
var manualResetEventSlim = new ManualResetEventSlim();
while (!this.cancellationToken.IsCancellationRequested)
{
if (this.tasksInPampool.Count >= 5)
{
this.tasksAwaiter.Wait();
this.tasksAwaiter.Reset();
}
foreach (var tasksQueue in this.tasks.Values.ToArray())
{
if (this.tasksInPampool.Count >= 5)
{
this.tasksAwaiter.Wait();
this.tasksAwaiter.Reset();
}
if (tasksQueue.TryPeek(out var task) && task.State == SIRTTaskState.Pending)
{
this.tasksInPampool.Add(true);
this.serialPort.Write(task.Start());
this.Logging?.Invoke(task.ToString());
}
manualResetEventSlim.Wait(100);
manualResetEventSlim.Reset();
await Task.Delay(10);
}
manualResetEventSlim.Wait(100);
manualResetEventSlim.Reset();
await Task.Delay(10);
}
}, this.cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current)
}
, this.cancellationToken
, TaskCreationOptions.LongRunning
, TaskScheduler.Current)
.ContinueWith(this.ExceptionLogging);
}
@ -268,6 +280,15 @@
task.Cancelled -= this.OnStateChanged;
task.Completed -= this.OnStateChanged;
task.Timeouted -= this.OnTaskTimeout;
var lastIX = this.tasksInPampool.Count - 1;
if (lastIX >= 0)
{
this.tasksInPampool.RemoveAt(lastIX);
}
this.tasksAwaiter.Set();
}
private bool TryRun<TTask>(TTask task) where TTask : SIRTTask

View File

@ -1,7 +1,5 @@
namespace Common.Hardware.SIRT
{
using Common.Hardware.Ports;
using System;
using System.Collections.Concurrent;

View File

@ -21,15 +21,6 @@
}
}
public void CloseConnections()
{
foreach (var broadcaster in this.GetConnections())
{
broadcaster.Logging -= this.NotifyMessage;
broadcaster.Close();
}
}
public void DequeueTasks(uint address)
{
foreach (var broadcaster in this.GetConnections())
@ -38,15 +29,6 @@
}
}
public void OpenConnections()
{
foreach (var broadcaster in this.GetConnections())
{
broadcaster.Logging += this.NotifyMessage;
broadcaster.Open();
}
}
public void ConnectSIRT(string portName, Action<SIRTBroadcaster> callback)
{
if (!this.broadcasters.TryGetValue(portName, out var broadcaster))
@ -60,13 +42,12 @@
}
}
callback(broadcaster);
if (broadcaster?.IsActivated == false)
{
broadcaster?.Close();
broadcaster?.Open();
}
callback(broadcaster);
}
public void EnqueueTask(SIRTTask task)
@ -77,9 +58,6 @@
}
}
public IEnumerable<string> GetPortNames()
=> this.broadcasters.Keys.ToArray();
public void RemoveConnections()
{
foreach (var key in this.broadcasters.Keys.ToArray())
@ -92,10 +70,10 @@
}
}
private IEnumerable<SIRTBroadcaster> GetConnections()
=> this.broadcasters.Values.ToArray();
private void NotifyMessage(string message)
=> this.Logging?.Invoke(message);
private IEnumerable<SIRTBroadcaster> GetConnections()
=> this.broadcasters.Values.ToArray();
}
}

View File

@ -0,0 +1,30 @@
namespace Common.Hardware.SIRT
{
using System;
public struct SIRTKey : IEquatable<SIRTKey>
{
public SIRTKey(string identity, int frecuency) : this()
{
this.SirtId = identity;
this.Frequency = frecuency;
}
public string SirtId { get; set; }
public int Frequency { get; set; }
public bool Equals(SIRTKey other)
=> other.SirtId == this.SirtId;
public override bool Equals(object other)
=> other is SIRTKey sirtKey
&& this.Equals(sirtKey);
public override int GetHashCode()
=> this.ToString().GetHashCode();
public override string ToString()
=> $"{this.SirtId}|{this.Frequency}";
}
}

View File

@ -1,7 +1,7 @@
namespace Common.Hardware.SIRT
{
using Common.Hardware.Ports;
using Newtonsoft.Json;
using Common.Hardware.SIRT.Parameters;
using System;
public class SIRTMessage
@ -26,13 +26,17 @@
public SIRTMessage()
{
this.bytes = new byte[MIN_LEN];
this.bytes[0] = PC2SIRT;
this.Start = PC2SIRT;
this.Stop = STOP;
}
public SIRTMessage(byte[] bytes)
public SIRTMessage(byte[] bytes) : this()
=> this.bytes = bytes;
public byte Start
{
this.bytes = bytes;
this.bytes[0] = SIRT2PC;
get => this.bytes[0];
set => this.bytes[0] = value;
}
public byte Cmd
@ -59,9 +63,12 @@
set => value.GetBytesBE().CopyTo(this.bytes, 4);
}
public byte Length => this.bytes[8];
public byte Length
{
get => this.bytes[8];
set => this.bytes[8] = value;
}
[JsonIgnore]
public byte[] Data
{
get
@ -87,24 +94,68 @@
}
}
public ushort CRC => this.bytes.ToUInt16BE(this.bytes.Length - 3);
public string Content => this.ToString();
public byte[] ToByteArray()
public ushort CRC
{
var length = this.bytes.Length;
var crc = this.bytes.CRCCCITT(1, length - 3);
var crcBytes = crc.GetBytesBE();
get => this.bytes.ToUInt16BE(this.bytes.Length - 3);
set => value.GetBytesBE().CopyTo(this.bytes, this.bytes.Length - 3);
}
this.bytes[length - 3] = crcBytes[0];
this.bytes[length - 2] = crcBytes[1];
this.bytes[length - 1] = STOP;
public byte Stop
{
get => this.bytes[this.bytes.Length - 1];
set => this.bytes[this.bytes.Length - 1] = value;
}
public byte[] GetBytes()
{
this.CRC = this.bytes.CRCCCITT(1, this.bytes.Length - 3);
this.Stop = STOP;
return this.bytes;
}
public override string ToString()
=> BitConverter.ToString(this.ToByteArray());
=> BitConverter.ToString(this.bytes);
public static implicit operator byte[] (SIRTMessage message)
=> message.bytes;
public static implicit operator SIRTMessage(byte[] bytes)
=> new SIRTMessage(bytes);
internal static SIRTMessage Activate = new SIRTMessage
{
Cmd = W_REG,
Address = 0x20000000,
P2 = 0x05,
Data = new byte[]
{
new SirtOperating { /* default */ },
new BluetoothOperating { BtOff = true },
new RFModuleOperating { RfOff = true },
new RFModuleOperating { OpMode = OperatingModes.ReceiveF1TransmitSensusRFF3 },
new PamTimeout { Minutes = 1 }
}
};
internal static SIRTMessage Identify = new SIRTMessage
{
Cmd = SIRTMessage.R_REG,
Address = 0x11001820,
P2 = 0x08
};
internal static readonly SIRTMessage ReadPamPool = new SIRTMessage
{
Cmd = R_PAM,
Address = 0xFFFFFFFF
};
internal static SIRTMessage DeleteFromPamPool(uint address) => new SIRTMessage
{
Cmd = W_PAM,
P1 = new P811 { DelPamAdr = true },
Address = address
};
}
}

View File

@ -0,0 +1,263 @@
namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
using SystemSerialPort = System.IO.Ports.SerialPort;
public class SIRTStream
{
private readonly SystemSerialPort serialPort = new SystemSerialPort
{
BaudRate = 112500,
DataBits = 8,
Parity = Parity.None,
StopBits = StopBits.One
};
public bool IsRunning { get; private set; }
public string Identity { get; private set; }
public int Frecuency { get; private set; }
public SIRTKey Key { get; private set; }
public string PortName => this.serialPort.PortName;
public void Close(int timeout = 3000)
{
var disposeAwaiter = new ManualResetEventSlim();
void Disposed(object _, EventArgs _1)
{
this.serialPort.Disposed -= Disposed;
disposeAwaiter.Set();
}
try
{
this.serialPort.Disposed += Disposed;
this.serialPort.Close();
disposeAwaiter.Wait(timeout);
}
catch // TODO: (Exception e)
{
this.serialPort.Disposed -= Disposed;
disposeAwaiter.Set();
}
}
public void Open(string portName, int timeout = 3000)
{
if (this.serialPort.IsOpen)
{
this.IsRunning = false;
this.Close();
}
this.serialPort.PortName = portName;
try
{
this.serialPort.Open();
}
catch // TODO: (Exception e)
{
return;
}
var sirtRequest = default(SIRTMessage);
var sirtRequestBytes = default(byte[]);
var sirtResponse = default(SIRTMessage);
var sirtResponseAwaiter = new ManualResetEventSlim();
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
var cancellationTask = Task.Run(() =>
{
foreach (var message in this.ReadStream())
{
var sameAddress = message.Address == sirtRequest?.Address;
var isAnswer = message.Cmd == SIRTMessage.ACKNANSW;
var withNoErrors = message.P1 == 0;
var readOrWrite = message.P2 == SIRTMessage.W_REG || message.P2 == SIRTMessage.R_REG;
if (sameAddress && isAnswer && withNoErrors && readOrWrite)
{
sirtResponse = message;
sirtResponseAwaiter.Set();
}
}
}, cancellationToken);
try
{
sirtResponse = null;
sirtRequest = SIRTMessage.Activate;
sirtRequestBytes = sirtRequest.GetBytes();
for (var i = 0; i < 5; i++)
{
this.Write(sirtRequestBytes);
sirtResponseAwaiter.Wait(timeout);
sirtResponseAwaiter.Reset();
if (sirtResponse != null)
{
break;
}
}
sirtResponse = null;
sirtRequest = SIRTMessage.Identify;
sirtRequestBytes = sirtRequest.GetBytes();
for (var i = 0; i < 5; i++)
{
this.Write(sirtRequestBytes);
sirtResponseAwaiter.Wait(timeout);
sirtResponseAwaiter.Reset();
if (sirtResponse != null)
{
this.IsRunning = true;
this.Identity = BitConverter.ToString(sirtResponse.Data ?? Array.Empty<byte>());
this.Frecuency = string.IsNullOrWhiteSpace(this.Identity)
? -1
: this.Identity[10] == '0'
? 868
: 433;
this.Key = new SIRTKey(this.Identity, this.Frecuency);
break;
}
}
cancellationTokenSource.Cancel();
}
catch // TODO: (Exception e)
{
return;
}
}
public IEnumerable<SIRTMessage> ReadStream()
{
var readAwaiter = new ManualResetEventSlim();
void DataReceived(object _, SerialDataReceivedEventArgs args)
{
if (args.EventType == SerialData.Chars)
{
readAwaiter.Set();
}
}
this.serialPort.DataReceived += DataReceived;
var buffer = new List<byte>();
var bytes = default(byte[]);
var length = default(int);
while (this.serialPort.IsOpen)
{
readAwaiter.Wait();
readAwaiter.Reset();
bytes = new byte[this.serialPort.BytesToRead];
length = this.serialPort.Read(bytes, 0, bytes.Length);
if (length <= 0)
{
continue;
}
buffer.AddRange(bytes);
while (this.TryParseMessage(buffer, out var message))
{
yield return message;
}
}
this.serialPort.DataReceived -= DataReceived;
}
public void Write(byte[] bytes)
{
if (this.serialPort.IsOpen && bytes?.Length > 0)
{
this.serialPort.Write(bytes, 0, bytes.Length);
}
}
private bool TryParseMessage(List<Byte> buffer, out SIRTMessage message)
{
message = default(SIRTMessage);
var bufferLength = buffer.Count;
if (bufferLength <= 0)
{
return false;
}
var msgLength = 0;
var msg = default(byte[]);
var startIX = buffer.IndexOf(SIRTMessage.SIRT2PC);
if (startIX < 0)
{
buffer.Clear();
return false;
}
var lengthIX = startIX + 8;
if (lengthIX >= bufferLength)
{
return false;
}
var dataLength = buffer[lengthIX];
var stopIX = lengthIX + dataLength + 3;
if (stopIX >= bufferLength)
{
return false;
}
if (buffer[stopIX] != SIRTMessage.STOP)
{
startIX = buffer.IndexOf(SIRTMessage.SIRT2PC, startIX + 1);
if (startIX >= 0)
{
buffer.RemoveRange(0, startIX + 1);
}
else
{
buffer.Clear();
}
return false;
}
msgLength = stopIX - startIX + 1;
msg = new byte[msgLength];
buffer.CopyTo(startIX, msg, 0, msgLength);
buffer.RemoveRange(0, startIX + msgLength);
message = new SIRTMessage(msg);
return true;
}
}
}

View File

@ -0,0 +1,81 @@
namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class SIRTStreamFactory
{
private readonly ConcurrentDictionary<SIRTKey, SIRTStream> streams = new ConcurrentDictionary<SIRTKey, SIRTStream>();
private readonly ConcurrentDictionary<SIRTKey, List<bool>> pams = new ConcurrentDictionary<SIRTKey, List<bool>>();
private readonly ConcurrentDictionary<SIRTKey, Task> readers = new ConcurrentDictionary<SIRTKey, Task>();
private readonly ConcurrentDictionary<uint, PamChanel> chanels
= new ConcurrentDictionary<uint, PamChanel>();
private readonly ConcurrentDictionary<uint, ConcurrentBag<SIRTKey>> addresses
= new ConcurrentDictionary<uint, ConcurrentBag<SIRTKey>>();
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private Task cancellationTaks;
public void ConnectSirts(params string[] portNames)
{
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
var tasks = new List<Task>();
foreach (var portName in portNames.Intersect(SerialPort.GetPortNames()))
{
var task = Task.Run(() =>
{
var sirtStream = new SIRTStream();
sirtStream.Open(portName);
if (sirtStream.IsRunning)
{
this.streams.GetOrAdd(sirtStream.Key, sirtStream);
this.pams.GetOrAdd(sirtStream.Key, new List<bool>());
this.readers.GetOrAdd(sirtStream.Key, Task.Run(() =>
{
var stream = sirtStream;
var key = stream.Key;
foreach (var message in stream.ReadStream())
{
var address = message.Address;
this.addresses
.GetOrAdd(address, new ConcurrentBag<SIRTKey>())
.Add(key);
this.chanels
.GetOrAdd(message.Address, new PamChanel())
.Push(message);
}
}
, this.cancellationToken));
}
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
this.cancellationTaks = Task.Run((Action)this.StartSendingPams, this.cancellationToken);
}
private void StartSendingPams()
{
while (!this.cancellationToken.IsCancellationRequested)
{
foreach (var chanel in this.chanels.Values)
{
chanel.Pop();
}
}
}
}
}

View File

@ -21,9 +21,9 @@
return Array.Empty<byte>();
}
internal class AnswerTask : SIRTTask
public class AnswerTask : SIRTTask
{
public AnswerTask() : base(0, 1000)
public AnswerTask() : base(0, 3000)
{
}
@ -38,7 +38,7 @@
}
}
internal static readonly AnswerTask ActivateSIRT = new AnswerTask
public static readonly AnswerTask ActivateSIRT = new AnswerTask
{
Cmd = SIRTMessage.W_REG,
RequestAddress = 0x20000000,

View File

@ -69,7 +69,7 @@
public int Frequency { get; }
public SIRTTaskState State { get; protected set; }
public SIRTTaskState State { get; set; }
public void PushResponse(SIRTMessage response)
{
@ -84,7 +84,7 @@
}
}
public virtual byte[] ToByteArray() => this.request.ToByteArray();
public virtual byte[] ToByteArray() => this.request.GetBytes();
public override string ToString() => BitConverter.ToString(this.ToByteArray());

View File

@ -0,0 +1,584 @@
namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public static class SerialDataExtensions
{
private const int ByteSize = 8;
private const int SByteSize = 16;
private const int Int16Size = 16;
private const int UInt16Size = 16;
private const int Int32Size = 32;
private const int UInt32Size = 32;
private const int Int64Size = 64;
private const int UInt64Size = 64;
public static byte[] GetBitsBE(this byte value)
{
var bits = new byte[ByteSize];
for (int i = 7, x = 0; i >= 0; i--, x++)
{
bits[x] = (byte)((value >> i) & 1);
}
return bits;
}
public static byte[] GetBitsLE(this byte value)
{
var bits = new byte[ByteSize];
for (var i = 0; i < ByteSize; i++)
{
bits[i] = (byte)((value >> i) & 1);
}
return bits;
}
public static byte[] GetBitsLE(this ushort value)
{
var bits = new byte[UInt16Size];
for (var i = 0; i < UInt16Size; i++)
{
bits[i] = (byte)((value >> i) & 1);
}
return bits;
}
public static byte GetByteLE(this byte[] bits)
{
if (bits is null)
{
return default(byte);
}
var value = default(byte);
for (var i = 0; i < ByteSize; i++)
{
value ^= (byte)(bits[i] << i);
}
return value;
}
public static byte GetByteLE(this byte[] bits, int start = 0, int count = 0)
{
if (bits is null)
{
return default(byte);
}
if (count == 0)
{
count = bits.Length;
}
var length = start + count;
var _byte = default(byte);
for (int i = start, x = 0; i < length; i++, x++)
{
_byte ^= (byte)(bits[i] << x);
}
return _byte;
}
public static void SetBitsLE(this byte value, byte[] bits, int start = 0, int count = 0)
{
if (bits is null)
{
return;
}
if (count == 0 || count > bits.Length)
{
count = bits.Length;
}
for (int i = start, x = 0; i < count; i++, x++)
{
bits[i] = (byte)((value >> x) % 2);
}
}
public static byte[] GetBytesBE(this sbyte value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this short value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this int value)
{
var bytes = new byte[4];
var index = 0;
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this long value)
{
var bytes = new byte[8];
var index = 0;
bytes[index++] = (byte)(value >> 56);
bytes[index++] = (byte)(value >> 48);
bytes[index++] = (byte)(value >> 40);
bytes[index++] = (byte)(value >> 32);
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this ushort value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this uint value)
{
var bytes = new byte[4];
var index = 0;
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesBE(this ulong value)
{
var bytes = new byte[8];
var index = 0;
bytes[index++] = (byte)(value >> 56);
bytes[index++] = (byte)(value >> 48);
bytes[index++] = (byte)(value >> 40);
bytes[index++] = (byte)(value >> 32);
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 8);
bytes[index] = (byte)value;
return bytes;
}
public static byte[] GetBytesLE(this sbyte value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)value;
bytes[index] = (byte)(value >> 8);
return bytes;
}
public static byte[] GetBytesLE(this short value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)value;
bytes[index] = (byte)(value >> 8);
return bytes;
}
public static byte[] GetBytesLE(this int value)
{
var bytes = new byte[4];
var index = 0;
bytes[index++] = (byte)value;
bytes[index++] = (byte)(value >> 8);
bytes[index++] = (byte)(value >> 16);
bytes[index] = (byte)(value >> 24);
return bytes;
}
public static byte[] GetBytesLE(this long value)
{
var bytes = new byte[8];
var index = 0;
bytes[index++] = (byte)value;
bytes[index++] = (byte)(value >> 8);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 32);
bytes[index++] = (byte)(value >> 40);
bytes[index++] = (byte)(value >> 48);
bytes[index] = (byte)(value >> 56);
return bytes;
}
public static byte[] GetBytesLE(this ushort value)
{
var bytes = new byte[2];
var index = 0;
bytes[index++] = (byte)value;
bytes[index] = (byte)(value >> 8);
return bytes;
}
public static byte[] GetBytesLE(this uint value)
{
var bytes = new byte[4];
var index = 0;
bytes[index++] = (byte)value;
bytes[index++] = (byte)(value >> 8);
bytes[index++] = (byte)(value >> 16);
bytes[index] = (byte)(value >> 24);
return bytes;
}
public static byte[] GetBytesLE(this ulong value)
{
var bytes = new byte[8];
var index = 0;
bytes[index++] = (byte)value;
bytes[index++] = (byte)(value >> 8);
bytes[index++] = (byte)(value >> 16);
bytes[index++] = (byte)(value >> 24);
bytes[index++] = (byte)(value >> 32);
bytes[index++] = (byte)(value >> 40);
bytes[index++] = (byte)(value >> 48);
bytes[index] = (byte)(value >> 56);
return bytes;
}
public static sbyte ToSByteBE(this byte[] bytes, int start = 0)
{
var value = default(sbyte);
value ^= (sbyte)(bytes[start++] << 8);
value ^= (sbyte)bytes[start];
return value;
}
public static short ToInt16BE(this byte[] bytes, int start = 0)
{
var value = default(short);
value ^= (short)(bytes[start++] << 8);
value ^= bytes[start];
return value;
}
public static int ToInt32BE(this byte[] bytes, int start = 0)
{
var value = default(int);
value ^= bytes[start++] << 24;
value ^= bytes[start++] << 16;
value ^= bytes[start++] << 8;
value ^= bytes[start];
return value;
}
public static long ToInt64BE(this byte[] bytes, int start = 0)
{
var value = default(long);
value ^= bytes[start++] << 56;
value ^= bytes[start++] << 48;
value ^= bytes[start++] << 40;
value ^= bytes[start++] << 32;
value ^= bytes[start++] << 24;
value ^= bytes[start++] << 16;
value ^= bytes[start++] << 8;
value ^= bytes[start];
return value;
}
public static ushort ToUInt16BE(this byte[] bytes, int start = 0)
{
var value = default(ushort);
value ^= (ushort)(bytes[start++] << 8);
value ^= bytes[start];
return value;
}
public static uint ToUInt32BE(this byte[] bytes, int start = 0)
{
var value = default(uint);
value ^= (uint)(bytes[start++] << 24);
value ^= (uint)(bytes[start++] << 16);
value ^= (uint)(bytes[start++] << 8);
value ^= bytes[start];
return value;
}
public static ulong ToUInt64BE(this byte[] bytes, int start = 0)
{
var value = default(ulong);
value ^= (ulong)(bytes[start++] << 56);
value ^= (ulong)(bytes[start++] << 48);
value ^= (ulong)(bytes[start++] << 40);
value ^= (ulong)(bytes[start++] << 32);
value ^= (ulong)(bytes[start++] << 24);
value ^= (ulong)(bytes[start++] << 16);
value ^= (ulong)(bytes[start++] << 8);
value ^= bytes[start];
return value;
}
public static sbyte ToSByteLE(this byte[] bytes, int start = 0)
{
var value = default(sbyte);
value ^= (sbyte)bytes[start++];
value ^= (sbyte)(bytes[start] << 8);
return value;
}
public static short ToInt16LE(this byte[] bytes, int start = 0)
{
var value = default(short);
value ^= bytes[start++];
value ^= (short)(bytes[start] << 8);
return value;
}
public static int ToInt32LE(this byte[] bytes, int start = 0)
{
var value = default(int);
value ^= bytes[start++];
value ^= bytes[start++] << 8;
value ^= bytes[start++] << 16;
value ^= bytes[start] << 24;
return value;
}
public static long ToInt64LE(this byte[] bytes, int start = 0)
{
var value = default(long);
value ^= bytes[start++];
value ^= bytes[start++] << 8;
value ^= bytes[start++] << 16;
value ^= bytes[start++] << 24;
value ^= bytes[start++] << 32;
value ^= bytes[start++] << 40;
value ^= bytes[start++] << 48;
value ^= bytes[start] << 56;
return value;
}
public static ushort ToUInt16LE(this byte[] bytes, int start = 0)
{
var value = default(ushort);
value ^= bytes[start++];
value ^= (ushort)(bytes[start] << 8);
return value;
}
public static ushort ToUIint16LEFromBits(this byte[] bits)
{
const int size = 16;
if (bits is null)
{
bits = new byte[size];
}
Array.Resize(ref bits, size);
ushort value = 0;
for (var i = 0; i < size; i++)
{
value ^= (ushort)(bits[i] << i);
}
return value;
}
public static uint ToUInt32LE(this byte[] bytes, int start = 0)
{
var value = default(uint);
value ^= bytes[start++];
value ^= (uint)(bytes[start++] << 8);
value ^= (uint)(bytes[start++] << 16);
value ^= (uint)(bytes[start] << 24);
return value;
}
public static ulong ToUInt64LE(this byte[] bytes, int start = 0)
{
var value = default(ulong);
value ^= bytes[start++];
value ^= (ulong)(bytes[start++] << 8);
value ^= (ulong)(bytes[start++] << 16);
value ^= (ulong)(bytes[start++] << 24);
value ^= (ulong)(bytes[start++] << 32);
value ^= (ulong)(bytes[start++] << 40);
value ^= (ulong)(bytes[start++] << 48);
value ^= (ulong)(bytes[start] << 56);
return value;
}
public static ushort CRCCCITT(this byte[] bytes, int start = 0, int length = 0)
{
if (length == 0)
{
length = bytes.Length;
}
var crc = (ushort)0xFFFF;
for (var b = start; b < length; b++)
{
var _byte = bytes[b];
var token = (ushort)((_byte << 8) & 0xFF00);
for (var i = 0; i < 8; i++)
{
if (0x8000 == ((crc ^ token) & 0x8000))
{
crc <<= 1;
crc ^= 0x1021;
}
else
{
crc <<= 1;
}
token <<= 1;
}
}
return crc;
}
public static byte[] GetBytes(this string hexString)
{
var bytes = new List<byte>();
if (!string.IsNullOrWhiteSpace(hexString))
{
hexString = Regex.Replace(hexString, "[^a-fA-F0-9]*", string.Empty);
var first = true;
var x = 0;
foreach (var hex in hexString)
{
if ('0' <= hex && hex <= '9')
{
x += hex - '0';
}
else if ('A' <= hex && hex <= 'F')
{
x += hex - 'A' + 10;
}
else if ('a' <= hex && hex <= 'f')
{
x = hex - 'a' + 10;
}
else
{
continue;
}
if (first)
{
x *= 16;
}
else
{
bytes.Add((byte)x);
x = 0;
}
first = !first;
}
}
return bytes.ToArray();
}
public static byte[] GetEncryptionKey(this string hexString, int requiredLength = 16)
{
var bytes = hexString.GetBytes();
if (bytes?.Length != requiredLength)
{
return default(byte[]);
}
return bytes;
}
}
}

View File

@ -0,0 +1,207 @@
namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using SysSerialPort = System.IO.Ports.SerialPort;
public sealed class SerialPort
{
private static readonly ConcurrentDictionary<string, SysSerialPort> serialPorts
= new ConcurrentDictionary<string, SysSerialPort>();
private readonly ManualResetEventSlim readAwaiter;
private readonly ManualResetEventSlim closeAwaiter;
public SerialPort(string name, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
this.COMPort = name;
this.readAwaiter = new ManualResetEventSlim();
this.closeAwaiter = new ManualResetEventSlim();
var sp = new SysSerialPort(this.COMPort, baudRate, parity, dataBits, stopBits);
serialPorts.AddOrUpdate(this.COMPort, sp, (key, value) =>
{
value?.Close();
return sp;
});
}
public event Action Connected;
public event Action Disconnected;
public event Action<string> Logging;
public string COMPort { get; }
public bool IsOpen => serialPorts.TryGetValue(this.COMPort, out var sp) && sp.IsOpen;
public void Close()
{
if (serialPorts.TryGetValue(this.COMPort, out var sp))
{
try
{
sp.Close();
this.closeAwaiter.Wait(5000);
this.closeAwaiter.Reset();
sp.DataReceived -= this.SP_DataReceived;
sp.Disposed -= this.SP_Disposed;
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
}
}
public void Open()
{
if (serialPorts.TryGetValue(this.COMPort, out var sp) && !sp.IsOpen)
{
try
{
sp.DataReceived += this.SP_DataReceived;
sp.Disposed += this.SP_Disposed;
sp.Open();
this.Connected?.Invoke();
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
}
}
public IEnumerable<byte[]> ReadBytes()
{
var sp = this.GetOpenedSP();
var size = sp.ReadBufferSize;
var buffer = new byte[size];
var length = 0;
using (sp)
{
while (sp.IsOpen)
{
this.readAwaiter.Wait();
try
{
buffer = new byte[size];
length = sp.Read(buffer, 0, size);
Array.Resize(ref buffer, length);
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
this.readAwaiter.Reset();
yield return buffer;
}
sp.Close();
}
}
public IEnumerable<string> ReadLines()
{
var sp = this.GetOpenedSP();
var text = default(string);
using (sp)
{
while (sp.IsOpen)
{
this.readAwaiter.Wait();
try
{
text = sp.ReadLine();
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
this.readAwaiter.Reset();
yield return text;
}
}
}
public void Remove()
{
if (serialPorts.TryRemove(this.COMPort, out var sp))
{
sp.Close();
}
}
public void Write(byte[] bytes)
{
var sp = this.GetOpenedSP();
try
{
sp.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
}
public void Write(string text)
{
var sp = this.GetOpenedSP();
try
{
sp.Write(text);
}
catch (Exception e)
{
this.Logging?.Invoke(e.ToString());
}
}
private SysSerialPort GetOpenedSP()
{
if (!serialPorts.TryGetValue(this.COMPort, out var sp))
{
throw new InvalidOperationException($"{nameof(SerialPort)} on {this.COMPort} dose not exists!");
}
if (!sp.IsOpen)
{
this.Close();
this.Open();
}
return sp;
}
private void SP_DataReceived(object _, SerialDataReceivedEventArgs args)
=> this.readAwaiter.Set();
private void SP_Disposed(object _, EventArgs _1)
{
this.closeAwaiter.Set();
this.Disconnected?.Invoke();
}
public static string[] GetPortNames()
=> SysSerialPort.GetPortNames();
}
}

View File

@ -0,0 +1,33 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Json
{
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
public class JsonVersionsConverter : JsonConverter<FwVersion>
{
public override FwVersion ReadJson(JsonReader reader, Type objectType, FwVersion existingValue, Boolean hasExistingValue, JsonSerializer serializer)
{
var jobject = JToken.Load(reader);
if (jobject.Type != JTokenType.Object)
{
if (int.TryParse($"{jobject}", out var version))
{
return new FwVersion
{
First = version
};
}
}
return jobject.ToObject<FwVersion>();
}
public override void WriteJson(JsonWriter writer, FwVersion value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

View File

@ -58,6 +58,7 @@
<ItemGroup>
<Compile Include="Attributes\EregisterFeatureAttribute.cs" />
<Compile Include="Eregister.cs" />
<Compile Include="EregisterChangeMeterTypeTask.cs" />
<Compile Include="EregisterFactory.cs" />
<Compile Include="EregisterCheckFinalizationTask.cs" />
<Compile Include="EregisterCheckInitializationTask.cs" />
@ -157,10 +158,6 @@
<Compile Include="Telegrams\SEMI.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Common.Hardware.Ports\Common.Hardware.Ports.csproj">
<Project>{9ae071c0-db12-4e09-a3c7-43f6dcd518d6}</Project>
<Name>Common.Hardware.Ports</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Common.Hardware.SIRT\Common.Hardware.SIRT.csproj">
<Project>{8de8e742-ee0a-4004-aa49-3d08d748e5ac}</Project>
<Name>Common.Hardware.SIRT</Name>

View File

@ -7,7 +7,9 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
public class Eregister
@ -33,6 +35,35 @@
}
}
internal IEnumerable<EregisterTask> LoadInspectionInitializationTasks()
{
var features = parameters.LoadInspectionInitializationFeatures();
this.LoadProgrammingParameters(features);
var lastTask = this.runningTasks.LastOrDefault();
if (lastTask != null)
{
this.runningTasks.Enqueue(new EregisterChangeMeterTypeTask(lastTask.Frequency, lastTask.Timeout)
{
SlotNr = features.SlotNr,
PoNr = features.PoNr,
SerialNr = features.SerialNr,
P1 = new P811
{
DelPamSemi = true,
},
RequestAddress = features.RequestAddress,
ResponseAddress = features.ResponseAddress,
EncryptionKey = features.EncryptionKey,
Name = "Change Meter Type"
});
}
return this.runningTasks.AsEnumerable();
}
internal IEnumerable<EregisterTask> LoadInspectionFinalizationTasks()
{
var features = parameters.LoadInspectionFinalizationFeatures();
@ -56,15 +87,6 @@
return this.runningTasks.AsEnumerable();
}
internal IEnumerable<EregisterTask> LoadInspectionInitializationTasks()
{
var features = parameters.LoadInspectionInitializationFeatures();
this.LoadProgrammingParameters(features);
return this.runningTasks.AsEnumerable();
}
internal void StartProgramming()
{
var manualResetEventSlim = new ManualResetEventSlim();
@ -76,6 +98,9 @@
if (task is EregisterTask _task)
{
var numberStyles = NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier;
var cultureInfo = CultureInfo.InvariantCulture;
foreach (var etask in this.runningTasks)
{
if (etask.State != SIRTTaskState.Cancelled && etask.State != SIRTTaskState.Completed)
@ -85,6 +110,16 @@
etask.RequestAddress = _task.RequestAddress;
etask.ResponseAddress = _task.ResponseAddress;
}
if (etask.RadioFWVersion is null)
{
etask.RadioFWHex = _task.DEBUG?.RadioFWVersion;
if (int.TryParse($"{etask.RadioFWHex}", numberStyles, cultureInfo, out var radioFWVersion))
{
etask.RadioFWVersion = radioFWVersion;
}
}
}
}
@ -112,7 +147,7 @@
}
}
private void LoadProgrammingParameters(EregisterFeatures features)
private void LoadProgrammingParameters(EregisterFeatures features, [CallerMemberName] string caller = "")
{
this.Clear();

View File

@ -0,0 +1,40 @@
namespace Common.Hardware.WaterMeter.eRegister
{
using System;
using System.Globalization;
public class EregisterChangeMeterTypeTask : EregisterTask
{
public EregisterChangeMeterTypeTask(int frequency, int timeout = 5000) : base(frequency, timeout)
=> this.Name = "Change meter type";
public override byte[] ToByteArray()
{
var numberStyles = NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier;
var cultureInfo = CultureInfo.InvariantCulture;
// from Pruef2000.exe
if (int.TryParse($"1108", numberStyles, cultureInfo, out var minFWVersion) && int.TryParse($"110B", numberStyles, cultureInfo, out var exceptFWVersion))
{
if (this.RadioFWVersion < minFWVersion && this.RadioFWVersion != exceptFWVersion)
{
// do not change the type
this.request.Data = Array.Empty<byte>();
}
}
if (this.request.Data.Length > 0)
{
this.Name = $"FW: {this.RadioFWHex} - C & I";
}
else
{
this.Name = $"FW: {this.RadioFWHex} - Residential";
}
this.NotifyChanged();
return base.ToByteArray();
}
}
}

View File

@ -1,6 +1,5 @@
namespace Common.Hardware.WaterMeter.eRegister
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.WaterMeter.eRegister.Attributes;
using Common.Hardware.WaterMeter.eRegister.Features;

View File

@ -19,7 +19,6 @@
this.parameters = parameters;
this.pendingState = SIRTTaskState.Completed;
this.Name = "Initial Check";
this.Data = new OpticalTelegram
{
Minutes = 0
@ -99,10 +98,7 @@
message.AppendLine();
message.AppendLine("Möchten Sie mit die Prüfung fortfahren (Yes), oder Abbrechen (No)?");
var result = MessageBox.Show(
message.ToString()
, $"Fehler bei der Prüfungsinitialisierung"
, MessageBoxButtons.YesNo);
var result = MessageBox.Show(message.ToString(), $"Fehler bei der Prüfungsinitialisierung", MessageBoxButtons.YesNo);
if (result == DialogResult.No)
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.WaterMeter.eRegister.Features;
using Common.Hardware.WaterMeter.eRegister.Models;

View File

@ -56,6 +56,10 @@
public FactoryState Mode { get; set; }
public int? RadioFWVersion { get; set; }
public string RadioFWHex { get; set; }
public override byte[] ToByteArray()
{
var data = this.request.Data;
@ -78,7 +82,7 @@
P1 = this.request.P1,
P2 = this.request.P2,
}.ToByteArray();
}.GetBytes();
}
protected override void OnTimeout(object sender, ElapsedEventArgs e)
@ -149,19 +153,25 @@
{
this.SEMI = new SEMI(data, this.Frequency, this.P11);
this.IsEncrypted = this.SEMI.Crc != 0;
this.Label = this.SEMI.PAMStatus.ToString();
this.Label = default(string);
if (this.request.Data.Length > 0 && this.request.Data[0] == Pam.GetDebug && this.DEBUG == null)
if (this.SEMI.PAMStatus == PAMStatus.OK)
{
this.Label = "!DEBUG";
}
else if (this.SEMI.PAMStatus == PAMStatus.OK)
{
this.State = SIRTTaskState.Completed;
this.EndProcessResponse(response);
if (this.request.Data.Length > 0 && this.request.Data[0] == Pam.GetDebug && this.DEBUG == null)
{
this.Label = "!DEBUG";
}
else
{
this.State = SIRTTaskState.Completed;
this.Label = this.SEMI.PAMStatus.ToString();
this.EndProcessResponse(response);
}
}
else
{
this.Label = this.SEMI.PAMStatus.ToString();
if (this.SEMI.PAMStatus == PAMStatus.EXPIREDAUTH)
{
this.State = SIRTTaskState.Cancelled;

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ActivateMetrologyTestMode : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class AlarmsMask : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeDataLoggerSettings : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeFixedDateReadingSettings : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeMeterId : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeMeterReading : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeRadioId : Pam
{

View File

@ -2,7 +2,7 @@
{
using System;
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ChangeSensusRFEncryptionKey : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class OpenMeteringTransmitionIntervalWMBus : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class ParameterizeLeakageDetection : SingleBytePam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SendBubbleUpBurst : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetAlarms : AlarmsMask
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetBytterySeconds : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetDateAndTime : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetFrequencyOffset : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetMetrologyParameters : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetPcbId : Pam
{

View File

@ -2,7 +2,7 @@
{
using System;
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class SetTFXParameters : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
public class WirelessMBusMode : Pam
{

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Models
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.WaterMeter.eRegister.Attributes;
using Common.Hardware.WaterMeter.eRegister.Features;
using Common.Hardware.WaterMeter.eRegister.Telegrams;
@ -434,15 +434,6 @@
Vpp = this.VolumePerPulse,
VppLED = (uint)this.VolumePerLedPulse
};
features.Debug = new EregisterDebugFeatures
{
SetMeterType = new SetMeterType
{
Type = (MeterTypes)this.CandIType
},
};
}
return features;

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Telegrams
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.SIRT.Parameters;
using Common.Hardware.WaterMeter.eRegister.Features;

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Telegrams
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.SIRT.Parameters;
public class DEBUG : Payload

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Telegrams
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.SIRT.Parameters;
using System;

View File

@ -1,6 +1,6 @@
namespace Common.Hardware.WaterMeter.eRegister.Telegrams
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.Hardware.SIRT.Parameters;
using Common.Hardware.WaterMeter.eRegister.Features;

@ -1 +1 @@
Subproject commit fc6d1c60141d1dcce304443fe14f62a94e9dc123
Subproject commit 1713caf91ba8771f7331a878005598ef8c47d263

View File

@ -6,7 +6,7 @@
<appSettings>
<add key="ConnectionString" value="Server=SLASQL01.emea.sensus.net; Database=Auftrag; User ID=sa; Password=sqlserver;" />
<add key="EncryptionKeisUrl" value="http://sla12iis01.emea.sensus.net/LaaProductionWeb/api/eregister/radiokey/byserialno/{0}" />
<add key="SIRTComPorts" value="COM6, COM8" />
<add key="SIRTComPorts" value="COM6,COM8" />
<add key="PSNR" value="1" />
</appSettings>
<runtime>

View File

@ -151,7 +151,6 @@
<Compile Include="Models\Eregister_Shared.cs" />
<Compile Include="Models\HttpContext.cs" />
<Compile Include="Models\P2000_Shared.cs" />
<Compile Include="Models\SIRTFactoryModel.cs" />
<Compile Include="Pages\EregisterFinalize.xaml.cs">
<DependentUpon>EregisterFinalize.xaml</DependentUpon>
</Compile>
@ -279,10 +278,6 @@
<Resource Include="ILLink\ILLink.Descriptors.LibraryBuild.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Hardware\Common.Hardware.Ports\Common.Hardware.Ports.csproj">
<Project>{9ae071c0-db12-4e09-a3c7-43f6dcd518d6}</Project>
<Name>Common.Hardware.Ports</Name>
</ProjectReference>
<ProjectReference Include="..\..\Hardware\Common.Hardware.SIRT\Common.Hardware.SIRT.csproj">
<Project>{8de8e742-ee0a-4004-aa49-3d08d748e5ac}</Project>
<Name>Common.Hardware.SIRT</Name>

View File

@ -5,91 +5,47 @@
<Grid.DataContext>
<vm:SIRTBroadcasterVM />
</Grid.DataContext>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border BorderBrush="Gray"
BorderThickness="0, 0, 1, 1"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ComboBox Grid.Row="0"
IsEnabled="{Binding ComPortsEnabled}"
ItemsSource="{Binding PortNames}"
Margin="5, 5, 5, 0"
Padding="5, 3, 0, 3"
SelectedItem="{Binding PortName}"
Width="100"/>
<Button Command="{Binding AddSIRTCommand}"
Content="Add SIRT"
Grid.Row="1"
IsEnabled="{Binding AddEnabled}"
Margin="5, 5, 5, 0"
Padding="20, 3"
Width="100" />
<Button Command="{Binding ClearAllCommand}"
Content="Clear all"
Grid.Row="2"
IsEnabled="{Binding ClearEnabled}"
Margin="5, 5, 5, 5"
Padding="20, 3"
Width="100" />
<Border BorderBrush="Gray" BorderThickness="0, 0, 0, 1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ItemsControl Grid.Column="0" ItemsSource="{Binding Connections}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:SIRTConnectionVM}">
<Border BorderBrush="DimGray"
BorderThickness="0 0 1 0">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding PortName}" Margin="0 0 0 0" Padding="0 5" FontWeight="Bold" />
<Label Grid.Column="1" Content="-" Margin="5 0 0 0" Padding="0 5" />
<Label Grid.Column="2" Content="{Binding HexId}" Margin="5 0 0 0" Padding="0 5" FontWeight="Bold" />
<Label Grid.Column="3" Content="-" Margin="5 0 0 0" Padding="0 5" />
<Label Grid.Column="4" Content="{Binding Frequency}" Margin="5 0 0 0" Padding="0 5" FontWeight="Bold" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Column="1"
Content="Refresh connections"
Command="{Binding AddSIRTsCommand}"
Padding="20 5"
Cursor="Hand"
Margin="5"
VerticalAlignment="Center"/>
</Grid>
</Border>
<Border BorderBrush="Gray"
BorderThickness="0, 0, 0, 1"
Grid.Column="1"
Grid.Row="0"
Grid.RowSpan="2"
HorizontalAlignment="Stretch"
IsEnabled="{Binding ComPortsEnabled}"
VerticalAlignment="Stretch">
<ItemsControl ItemsSource="{Binding Connections}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:SIRTConnectionVM}">
<Grid Margin="0, 0, 5, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Background="WhiteSmoke" Grid.Column="0" Content="{Binding PortName}" Margin="5, 5, 5, 0" VerticalAlignment="Stretch" />
<Label Background="WhiteSmoke" Grid.Column="1" Content="{Binding HexId}" Margin="0, 5, 5, 0" VerticalAlignment="Stretch" />
<Label Background="WhiteSmoke" Grid.Column="2" Content="{Binding Frequency}" Margin="0, 5, 5, 0" VerticalAlignment="Stretch" />
<Label Background="WhiteSmoke" Grid.Column="3" Content="{Binding IsRunning}" Margin="0, 5, 5, 0" VerticalAlignment="Stretch" />
<Button Content="Reconnect"
Command="{Binding ReconnectCommand}"
Grid.Column="4"
IsEnabled="{Binding ReconnectEnabled}"
Margin="0, 5, 5, 0"
Padding="20, 3" />
<Button Content="Disconnect"
Command="{Binding DisconnectCommand}"
Grid.Column="5"
IsEnabled="{Binding DisconnectEnabled}"
Margin="0, 5, 5, 0"
Padding="10, 3" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</Grid>

View File

@ -24,7 +24,7 @@
serviceCollection
.AddScoped<DeviceManager>()
.AddScoped(CreateNLogger)
.AddScoped<SIRTFactory>()
.AddSingleton<SIRTFactory>()
.AddTransient<HomeModel>()
.AddTransient<SettingsModel>();

View File

@ -2,6 +2,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ShowsNavigationUI="False"
Source="Pages/EregisterManualProgramming.xaml"
Source="Pages/Home.xaml"
Title="TestBench UI">
</NavigationWindow>

View File

@ -1,42 +0,0 @@
namespace Common.UI.Models
{
using System;
using Common.Hardware.SIRT;
using NLog;
public class SIRTFactoryModel
{
private readonly SIRTFactory sirtFactory;
private readonly ILogger logger;
public SIRTFactoryModel(SIRTFactory sirtFactory, ILogger logger)
{
this.logger = logger;
this.sirtFactory = sirtFactory;
this.sirtFactory.Logging += this.SirtFactory_Logging;
}
internal Action<SIRTTask> EnqueueAction => this.sirtFactory.EnqueueTask;
internal void Initialize(string portNamesString, Action<SIRTBroadcaster> connecting)
{
var portNames = portNamesString
?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?? Array.Empty<string>();
foreach (var portName in portNames)
{
this.sirtFactory.ConnectSIRT(portName, connecting);
}
}
private void SirtFactory_Logging(string content)
=> this.logger.Debug(content);
internal void DisconnectAll() => this.sirtFactory.CloseConnections();
public static implicit operator SIRTFactory (SIRTFactoryModel model) => model?.sirtFactory;
}
}

View File

@ -3,18 +3,21 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Common.UI.Controls"
xmlns:VM="clr-namespace:Common.UI.ViewModels"
WindowTitle="TestBench UI / Eregister finalize">
WindowTitle="TestBench UI / Eregister finalize"
FontFamily="Consolas">
<Page.DataContext>
<VM:EregisterFinalizeVM />
</Page.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Controls:SIRTBroadcasters Grid.Row="0" />
<ScrollViewer Grid.Row="1"
<Controls:MainMenu Background="#FFF0F0F0" Grid.Row="0" />
<Controls:SIRTBroadcasters Background="#FFF0F0F0" Grid.Row="1" />
<ScrollViewer Grid.Row="2"
HorizontalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalAlignment="Stretch"
@ -23,7 +26,7 @@
</ScrollViewer>
<Border BorderBrush="#FFF0F0F0"
BorderThickness="0, 1, 0, 0"
Grid.Row="2" >
Grid.Row="3" >
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content="Start Programming"
Command="{Binding StartProgrammingCommand}"

View File

@ -3,18 +3,21 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Common.UI.Controls"
xmlns:VM="clr-namespace:Common.UI.ViewModels"
WindowTitle="TestBench UI / Eregister initialize">
WindowTitle="TestBench UI / Eregister initialize"
FontFamily="Consolas">
<Page.DataContext>
<VM:EregisterInitializeVM />
</Page.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Controls:SIRTBroadcasters Background="#FFF0F0F0" Grid.Row="0" />
<ScrollViewer Grid.Row="1"
<Controls:MainMenu Background="#FFF0F0F0" Grid.Row="0" />
<Controls:SIRTBroadcasters Background="#FFF0F0F0" Grid.Row="1" />
<ScrollViewer Grid.Row="2"
HorizontalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalAlignment="Stretch"
@ -23,7 +26,7 @@
</ScrollViewer>
<Border BorderBrush="Gray"
BorderThickness="0, 1, 0, 0"
Grid.Row="2" >
Grid.Row="3" >
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content="Start Programming"
Command="{Binding StartProgrammingCommand}"
@ -31,19 +34,19 @@
HorizontalAlignment="Left"
IsEnabled="{Binding StartEnabled}"
Margin="0, 0, 5, 0"
Padding="20, 3"/>
Padding="20, 5"/>
<Button Content="Stop Programming"
Command="{Binding StopProgrammingCommand}"
Grid.Row="2"
HorizontalAlignment="Left"
IsEnabled="{Binding StopEnabled}"
Margin="0, 0, 5, 0"
Padding="20, 3"/>
Padding="20, 5"/>
<Label FontWeight="Bold"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Margin="0"
Padding="10, 0"
Padding="20, 5"
Content="{Binding TimeElapsed}"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center" />

View File

@ -46,7 +46,6 @@
this.sirtFactory = AppHost.GetService<SIRTFactory>();
this.sirtFactory.Logging += x => this.logger.Debug(x);
this.eregisterFactory = new EregisterFactory(this.sirtFactory);
this.ProgrammingTasks = new ObservableCollection<EregisterTaskVM>();
this.StartProgrammingCommand = new Command(this.StartProgrammingCommandHandler);
this.StopProgrammingCommand = new Command(this.StopProgrammingCommandHandler);
this.StartEnabled = true;
@ -76,13 +75,8 @@
public ICommand StartProgrammingCommand { get; }
public ICommand StopProgrammingCommand { get; }
private IEnumerable<GridItem> programmingTasks;
public IEnumerable<GridItem> ProgrammingTasks
{
get => this.programmingTasks;
set => this.Set(vm => vm.programmingTasks = value);
}
public IEnumerable<GridItem> ProgrammingTasks { get; set; }
internal override void ViewModel_Loaded(object data)
{
@ -93,8 +87,6 @@
this.sharedId = AuftragDbContext.P2000Shared.LoadPendingAction(psnr)?.Id ?? 0;
}
}
Task.Run(async () => await this.PrepareProgrammingAsync(this.eregisterFactory.LoadInspectionInitializationTasks));
}
private void StartProgrammingCommandHandler()
@ -106,20 +98,16 @@
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
this.programmingTask = Task
.Run(async () =>
.Run(() =>
{
await this.PrepareProgrammingAsync();
await this.eregisterFactory.StartProgrammingAsync(this.cancellationToken);
})
.ContinueWith(_ =>
{
this.timer.Stop();
this.StartEnabled = true;
this.StopEnabled = false;
this.PrepareProgrammingAsync(this.eregisterFactory.LoadInspectionInitializationTasks)
.Wait();
this.timer.Start();
this.eregisterFactory
.StartProgrammingAsync(this.cancellationToken)
.Wait();
this.StopProgrammingCommandHandler();
});
this.timer.Start();
}
private void StopProgrammingCommandHandler()
@ -239,7 +227,11 @@
row = 1;
}
this.ProgrammingTasks = tasks;
this.InvokeAsync(() =>
{
this.ProgrammingTasks = tasks;
this.NotifyPropertyChanged(nameof(this.ProgrammingTasks));
});
}
}
}

View File

@ -1,187 +1,64 @@
namespace Common.UI.ViewModels
{
using Common.Hardware.Ports;
using Common.Hardware.SIRT;
using Common.UI.Infrastructure;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
internal class SIRTBroadcasterVM : ViewModel<SIRTBroadcasterVM>
{
private readonly SIRTFactory broadcaster;
private readonly ManagementEventWatcher comWatcher;
private readonly SIRTFactory sirtFactory;
public SIRTBroadcasterVM()
{
this.broadcaster = AppHost.GetService<SIRTFactory>();
this.sirtFactory = AppHost.GetService<SIRTFactory>();
this.Connections = new ObservableCollection<SIRTConnectionVM>();
this.PortNames = new ObservableCollection<string>();
this.AddSIRTCommand = new Command(this.AddSIRTConnectionCommandHandler);
this.ClearAllCommand = new Command(this.ClearAllCommandHandler);
this.comWatcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent");
this.comWatcher.EventArrived += (_, args) => this.UpdatePortNames();
this.comWatcher.Start();
this.AddSIRTsCommand = new Command(this.AddSIRTs);
//TODO: not needed hier
//private readonly ManagementEventWatcher comWatcher;
//this.comWatcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent");
//this.comWatcher.EventArrived += (_, args) => this.UpdatePortNames();
//this.comWatcher.Start();
this.AddSIRTs();
this.UpdatePortNames();
}
private bool comPortsEnabled;
public bool ComPortsEnabled
{
get => this.comPortsEnabled;
set => this.Set(vm => vm.comPortsEnabled = value);
}
private bool addEnabled;
public bool AddEnabled
{
get => this.addEnabled;
set => this.Set(vm => vm.addEnabled = value);
}
private bool cleanEnabled;
public bool ClearEnabled
{
get => this.cleanEnabled;
set => this.Set(vm => vm.cleanEnabled = value);
}
private string portName;
public string PortName
{
get => this.portName;
set
{
this.Set(vm => vm.portName = value);
this.AddEnabled = !string.IsNullOrWhiteSpace(value);
}
}
public Action InvokeWhenReady { get; set; }
public ICommand AddSIRTCommand { get; }
public ICommand ClearAllCommand { get; }
public ObservableCollection<string> PortNames { get; }
public ICommand AddSIRTsCommand { get; }
public ObservableCollection<SIRTConnectionVM> Connections { get; }
private void AddSIRTConnectionCommandHandler()
{
if (!string.IsNullOrWhiteSpace(this.PortName))
{
Task.Run(() =>
{
this.broadcaster.ConnectSIRT(this.PortName, broadcaster =>
{
var broadcasterVM = new SIRTConnectionVM(broadcaster);
broadcasterVM.Removed += this.RemoveSIRTConnectionVM;
this.InvokeAsync(() =>
{
this.Connections.Add(broadcasterVM);
});
});
this.ClearEnabled = true;
this.PortName = default(string);
this.UpdatePortNames();
});
}
}
private void ClearAllCommandHandler()
{
this.ComPortsEnabled = false;
this.ClearEnabled = false;
Task.Run(() =>
{
this.broadcaster.RemoveConnections();
this.InvokeAsync(this.Connections.Clear);
this.UpdatePortNames();
});
}
private void RemoveSIRTConnectionVM(SIRTConnectionVM connectionVM)
{
this.ComPortsEnabled = false;
this.ClearEnabled = false;
Task.Run(() =>
{
this.broadcaster.CloseConnection(connectionVM.PortName);
})
.ContinueWith(_ =>
{
this.InvokeAsync(() =>
{
this.Connections.Remove(connectionVM);
});
this.UpdatePortNames();
});
}
private void AddSIRTs()
{
Task.Run(async () =>
Task.Run(() =>
{
var portNames = Appsettings
.Get("SIRTComPorts")
?.Split(new[] { ';', ',', ' ' })
?.Select(x => x?.Trim())
?.ToArray() ?? new string[0];
portNames = SerialPort
.GetPortNames()
.Intersect(portNames)
.ToArray();
foreach (var portName in portNames)
this.InvokeAsync(() =>
{
this.broadcaster.ConnectSIRT(portName, broadcaster =>
var portNames = Appsettings
.Get("SIRTComPorts")
?.Split(new[] { ';', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?.Select(x => x?.Trim())
?.ToArray() ?? new string[0];
this.sirtFactory.RemoveConnections();
this.Connections.Clear();
foreach (var portName in portNames)
{
var broadcasterVM = new SIRTConnectionVM(broadcaster);
broadcasterVM.Removed += this.RemoveSIRTConnectionVM;
this.InvokeAsync(() =>
this.sirtFactory.ConnectSIRT(portName, sirt =>
{
this.Connections.Add(broadcasterVM);
this.Connections.Add(new SIRTConnectionVM(sirt));
});
});
this.ClearEnabled = true;
await Task.Delay(500);
}
Thread.Sleep(300);
}
});
});
}
private void UpdatePortNames()
=> this.InvokeAsync(() =>
{
this.PortNames.Clear();
var portNames = SerialPort
.GetPortNames()
.Except(this.broadcaster.GetPortNames())
.OrderBy(x => x);
foreach (var portName in portNames)
{
this.PortNames.Add(portName);
}
this.ComPortsEnabled = true;
});
}
}

View File

@ -9,10 +9,13 @@
internal class SIRTConnectionVM : ViewModel<SIRTConnectionVM>
{
private static int count;
private readonly SIRTBroadcaster connection;
public SIRTConnectionVM(SIRTBroadcaster connection)
{
this.Id = ++count;
this.connection = connection;
this.connection.Activated += this.SIRTBroadcaster_Activated;
this.connection.Connected += this.SIRTBroadcaster_Connected;
@ -26,6 +29,8 @@
public event Action<SIRTConnectionVM> Removed;
public int Id { get; }
private string portName;
public string PortName
{
@ -81,59 +86,71 @@
public ICommand RemoveCommand { get; }
private void RemoveCommand_Handler()
{
this.Removed?.Invoke(this);
}
private void RemoveCommand_Handler()
=> this.Removed?.Invoke(this);
private void DisconnectCommand_Handler()
{
this.DisconnectEnabled = false;
this.ReconnectEnabled = false;
this.RemoveEnabled = false;
this.IsRunning = null;
this.InvokeAsync(() =>
{
this.DisconnectEnabled = false;
this.ReconnectEnabled = false;
this.RemoveEnabled = false;
this.IsRunning = null;
});
Task.Run((Action)this.connection.Close);
}
private void ReconnectCommand_Handler()
{
this.DisconnectEnabled = false;
this.ReconnectEnabled = false;
this.RemoveEnabled = false;
this.IsRunning = null;
Task.Run(() =>
this.InvokeAsync(() =>
{
this.connection.Close();
this.connection.Open();
this.DisconnectEnabled = false;
this.ReconnectEnabled = false;
this.RemoveEnabled = false;
this.IsRunning = null;
});
Task.Run((Action)this.connection.Open);
}
private void SIRTBroadcaster_Activated()
{
this.DisconnectEnabled = true;
this.ReconnectEnabled = false;
this.RemoveEnabled = true;
this.IsRunning = "Activated";
this.InvokeAsync(() =>
{
this.DisconnectEnabled = true;
this.ReconnectEnabled = false;
this.RemoveEnabled = true;
this.IsRunning = "Activated";
});
this.UpdateState(this.connection);
}
private void SIRTBroadcaster_Connected()
{
this.DisconnectEnabled = true;
this.ReconnectEnabled = false;
this.RemoveEnabled = true;
this.IsRunning = "Connected";
this.InvokeAsync(() =>
{
this.DisconnectEnabled = true;
this.ReconnectEnabled = false;
this.RemoveEnabled = true;
this.IsRunning = "Connected";
});
this.UpdateState(this.connection);
}
private void SIRTBroadcaster_Disconnected()
{
this.DisconnectEnabled = false;
this.ReconnectEnabled = true;
this.RemoveEnabled = true;
this.IsRunning = "Disconnected";
this.InvokeAsync(() =>
{
this.DisconnectEnabled = false;
this.ReconnectEnabled = true;
this.RemoveEnabled = true;
this.IsRunning = "Disconnected";
});
this.UpdateState(this.connection);
}
@ -144,6 +161,10 @@
this.PortName = connection.COMPort;
this.HexId = connection.HexId;
this.Frequency = $"{connection.Frequency}MHz";
this.DisconnectEnabled = this.disconnectEnabled;
this.ReconnectEnabled = this.reconnectEnabled;
this.RemoveEnabled = this.removeEnabled;
this.IsRunning = this.running;
});
}
}