OMNI: 01-16 - tests on 2020

This commit is contained in:
Stoyan Zlatev
2024-01-16 16:06:10 +01:00
parent a05e490ef3
commit 95565a0add
63 changed files with 1545 additions and 5816 deletions
@@ -0,0 +1,9 @@
<Window x:Class="OMNIPruefung.EOLWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="450"
Width="800">
<DataGrid Background="White" HeadersVisibility="None" >
</DataGrid>
</Window>
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace OMNIPruefung
{
/// <summary>
/// Interaction logic for EOLWindow.xaml
/// </summary>
public partial class EOLWindow : Window
{
public EOLWindow()
{
InitializeComponent();
}
}
}
+1 -2
View File
@@ -12,7 +12,7 @@
<ContentVM:MainContentVM />
</Window.DataContext>
<Grid Margin="0, 3, 0, 0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="230" />
<ColumnDefinition Width="Auto" />
@@ -43,6 +43,5 @@
HorizontalAlignment="Stretch"
Background="White"/>
</DockPanel>
</Grid>
</Window>
@@ -57,30 +57,25 @@
public string PSNR => this[nameof(PSNR)];
public IEnumerable<string> AllKeys => appsettings.AllKeys;
}
public class ExchangeHubSettings : Appsettings
{
public string ExchangeHubURL
{
get => base[nameof(this.ExchangeHubURL)];
set => base[nameof(this.ExchangeHubURL)] = value;
get => this[nameof(this.ExchangeHubURL)];
set => this[nameof(this.ExchangeHubURL)] = value;
}
public string ExchangeHubOutputDir
{
get => base[nameof(this.ExchangeHubOutputDir)];
set => base[nameof(this.ExchangeHubOutputDir)] = value;
get => this[nameof(this.ExchangeHubOutputDir)];
set => this[nameof(this.ExchangeHubOutputDir)] = value;
}
}
public class EOLSettings : Appsettings
{
public IEnumerable<string> COMPorts
=> this[nameof(COMPorts)]
?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?? new string[] { };
internal COMPorts COMPorts
=> new COMPorts(this[nameof(COMPorts)]
?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?? new string[] { });
public string OmniDB => this[nameof(OmniDB)];
internal static readonly Appsettings Current = new Appsettings();
}
}
@@ -0,0 +1,37 @@
namespace OMNIPruefung.Models
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO.Ports;
internal class COMPorts : IEnumerable<string>
{
private readonly string[] comports;
private readonly string[] existing;
public COMPorts(string[] comports)
{
this.comports = comports;
this.existing = SerialPort.GetPortNames();
}
public bool Exists(string portName)
{
return Array.IndexOf(this.existing, portName) >= 0;
}
public IEnumerator<string> GetEnumerator()
{
foreach (var portName in this.comports)
{
yield return portName;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
@@ -0,0 +1,27 @@
namespace OMNIPruefung.Models
{
using OmniPlus;
public class EOLContentM
{
private readonly OmniIrdaEOL eol;
public EOLContentM()
{
this.eol = new OmniIrdaEOL(Appsettings.Current.OmniDB);
}
public void Load()
{
//var comports = new COMPorts();
//foreach (var portName in comports)
//{
// if (comports.Exists(portName))
// {
// this.eol.AddConnection(portName);
// }
//}
}
}
}
@@ -57,9 +57,14 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="EOLWindow.xaml.cs">
<DependentUpon>EOLWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Helpers\BooleanProgressBackgroundConverter.cs" />
<Compile Include="Helpers\BooleanVisibilityConverter.cs" />
<Compile Include="Models\Appsettings.cs" />
<Compile Include="Models\COMPorts.cs" />
<Compile Include="Models\EOLContentM.cs" />
<Compile Include="ViewModels\Content\SettingsContentVM.cs" />
<Compile Include="ViewModels\Features\OMNIPlusVM.cs" />
<Compile Include="ViewModels\Base\Command.cs" />
@@ -93,6 +98,10 @@
<Compile Include="Views\Options\Option.xaml.cs">
<DependentUpon>Option.xaml</DependentUpon>
</Compile>
<Page Include="EOLWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -18,10 +17,10 @@
public class COMContentVM : ContentVM
{
private readonly Dictionary<OmniPlusTestPoint, OmniPlusTest> results
= new Dictionary<OmniPlusTestPoint, OmniPlusTest>();
private readonly IDictionary<OmniPlusTestPoint, OmniPlusTest> results
= new SortedDictionary<OmniPlusTestPoint, OmniPlusTest>();
private OmniPlusConnection connection;
private OmniConnection connection;
public COMContentVM() : base()
{
@@ -30,6 +29,31 @@
this.Option.OptionSelected += this.NotifyOptionSelected;
}
private int nr;
public int Nr
{
get => this.nr;
set
{
this.nr = value;
this.NotifyPropertyChanged(nameof(this.Nr));
}
}
private string portName;
public string PortName
{
get => this.portName;
set
{
this.portName = value;
this.connection = new OmniIrdaConnection(value);
this.NotifyPropertyChanged(nameof(this.PortName));
}
}
private int progress;
public int Progress
{
@@ -90,43 +114,6 @@
}
}
private int nr;
public int Nr
{
get => this.nr;
set
{
this.nr = value;
this.NotifyPropertyChanged(nameof(this.Nr));
}
}
private string portName;
public string PortName
{
get => this.portName;
set
{
this.portName = value;
this.connection = new OmniPlusConnection(value);
this.NotifyPropertyChanged(nameof(this.PortName));
}
}
private string testResults;
public string TestResults
{
get => this.testResults;
set
{
this.testResults = value;
this.NotifyPropertyChanged(nameof(this.TestResults));
}
}
public OMNIPlusVM Meter { get; }
internal void CancelExecution()
@@ -149,39 +136,35 @@
this.Header = $"{this.PortName}";
this.State = this.Header;
this.State = $"{this.Header} - wird ermittelt ...";
try
{
this.Connected = this.connection.Connected;
this.connection.Open();
if (!this.Connected)
{
this.Connected = this.connection.ConnectIrda();
this.Running = this.Connected;
}
this.Connected = true;
this.Running = true;
if (this.IsRunning())
{
this.State = "Verbunden";
this.Header = $"{this.PortName}";
this.State = $"{this.PortName} verbunden";
}
else
{
this.connection.Disconnect();
this.connection.Close();
this.Header = $"({this.PortName} - nicht verbunden!)";
this.Header = $"{this.PortName} - nicht verbunden!";
this.State = this.Header;
}
}
catch (Exception e)
{
this.connection.Disconnect();
this.Header = $"({this.PortName} - nicht vorhanden!)";
this.connection.Close();
this.Header = $"({this.PortName} - {e.Message}!)";
this.State = this.Header;
}
}
return this.StartNew(Initialize, cancellationToken);
return Task.Factory.StartNew(Initialize, cancellationToken);
}
internal Task ReadSystemParametersAsync(CancellationToken cancelationToken)
@@ -193,30 +176,15 @@
if (this.IsRunning())
{
var response = this.connection.ViewSystemParameters();
this.Running = response.IsValid;
this.Header = response.BuildInfo.Value;
this.Progress += 10;
this.Meter.Add(response);
this.Header = response.BuildInfo.Value;
this.Running = response.IsValid;
if (this.Running)
{
this.State = "Systemeigenschaften gelesen und validiert";
}
else
{
this.State = "Systemeigenschaften konnten nicht gelesen werden";
}
this.Progress += 10;
}
else
{
this.State += $" (Verbindung unterbrochen)";
}
}
return this.StartNew(ReadSystemParameters, cancelationToken);
return Task.Factory.StartNew(ReadSystemParameters, cancelationToken);
}
internal Task SetInputVolumeAsync(OmniPlusType defaults, CancellationToken cancelationToken)
@@ -225,37 +193,32 @@
void SetInputVolume()
{
if (this.Connected)
if (this.IsRunning())
{
var response = this.connection.Set(defaults.InputVolume);
this.Running = response.Succeeded;
this.Progress += 10;
if (this.Running)
{
this.Meter.Add(defaults.InputVolume);
this.State = "Flow-Eigenschaften konfiguriert";
this.State = $"{this.Header}";
}
else
{
this.State = $"Flow-Eigenschaften: ({(int)response.Status} - {response.Status})";
this.State = $"{this.Header} - {response.Status}";
}
this.Progress += 10;
}
else
{
this.State += $" (Verbindung unterbrochen)";
}
}
return this.StartNew(SetInputVolume, cancelationToken);
return Task.Factory.StartNew(SetInputVolume, cancelationToken);
}
internal Task StartPPCalibrationAsync(OmniPlusTestPoint pp, CancellationToken cancellationToken)
{
cancellationToken.Register(this.CancelExecution);
void StartPPCalibration()
{
this.results[pp] = new OmniPlusTest();
@@ -264,84 +227,69 @@
{
var rotations = pp.Rotations;
var duration = pp.Duration;
var activationResponse = connection.StartChamberCalibration(pp.Rotations, pp.Duration);
this.Running = activationResponse.Succeeded && activationResponse.Control == ChamberCalibrationResponse.TEST_ACTIVATED;
var response = connection.StartChamberCalibration(pp.Rotations, pp.Duration);
this.Running = response.Succeeded && response.Control == ChamberCalibrationResponse.TEST_ACTIVATED;
this.Progress += 10;
this.Meter.Add(pp);
if (this.Running)
{
this.State = $"PP {rotations}/{duration} (rotations/seconds) wurde gestarted.";
this.State = $"{this.Header} PP {rotations}/{duration}";
}
else
{
this.State = $"PP {rotations}/{duration} (rotations/seconds): {(int)activationResponse.Status} - {activationResponse.Status}";
this.State = $"{this.Header} PP {rotations}/{duration}, Status:{response.Status}, Control:{response.Control}";
}
}
this.Progress += 10;
}
return this.StartNew(StartPPCalibration, cancellationToken);
return Task.Factory.StartNew(StartPPCalibration, cancellationToken);
}
internal Task StopPPCalibrationAsync(OmniPlusTestPoint pp, double referenceV, CancellationToken cancellationToken)
internal Task StopPPCalibrationAsync(OmniPlusTestPoint pp, double referenceFlowM3S, CancellationToken cancellationToken)
{
cancellationToken.Register(this.CancelExecution);
void StopPPCalibration()
{
if (this.IsRunning())
{
var calibrationResult = connection.ViewChamberCalibration();
this.results[pp].Rotations = calibrationResult.Rotations;
this.results[pp].Duration = calibrationResult.DurationSec;
this.results[pp].MeterVolume = pp.VolumeM3(this.results[pp]);
this.results[pp].VolumeMessured = referenceV;
var resonse = connection.ViewChamberCalibration();
this.Running = calibrationResult.Succeeded && calibrationResult.Control == ChamberCalibrationResponse.TEST_COMPLETED;
this.results[pp].Rotations = resonse.Rotations;
this.results[pp].Duration = resonse.Duration;
this.results[pp].MeterFlowM3S = pp.MeterFlowM3S(this.results[pp]);
this.results[pp].ReferenceFlowM3S = referenceFlowM3S;
this.Running = resonse.Succeeded && resonse.Control == ChamberCalibrationResponse.TEST_COMPLETED;
this.Meter.Add(this.results[pp]);
if (this.Running)
{
this.State = $"PP {pp.Rotations}/{pp.Duration} (rotations/seconds) wurde durchgeführt.";
this.State = $"{this.Header} PP {pp.Rotations}/{pp.Duration} - completed.";
}
else
{
this.State = $"PP {pp.Rotations}/{pp.Duration} fehlgeschlagen: {(int)calibrationResult.Control} - {calibrationResult.Control}";
this.State = $"{this.Header} PP {pp.Rotations}/{pp.Duration} failed: Status:{resonse.Status}, Control:{resonse.Control}";
}
}
this.Progress += 10;
}
return this.StartNew(StopPPCalibration, cancellationToken);
return Task.Factory.StartNew(StopPPCalibration, cancellationToken);
}
internal Task FinishInspectionAsync(CancellationToken cancellationToken)
internal Task SetRegisterSettingsAsync(CancellationToken cancellationToken)
{
cancellationToken.Register(this.CancelExecution);
void FinishInspection()
void SetRegisterSettings()
{
if (!this.IsRunning())
{
return;
}
var configurationParameters = this.connection.ViewConfigurationParameters();
var canContinue = configurationParameters.Succeeded;
// if (canContinue)
{
this.Meter.Add(configurationParameters);
// TODO: Uncomment in production
// var systemTimeReset = connection.SetSystemTime();
//canContinue = systemTimeReset.Succeeded;
}
// if (canContinue)
if (this.IsRunning())
{
var registerSettings = new RegisterSettings();
@@ -360,168 +308,233 @@
registerSettings.PulseUpdate = 0x00;
var response = this.connection.Set(registerSettings);
canContinue = response.Succeeded;
}
}
// if (canContinue)
{
var configurationParametersSet = new ConfigurationParametersSet();
configurationParametersSet.ProgrammableID = this.Meter.BuildInfo;
configurationParametersSet.FactoryID = this.Meter.BuildInfo;
configurationParametersSet.NumberOfReadingDigits = 8;
configurationParametersSet.ReadingPreset = "000000000";
configurationParametersSet.OptionalUniDirFields = 1;
configurationParametersSet.AlarmPercistancePeriodDays = 31;
configurationParametersSet.DataLogIntervalMinutes = 60;
configurationParametersSet.ManifacturingTime = Epoch20000101.UTCNow - 30000;
configurationParametersSet.SystemTime = Epoch20000101.UTCNow;
configurationParametersSet.RebootCount = 0;
configurationParametersSet.BuildInfo = this.Meter.BuildInfo;
return Task.Factory.StartNew(SetRegisterSettings, cancellationToken);
}
var response = this.connection.Set(configurationParametersSet);
canContinue = response.Succeeded;
}
internal Task FinishInspectionAsync(CancellationToken cancellationToken)
{
cancellationToken.Register(this.CancelExecution);
// if (canContinue)
{
var response = this.connection.ClearDisplay();
canContinue = response.Succeeded;
}
void FinishInspection()
{
//if (!this.IsRunning())
//{
// return;
//}
// if (canContinue)
{
var response = this.connection.Set(new LeakAlarm
{
FlowRateGal = 0.25F, // 0.25 gpm
TimeLimit = 24 * 60 * 60 // 24 hours => 86400sec
});
canContinue = response.Succeeded;
}
//var configurationParameters = this.connection.ViewConfigurationParameters();
//var canContinue = configurationParameters.Succeeded;
// if (canContinue)
{
var response = this.connection.Set(new HighFlowAlarm
{
FlowRateGal = 25F, // 25 gpm
TimeLimit = 1 * 60 * 60 // 1 hours => 86400sec
});
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// this.Meter.Add(configurationParameters);
// // TODO: Uncomment in production
// // var systemTimeReset = connection.SetSystemTime();
// //canContinue = systemTimeReset.Succeeded;
//}
// if (canContinue)
{
var response = this.connection.Set(new ReverseFlowAlarm
{
FlowRateGal = -1F, // -1 gpm
TimeLimit = 60 // 1 hours => 86400sec
});
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// var registerSettings = new RegisterSettings();
// if (canContinue)
{
var response = this.connection.ClearAlarms();
canContinue = response.Succeeded;
}
// registerSettings.IntPart = this.Meter.IntPart;
// registerSettings.Fraction = this.Meter.Fraction;
// registerSettings.Size = this.Meter.Size;
// registerSettings.Range = this.Meter.Range;
// registerSettings.VolumePerPulseUnit = 0x00;
// registerSettings.MeterUnits = (byte)MessurementUnits.USGallons;
// registerSettings.FlowUnits = (byte)MessurementUnits.USGallons;
// registerSettings.FlowRate = (byte)TimeUnits.Minutes;
// registerSettings.FactoryCorrection = this.Meter.FactoryCorrection;
// registerSettings.FieldCorrection = 0x00;
// registerSettings.PulseWeight = 0x01;
// registerSettings.PulseWidth = 0x02;
// registerSettings.PulseUpdate = 0x00;
// if (canContinue)
{
var alarmsState = this.connection.ViewAlarmsState();
canContinue = alarmsState.Succeeded;
//&& alarmsState.UsrEnabled
//&& alarmsState.PreEnabledInactive;
//TODO: Check alarms
}
// var response = this.connection.Set(registerSettings);
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var response = this.connection.EnableNFC();
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// var configurationParametersSet = new ConfigurationParametersSet();
// configurationParametersSet.ProgrammableID = this.Meter.BuildInfo;
// configurationParametersSet.FactoryID = this.Meter.BuildInfo;
// configurationParametersSet.NumberOfReadingDigits = 8;
// configurationParametersSet.ReadingPreset = "000000000";
// configurationParametersSet.OptionalUniDirFields = 1;
// configurationParametersSet.AlarmPercistancePeriodDays = 31;
// configurationParametersSet.DataLogIntervalMinutes = 60;
// configurationParametersSet.ManifacturingTime = Epoch20000101.UTCNow - 30000;
// configurationParametersSet.SystemTime = Epoch20000101.UTCNow;
// configurationParametersSet.RebootCount = 0;
// configurationParametersSet.BuildInfo = this.Meter.BuildInfo;
// if (canContinue)
{
var registerSettingsAfter = this.connection.ViewRegisterSettings();
//canContinue = registerSettingsAfter.Succeeded
// && meter.Compare(registerSettingsAfter);
}
// var response = this.connection.Set(configurationParametersSet);
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var systemParametersAfter = this.connection.ViewSystemParameters();
canContinue = systemParametersAfter.Succeeded;
//&& meter.Compare(systemParametersAfter);
}
//// if (canContinue)
//{
// var response = this.connection.ClearDisplay();
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var configurationParametersAfter = this.connection.ViewConfigurationParameters();
canContinue = configurationParametersAfter.Succeeded;
//&& meter.Compare(configurationParametersAfter);
}
//// if (canContinue)
//{
// var response = this.connection.Set(new LeakAlarm
// {
// FlowRateGal = 0.25F, // 0.25 gpm
// TimeLimit = 24 * 60 * 60 // 24 hours => 86400sec
// });
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var alarmsState = this.connection.ViewAlarmsState();
canContinue = alarmsState.Succeeded;
//&& alarmsState.UsrEnabled
//&& alarmsState.PreEnabledInactive;
}
//// if (canContinue)
//{
// var response = this.connection.Set(new HighFlowAlarm
// {
// FlowRateGal = 25F, // 25 gpm
// TimeLimit = 1 * 60 * 60 // 1 hours => 86400sec
// });
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var response = this.connection.ViewAlarmSettings(0x01);
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// var response = this.connection.Set(new ReverseFlowAlarm
// {
// FlowRateGal = -1F, // -1 gpm
// TimeLimit = 60 // 1 hours => 86400sec
// });
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var response = this.connection.ViewAlarmSettings(0x02);
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// var response = this.connection.ClearAlarms();
// canContinue = response.Succeeded;
//}
// if (canContinue)
{
var response = this.connection.ViewAlarmSettings(0x04);
canContinue = response.Succeeded;
}
//// if (canContinue)
//{
// var alarmsState = this.connection.ViewAlarmsState();
// canContinue = alarmsState.Succeeded;
// //&& alarmsState.UsrEnabled
// //&& alarmsState.PreEnabledInactive;
// //TODO: Check alarms
//}
if (canContinue)
{
//connection.Set(new FactorySeal
//{
// Sealed = true,
//});
//// if (canContinue)
//{
// var response = this.connection.EnableNFC();
// canContinue = response.Succeeded;
//}
//var factorySeal = connection.ViewFactorySeal();
//canContinue = factorySeal.Succeeded && factorySeal.Sealed;
}
//// if (canContinue)
//{
// var registerSettingsAfter = this.connection.ViewRegisterSettings();
// //canContinue = registerSettingsAfter.Succeeded
// // && meter.Compare(registerSettingsAfter);
//}
//// if (canContinue)
//{
// var systemParametersAfter = this.connection.ViewSystemParameters();
// canContinue = systemParametersAfter.Succeeded;
// //&& meter.Compare(systemParametersAfter);
//}
//// if (canContinue)
//{
// var configurationParametersAfter = this.connection.ViewConfigurationParameters();
// canContinue = configurationParametersAfter.Succeeded;
// //&& meter.Compare(configurationParametersAfter);
//}
//// if (canContinue)
//{
// var alarmsState = this.connection.ViewAlarmsState();
// canContinue = alarmsState.Succeeded;
// //&& alarmsState.UsrEnabled
// //&& alarmsState.PreEnabledInactive;
//}
//// if (canContinue)
//{
// var response = this.connection.ViewAlarmSettings(0x01);
// canContinue = response.Succeeded;
//}
//// if (canContinue)
//{
// var response = this.connection.ViewAlarmSettings(0x02);
// canContinue = response.Succeeded;
//}
//// if (canContinue)
//{
// var response = this.connection.ViewAlarmSettings(0x04);
// canContinue = response.Succeeded;
//}
//if (canContinue)
//{
// //connection.Set(new FactorySeal
// //{
// // Sealed = true,
// //});
// //var factorySeal = connection.ViewFactorySeal();
// //canContinue = factorySeal.Succeeded && factorySeal.Sealed;
//}
this.Progress = 100;
}
return this.StartNew(FinishInspection, cancellationToken);
return Task.Factory.StartNew(FinishInspection, cancellationToken);
}
internal void SaveInspection(StringBuilder results)
internal Task GetRegisterSettingsAsync(CancellationToken cancellationToken)
{
if (results.Length <= 1)
cancellationToken.Register(this.CancelExecution);
void GetRegisterSettings()
{
results.AppendLine(string.Join(";", this.Meter.Results.Select(x => x.Key)));
if (this.IsRunning())
{
var response = this.connection.ViewRegisterSettings();
if (response.Succeeded)
{
this.Meter.AddResult("<<< Correction factor", $"{response.FactoryCorrection / 10D:0.00} %");
}
}
}
results.AppendLine(string.Join(";", this.Meter.Results.Select(x => x.Value)));
return Task.Factory.StartNew(GetRegisterSettings, cancellationToken);
}
internal double GetCorrectionFactor()
{
var correction = this.results
.OrderBy(x => x.Key.GalPerMin)
.Select(x => x.Value.DifferencePercentage)
.ToArray()
.GetCorrectionFactor();
var deviations = this.results
.OrderBy(x => x.Key.GPM)
.Select(x => x.Value.DifferencePercentage())
.ToArray();
this.State = $"Korekturfaktor: {correction:0.00} %";
var correction = deviations.GetCorrectionFactor();
var correctionUnit = 1 + correction / 100;
this.State = $"{this.Header}, correction: {correction:0.00} %";
this.Meter.AddFactoryCorrection(correction);
foreach (var deviation in deviations)
{
this.Meter.AddResult($"{deviation:0.00} %", $"{deviation * correctionUnit:0.00} %");
}
return correction;
}
@@ -530,7 +543,7 @@
{
try
{
this.connection?.Disconnect();
this.connection?.Close();
}
catch (Exception e)
{
@@ -538,30 +551,14 @@
}
}
private bool IsRunning()
public bool IsRunning()
{
if (!this.Running)
{
return false;
}
this.Connected = this.connection.Connected;
return this.Connected;
}
private Task StartNew(Action action, CancellationToken cancellationToken, int counter = 3)
{
return Task
.Factory
.StartNew(action, cancellationToken);
//.ContinueWith(task =>
//{
// if (task.Status == TaskStatus.Faulted && counter > 0)
// {
// StartNew(action, cancellationToken, counter - 1).Wait();
// }
//});
}
}
}
@@ -12,7 +12,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
@@ -22,14 +21,12 @@
public class EOLContentVM : ContentVM
{
private static readonly string line = new string('=', 500);
private readonly EOLSettings omnisettings;
private readonly ExchangeHubSettings hubsettings;
private readonly ExchangeConnection exchangeConnection;
private readonly OmniDatabase dbcontext;
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private OmniPlusDatabase dbcontext;
private ManualResetEventSlim awaiter;
private ICollection<Task> tasks;
private TimersTimer timer;
@@ -41,22 +38,17 @@
this.CanStart = true;
this.CanCheck = true;
this.Option = new EOLOptionVM(this);
this.OmniDefaults = new OmniPlusType();
this.Option.OptionSelected += this.NotifyOptionSelected;
this.tasks = new List<Task>();
this.omnisettings = new EOLSettings();
this.hubsettings = new ExchangeHubSettings();
this.exchangeConnection = new ExchangeConnection();
this.dbcontext = new OmniPlusDatabase(this.omnisettings.OmniDB);
this.dbcontext = new OmniDatabase(Appsettings.Current.OmniDB);
this.OmniDefaults = new OmniPlusType();
this.LoadComPorts = new Command(this.PrepareConnections);
this.CancelInspection = new Command(this.CancelInspectionHandler);
this.StartInspection = new Command(this.StartInspectionHandler);
this.CheckInspection = new Command(this.CheckInspectionHandler);
this.Option.OptionSelected += this.NotifyOptionSelected;
this.PrepareConnections();
}
private int size;
@@ -204,8 +196,7 @@
this.State = e.ToString();
}
this.exchangeConnection.Disconnect();
this.exchangeConnection.Connect(this.hubsettings.ExchangeHubURL);
this.exchangeConnection.Connect(Appsettings.Current.ExchangeHubURL);
if (this.Size == 0 || this.Type is null)
{
@@ -230,14 +221,13 @@
this.dbcontext.LoadOmniDefaults((byte)this.Size, this.Type, this.OmniDefaults);
this.NotifyPropertyChanged(nameof(this.OmniDefaults));
this.Text = $"ME OMNI 1.5-2\" {this.Type}";
try
{
var placeNr = 1;
foreach (var com in this.omnisettings.COMPorts)
foreach (var com in Appsettings.Current.COMPorts)
{
var comVM = new COMContentVM();
comVM.ContentSelected += this.NotifyCotnentSelected;
@@ -271,6 +261,7 @@
catch (Exception e)
{
this.Error = e.ToString();
this.LogError(e.ToString());
}
this.CanStop = false;
@@ -289,8 +280,9 @@
try
{
this.exchangeConnection.SendStopFlow();
this.exchangeConnection.Disconnect();
this.awaiter.Set();
this.awaiter?.Set();
this.cancellationTokenSource?.Cancel();
this.tasks.Clear();
@@ -300,6 +292,7 @@
{
this.Error = e.ToString();
this.State = default(string);
this.LogError(e.ToString());
}
Task.Factory.StartNew(() =>
@@ -334,6 +327,22 @@
}
});
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.SetRegisterSettingsAsync(cancellationToken));
}
});
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.GetRegisterSettingsAsync(cancellationToken));
}
});
foreach (var pp in this.OmniDefaults.TestPoints)
{
if (this.canceled)
@@ -344,17 +353,21 @@
var rotations = pp.Rotations;
var duration = pp.Duration;
this.StartFlow(pp.VolumeM3H);
this.StartFlow(pp.RequiredFlowM3H);
if (this.canceled)
{
break;
}
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
// this.canceled = this.canceled || meterVM.IsRunning();
tasks.Add(meterVM.StartPPCalibrationAsync(pp, cancellationToken));
}
});
@@ -366,20 +379,27 @@
break;
}
this.WaitUntil((int)(duration * 1.2), true, false);
this.WaitUntil(duration, true, false);
if (this.canceled)
{
break;
}
var referenceV = this.GetReferenceVolume();
var referenceFlowM3S = this.GetReferenceFlowM3S();
if (referenceFlowM3S == default(double))
{
break;
}
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.StopPPCalibrationAsync(pp, referenceV, cancellationToken));
// this.canceled = this.canceled || meterVM.IsRunning();
tasks.Add(meterVM.StopPPCalibrationAsync(pp, referenceFlowM3S, cancellationToken));
}
});
@@ -391,37 +411,18 @@
this.exchangeConnection.SendStopFlow();
foreach (var meterVM in metersVM)
{
meterVM.GetCorrectionFactor();
}
var results = new StringBuilder();
foreach (var meterVM in metersVM)
{
meterVM.SaveInspection(results);
}
try
{
var directory = Directory.CreateDirectory(".\\Results");
var file = Path.Combine(directory.FullName, $"Results_{DateTime.Now:yyyyMMddHHmmss}.csv");
File.WriteAllText(file, results.ToString());
}
catch (Exception e)
{
this.State = e.ToString();
}
if (!this.canceled)
{
foreach (var meterVM in metersVM)
{
meterVM.GetCorrectionFactor();
}
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.FinishInspectionAsync(cancellationToken));
tasks.Add(meterVM.SetRegisterSettingsAsync(cancellationToken));
}
});
}
@@ -458,7 +459,7 @@
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.SetInputVolumeAsync(this.OmniDefaults, cancellationToken));
tasks.Add(meterVM.GetRegisterSettingsAsync(cancellationToken));
}
});
@@ -472,7 +473,7 @@
var rotations = pp.Rotations;
var duration = pp.Duration;
this.StartFlow(pp.VolumeM3H);
this.StartFlow(pp.RequiredFlowM3H);
if (this.canceled)
{
@@ -494,20 +495,27 @@
break;
}
this.WaitUntil((int)(duration * 1.2), true, false);
this.WaitUntil(duration, true, false);
if (this.canceled)
{
break;
}
var referenceV = this.GetReferenceVolume();
var referenceFlowM3S = this.GetReferenceFlowM3S();
if (referenceFlowM3S == default(double))
{
break;
}
this.WaitUntil((int)(Math.Truncate(duration * 0.2) + 1), true, false);
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.StopPPCalibrationAsync(pp, referenceV, cancellationToken));
tasks.Add(meterVM.StopPPCalibrationAsync(pp, referenceFlowM3S, cancellationToken));
}
});
@@ -534,7 +542,6 @@
this.CanStart = true;
this.Error = default(string);
this.State = default(string);
}, this.cancellationToken);
}
@@ -593,16 +600,16 @@
{
var received = false;
var volume = volumeM3H;
var timeout = 120; // seconds
var timeout = 500; // seconds
void referenceVolumeReceived(double value, string _)
void FlowStarted(double value, string _)
{
timeout = -1;
timeout = 0;
received = true;
volume = value;
}
this.exchangeConnection.StartFlow += referenceVolumeReceived;
this.exchangeConnection.StartFlow += FlowStarted;
this.exchangeConnection.SendStartFlow(volumeM3H);
@@ -624,6 +631,8 @@
this.State = $"Warten auf Q({volumeM3H:0.0000}): {timeout} Sekunden verbleiben ...";
}
this.exchangeConnection.StartFlow -= FlowStarted;
if (!this.canceled)
{
this.State = $"Durchfluss {volume:0.0000} erreicht ...";
@@ -634,16 +643,16 @@
{
var received = false;
var reference = 0;
var timeout = 30; // seconds
var timeout = 60; // seconds
void referenceVolumeReceived(int seconds, string _)
void ReferenceMessurementStarted(int seconds, string _)
{
timeout = -1;
timeout = 0;
received = true;
reference = seconds;
}
this.exchangeConnection.StartReferenceMessurement += referenceVolumeReceived;
this.exchangeConnection.StartReferenceMessurement += ReferenceMessurementStarted;
this.exchangeConnection.SendStartReferenceMessurement(duration);
@@ -665,26 +674,28 @@
this.State = $"Warten bis RZ gestarted: {timeout} Sekunden verbleiben ...";
}
this.exchangeConnection.StartReferenceMessurement -= ReferenceMessurementStarted;
if (!this.canceled)
{
this.State = $"Referenzmessung gestartet ...";
}
}
private double GetReferenceVolume()
private double GetReferenceFlowM3S()
{
var received = false;
var referenceV = 0D;
var timeout = 30; // seconds
var timeout = 60; // seconds
void referenceVolumeReceived(double value, string _)
void ReferenceFlowM3SecReceived(double value, string _)
{
timeout = -1;
timeout = 0;
received = true;
referenceV = value;
}
this.exchangeConnection.StopReferenceMessurement += referenceVolumeReceived;
this.exchangeConnection.StopReferenceMessurement += ReferenceFlowM3SecReceived;
this.exchangeConnection.SendStopReferenceMessurement();
@@ -706,6 +717,8 @@
this.State = $"Warten RZ-Ergebnis: {timeout} Sekunden verbleiben ...";
}
this.exchangeConnection.StopReferenceMessurement -= ReferenceFlowM3SecReceived;
if (!this.canceled)
{
@@ -764,7 +777,14 @@
private void LogError(string error)
{
File.AppendAllText(this.errorLog, error);
try
{
File.AppendAllText(this.errorLog, error);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
@@ -12,7 +12,6 @@
public class ExchangeHubContentVM : ContentVM
{
private readonly ExchangeHubSettings hubsettings;
private readonly ExchangeConnection connection;
public ExchangeHubContentVM() : base()
@@ -22,44 +21,12 @@
this.Option.OptionSelected += this.NotifyOptionSelected;
this.Connect = new Command(this.ConnectHubHandler);
this.Disconnect = new Command(this.DisconnectHubHandler);
this.hubsettings = new ExchangeHubSettings();
this.connection = new ExchangeConnection();
this.connection.StateChanged += Connection_StateChanged1;
this.NotifyPropertyChanged(nameof(this.LogContent));
}
public string URL
{
get => this.hubsettings.ExchangeHubURL;
set
{
this.hubsettings.ExchangeHubURL = value;
this.NotifyPropertyChanged(nameof(this.URL));
}
}
public string OutputDir
{
get
{
if (string.IsNullOrWhiteSpace(this.hubsettings.ExchangeHubOutputDir))
{
this.hubsettings.ExchangeHubOutputDir = App.Path;
}
return this.hubsettings.ExchangeHubOutputDir;
}
set
{
this.hubsettings.ExchangeHubOutputDir = value;
this.NotifyPropertyChanged(nameof(this.OutputDir));
}
}
private bool connected;
public bool Connected
{
@@ -85,7 +52,7 @@
{
Task.Factory.StartNew(() =>
{
this.connection.Connect(this.URL);
this.connection.Connect(Appsettings.Current.ExchangeHubURL);
});
}
@@ -13,17 +13,15 @@
this.ContentSelected += this.SetContentSelected;
this.Options = new ObservableCollection<OptionVM>();
var exchangeHubVM = new ExchangeHubContentVM();
exchangeHubVM.ContentSelected += this.SetContentSelected;
// var exchangeHubVM = new ExchangeHubContentVM();
// exchangeHubVM.ContentSelected += this.SetContentSelected;
// this.Options.Add(exchangeHubVM.Option);
// this.Nodes.Add(exchangeHubVM);
var contentEOL = new EOLContentVM();
contentEOL.ContentSelected += this.SetContentSelected;
this.Nodes.Add(exchangeHubVM);
this.Nodes.Add(contentEOL);
this.Options.Add(exchangeHubVM.Option);
this.Options.Add(contentEOL.Option);
this.Nodes.Add(contentEOL);
}
private ContentVM content;
@@ -1,15 +1,25 @@
namespace OMNIPruefung.ViewModels.Features
{
using OmniPlus;
using OmniPlus.Features;
using OmniPlus.Inspection;
using OMNIPruefung.Models;
using OMNIPruefung.ViewModels.Base;
using System;
using System.Collections.ObjectModel;
using System.Windows;
public class OMNIPlusVM : VM<OMNIPlusVM>
{
public ObservableCollection<Result> Results { get; }
= new ObservableCollection<Result>();
// TODO: save all in database
private readonly OmniDatabase database;
public OMNIPlusVM()
{
this.database = new OmniDatabase(Appsettings.Current.OmniDB);
this.Results = new ObservableCollection<Result>();
}
public ushort IntPart { get; internal set; }
@@ -21,25 +31,24 @@
public sbyte FactoryCorrection { get; internal set; }
public string BuildInfo { get; internal set; }
public ObservableCollection<Result> Results { get; }
internal void AddResult(string key, string value)
{
this.Results.Add(new Result
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Key = key,
Value = value
});
this.Results.Add(new Result
{
Key = key,
Value = value
});
}));
}
internal void Add(SystemParameters response)
internal void Add(OmniPlus.Features.SystemParameters response)
{
this.AddResult("Reading System Parameters", $"{response.Status}");
if (response.Succeeded)
{
this.BuildInfo = response.BuildInfo.Value;
this.AddResult(nameof(response.VersionAndType), response.VersionAndType.Value);
this.AddResult(nameof(response.BuildInfo), response.BuildInfo.Value);
this.AddResult(nameof(response.BatteryVoltage), $"{(response.BatteryVoltage.Volts + 0.0001) / 1000:0.0000 V}");
@@ -52,29 +61,32 @@
internal void Add(InputVolume response)
{
this.IntPart = response.IntPart;
this.Fraction = response.Fraction;
this.Size = response.Size;
this.Range = response.Range;
this.IntPart = response.IntPartFull;
this.Fraction = response.Fraction;
this.AddResult("Setting ml/r", $"{response.MlPerRotation:0.0000 ml/r}");
this.AddResult(nameof(response.Size), $"{response.Size}");
this.AddResult(nameof(response.Range), $"{response.Range}");
this.AddResult(nameof(response.Direction), $"{response.Direction}");
this.AddResult(nameof(response.IntPart), $"{response.IntPart}");
this.AddResult(nameof(response.Fraction), $"{response.Fraction}");
}
internal void Add(OmniPlusTestPoint pp)
{
this.AddResult("", $"");
this.AddResult("Test point:", $"{pp.Rotations}/{pp.Duration:0}");
this.AddResult("Volume", $"{pp.VolumeM3H:0.0000 m³/h}");
this.AddResult("Duration", $"{pp.Duration:0 sec.}");
this.AddResult("ml/rotation", $"{pp.MlPerRotation:0.0000 ml/r}");
this.AddResult("Volume", $"{pp.RequiredFlowM3H:0.00000000 m³/h}");
this.AddResult("Validation frame", $"{pp.MinDiff:0.00}% - {pp.MaxDiff:0.00}%");
}
internal void Add(OmniPlusTest test)
{
this.AddResult("Result", $"{test.DifferencePercentage:0.00}%");
this.AddResult("Meter volume", $"{test.MeterVolume:0.0000 m³}");
this.AddResult("Reference volume", $"{test.VolumeMessured:0.0000 m³}");
this.AddResult("Test result", $"{test.Rotations}/{test.Duration:0}");
this.AddResult("Test result:", $"{test.Rotations:0}/{test.Duration:0.0000}");
this.AddResult("Meter volume", $"{test.MeterFlowM3S:0.00000000 m³}");
this.AddResult("Reference volume", $"{test.ReferenceFlowM3S:0.00000000 m³}");
this.AddResult("Deviation", $"{test.DifferencePercentage():0.00}%");
}
internal void Add(ConfigurationParameters response)
@@ -93,8 +105,7 @@
{
this.FactoryCorrection = (sbyte)(value * 10);
this.AddResult("Factory correction %", $"{value:0.00}%");
this.AddResult("Factory correction", $"{this.FactoryCorrection:0}");
this.AddResult("Correction", $"{value:0.00} %");
}
}
@@ -58,9 +58,9 @@
<Label Grid.Column="3" Grid.Row="3" Content="min %" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="4" Grid.Row="3" Content="max %" HorizontalContentAlignment="Right" Grid.ColumnSpan="2" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="2" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="6" Content="{Binding OmniDefaults.TestPoints[2].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].RequiredFlowM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].RequiredFlowM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="6" Content="{Binding OmniDefaults.TestPoints[2].RequiredFlowM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="3" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].MinDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 21, 0" />
<Label Grid.Column="3" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].MinDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 21, 0" />
@@ -1,21 +0,0 @@
namespace OmniPlus.Connections
{
internal class IrdaEncoder : SerialDataEncoder
{
public byte Device2PC { get; } = SerialDataExtensions.IRDA_REG2PC;
public override bool TryDecode(byte[] encoded, out byte[] decoded)
{
decoded = encoded.FromIrdaMessage();
return decoded.Length > 0;
}
public override bool TryEncode(byte[] decoded, out byte[] encoded)
{
encoded = decoded.ToIrdaMessage();
return encoded.Length > 0;
}
}
}
@@ -1,50 +0,0 @@
namespace OmniPlus.Connections
{
using System;
using System.Threading;
internal class IrdaStream : SerialDataReader
{
private readonly IrdaEncoder encoder;
public IrdaStream(SerialPortSettings settings) : base(settings)
{
this.encoder = new IrdaEncoder();
}
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
base.WriteBytes(1, 1, 1, 1);
Thread.Sleep(1);
base.WriteBytes(message);
}
}
protected override void BeginRead(byte[] bytes)
{
if (bytes is null)
{
return;
}
var start = Array.IndexOf(bytes, this.encoder.Device2PC);
if (start >= 0)
{
if (this.encoder.TryDecode(bytes, out byte[] message))
{
this.EnqueueMessage(message);
this.RemoveRange(message.Length);
}
}
else
{
this.RemoveRange(bytes.Length);
}
}
}
}
@@ -0,0 +1,29 @@
namespace OmniPlus.Connections
{
internal sealed class OmniIrdaEncoder : SerialDataEncoder
{
public override bool TryDecode(byte[] data, out byte[] message, out int start, out int length)
{
message = default(byte[]);
if (data.FromIrdaMessage(out byte[] payload, out start, out length))
{
if (payload.FromUI1236Message(out message, out start, out length))
{
return true;
}
}
return false;
}
public override bool TryEncode(byte[] data, out byte[] message)
{
message = data
.ToUI1236Message()
.ToIrdaMessage();
return message != null && message.Length > 0;
}
}
}
@@ -0,0 +1,54 @@
namespace OmniPlus.Connections
{
using System.Threading;
internal sealed class OmniIrdaStream : SerialDataStream
{
private readonly ManualResetEventSlim waitHandle;
public OmniIrdaStream(SerialDataEncoder encoder, SerialPortSettings settings) : base(encoder, settings)
{
this.waitHandle = new ManualResetEventSlim();
}
public override byte[] Send(params byte[] message)
{
var response = new byte[0];
void DataReceived(byte[] data)
{
response = data;
this.waitHandle.Set();
}
this.DataReceived += DataReceived;
this.StartListening();
for (int i = 0; i < 3; i++)
{
if (response != null && response.Length > 0)
{
break;
}
this.WritePlain(1, 1, 1, 1);
this.waitHandle.Wait(1);
this.waitHandle.Reset();
this.WriteEncoded(message);
this.waitHandle.Wait(3000);
this.waitHandle.Reset();
}
this.StopListening();
this.DataReceived -= DataReceived;
return response;
}
}
}
@@ -0,0 +1,22 @@
namespace OmniPlus.Connections
{
internal class OmniUniProEncoder : SerialDataEncoder
{
public override bool TryDecode(byte[] data, out byte[] message, out int start, out int length)
{
return data.FromUniProMessage(out message, out start, out length);
}
public override bool TryEncode(byte[] data, out byte[] message)
{
message = new byte[0];
if (data != null && data.Length > 0)
{
message = data.ToUniProMessage();
}
return message != null && message.Length > 0;
}
}
}
@@ -0,0 +1,49 @@
namespace OmniPlus.Connections
{
using System.Threading;
internal class OmniUniProStream : SerialDataStream
{
private readonly ManualResetEventSlim waitHandle;
public OmniUniProStream(SerialDataEncoder encoder, SerialPortSettings settings) : base(encoder, settings)
{
this.waitHandle = new ManualResetEventSlim();
}
public override byte[] Send(params byte[] message)
{
var response = new byte[0];
void DataReceived(byte[] data)
{
response = data;
this.waitHandle.Set();
}
this.DataReceived += DataReceived;
this.StartListening();
for (int i = 0; i < 3; i++)
{
if (response != null && response.Length > 0)
{
break;
}
this.WriteEncoded(message);
this.waitHandle.Wait(3000);
this.waitHandle.Reset();
}
this.StopListening();
this.DataReceived -= DataReceived;
return response;
}
}
}
@@ -1,110 +0,0 @@
namespace OmniPlus.Connections
{
using System;
using System.IO.Ports;
using System.Text;
internal class Program
{
static void Main(string[] args)
{
var number = "81623241198";
var last = number.Length - 1;
var line = string.Empty;
while (!string.IsNullOrEmpty(line = Console.ReadLine()))
{
Console.WriteLine();
var next = number + line[0];
var request = new byte[] { };
var response = new byte[] { };
var settings = new SerialPortSettings
{
BaudRate = 115200,
DataBits = 8,
Parity = Parity.None,
PortName = "COM1",
StopBits = StopBits.One,
};
var foreground = Console.ForegroundColor;
using (var stream = new UI1236Stream(settings))
{
stream.Open();
request = new byte[] { 0x05 };
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[] { 0x01 };
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[14];
request[0] = 0x02;
Encoding.ASCII.GetBytes(next).CopyTo(request, 1);
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[] { 0x01 };
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[] { 0x03 };
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[22];
request[0] = 0x04;
Encoding.ASCII.GetBytes($"SEN{next}").CopyTo(request, 1);
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
request = new byte[] { 0x03 };
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($">>> {BitConverter.ToString(request)}");
response = stream.Write(request);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
Console.ForegroundColor = foreground;
}
Console.WriteLine();
}
}
}
}
@@ -2,8 +2,8 @@
{
internal abstract class SerialDataEncoder
{
public abstract bool TryDecode(byte[] encoded, out byte[] decoded);
public abstract bool TryEncode(byte[] data, out byte[] message);
public abstract bool TryEncode(byte[] decoded, out byte[] encoded);
public abstract bool TryDecode(byte[] data, out byte[] message, out int start, out int length);
}
}
@@ -2,7 +2,7 @@
{
using System;
internal static class SerialDataExtensions
public static class SerialDataExtensions
{
public const int BYTE_BITS = 8;
@@ -18,13 +18,17 @@
public const byte UNIPRO_MIN_LENGTH = 4;
public const byte UI1236_START = 0x0D;
public const byte UI1236_LEN_INDEX = 1;
public const byte UI1236_DATA_INDEX = 3;
public const byte UI1236_MIN_LENGTH = 5;
public const byte UI1236_HED_LENGTH = 3;
public const byte UI1236_HEAD_LENGTH = 3;
public const byte IRDA_START = 0x9B;
public const byte IRDA_PING = 0x82;
public const byte IRDA_PC2REG = 0x33;
public const byte IRDA_REG2PC = 0x43;
public const byte IRDA_LEN_INDEX = 2;
public const byte IRDA_DATA_INDEX = 3;
public const byte IRDA_MIN_LENGTH = 5;
public const byte IRDA_CRC_LENGTH = 2;
@@ -39,14 +43,27 @@
/// </summary>
public static byte[] ToUI1236Message(this byte[] bytes)
{
var message = new byte[0];
if (bytes is null)
{
return message;
}
var bytesLength = bytes.Length;
var payloadLength = bytes.Length + UI1236_MIN_LENGTH;
payloadLength += payloadLength % OxO2;
if (bytesLength == 0)
{
return message;
}
var messageLength = bytes.Length + UI1236_MIN_LENGTH;
messageLength += messageLength % OxO2;
var index = OxOO;
var message = new byte[payloadLength];
message = new byte[messageLength];
message[index++] = UI1236_START;
message[index++] = (byte)(bytesLength + UI1236_HED_LENGTH);
message[index++] = (byte)(bytesLength + UI1236_HEAD_LENGTH);
UI1236Control control = OxOO;
control.ReturnResponse = true;
@@ -55,45 +72,13 @@
bytes.CopyTo(message, index);
var checksum = message.CalculateCheckSUM(message.Length - OxO2);
var checksumIndex = bytesLength + UI1236_HED_LENGTH;
var checksumIndex = bytesLength + UI1236_HEAD_LENGTH;
message[checksumIndex++] = checksum[OxO1];
message[checksumIndex++] = checksum[OxOO];
return message;
}
/// <summary>
/// <para>UI1236 structure:</para>
/// <para> 0. 0x0D - Start byte</para>
/// <para> 1. .... - Length: max. 254</para>
/// <para> 2. .... - Control byte</para>
/// <para>3+n. .... - Payload</para>
/// <para>n-2. .... - Checksum 0 </para>
/// <para>n-1. .... - Checksum 1 </para>
/// </summary>
public static byte[] FromUI1236Message(this byte[] bytes)
{
var payload = new byte[OxOO];
if (bytes is null)
{
return payload;
}
var payloadLength = bytes.Length - UI1236_MIN_LENGTH;
if (payloadLength <= OxOO)
{
return payload;
}
payload = new byte[payloadLength];
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
return payload;
}
/// <summary>
/// <para>UniPro structure:</para>
/// <para> 0. .... - Start byte</para>
@@ -126,27 +111,56 @@
/// <para> .. .... - Payload</para>
/// <para>n-1. .... - Stop byte</para>
/// </summary>
public static byte[] FromUniProMessage(this byte[] bytes)
public static bool FromUniProMessage(this byte[] bytes, out byte[] message, out int start, out int length)
{
var payload = new byte[OxOO];
message = default(byte[]);
length = default(int);
start = default(int);
if (bytes is null)
{
return payload;
return false;
}
var payloadLength = bytes.Length - UNIPRO_MIN_LENGTH;
var bytesLength = bytes.Length;
if (payloadLength <= OxOO)
while (start < bytesLength)
{
return payload;
start = Array.IndexOf(bytes, UNIPRO_REG2PC) - 1;
if (start < 0 || bytes[start] == UNIPRO_START)
{
break;
}
start += 2;
}
payload = new byte[payloadLength];
if (start < 0)
{
return false;
}
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
start += 2;
return payload;
if (start >= bytesLength)
{
return false;
}
length = bytes[start] - UNIPRO_MIN_LENGTH;
if (start + length >= bytesLength)
{
return false;
}
start += 1;
message = new byte[length];
Buffer.BlockCopy(bytes, start, message, 0, length);
return true;
}
/// <summary>
@@ -161,21 +175,35 @@
/// </summary>
public static byte[] ToIrdaMessage(this byte[] bytes)
{
var payloadLength = bytes.Length;
payloadLength += payloadLength % OxO2;
var message = new byte[0];
if (bytes is null)
{
return message;
}
var bytesLength = bytes.Length;
if (bytesLength == 0)
{
return message;
}
var messageLength = bytesLength;
messageLength += messageLength % OxO2;
var index = OxOO;
var message = new byte[payloadLength + IRDA_MIN_LENGTH];
message = new byte[messageLength + IRDA_MIN_LENGTH];
message[index++] = IRDA_START;
message[index++] = IRDA_PC2REG;
message[index++] = (byte)(payloadLength / OxO2);
message[index++] = (byte)(messageLength / OxO2);
bytes.CopyTo(message, index);
var messageLength = message.Length;
var crc16 = message.CalculateCRC8408(1, messageLength - IRDA_CRC_LENGTH);
message[messageLength - OxO2] = crc16[OxOO];
message[messageLength - OxO1] = crc16[OxO1];
var _length = message.Length;
var crc16 = message.CalculateCRC8408(1, _length - IRDA_CRC_LENGTH);
message[_length - OxO2] = crc16[OxOO];
message[_length - OxO1] = crc16[OxO1];
return message;
}
@@ -190,106 +218,111 @@
/// <para>n-2. .... - CRC16 0 </para>
/// <para>n-1. .... - CRC16 1 </para>
/// </summary>
public static byte[] FromIrdaMessage(this byte[] bytes)
public static bool FromIrdaMessage(this byte[] bytes, out byte[] message, out int start, out int length)
{
var payload = new byte[OxOO];
message = default(byte[]);
length = default(int);
start = default(int);
if (bytes is null)
{
return payload;
return false;
}
var payloadLength = bytes.Length - IRDA_MIN_LENGTH;
var bytesLength = bytes.Length;
if (payloadLength <= OxOO)
while (start < bytesLength)
{
return payload;
start = Array.IndexOf(bytes, IRDA_REG2PC, start) - 1;
if (start < 0 || bytes[start] == IRDA_START)
{
break;
}
start += 2;
}
payload = new byte[payloadLength];
if (start < 0)
{
return false;
}
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
start += 2;
return payload;
if (start >= bytesLength)
{
return false;
}
length = bytes[start] * 2;
if (start + length >= bytesLength)
{
return false;
}
start += 1;
message = new byte[length];
Buffer.BlockCopy(bytes, start, message, 0, length);
return true;
}
/// <summary>
/// <para>Irda structure:</para>
/// <para> 0. .... - Start byte</para>
/// <para> 1. .... - Direction</para>
/// <para> 2. .... - Length / 2</para>
/// <para>UI1236 structure:</para>
/// <para> 0. 0x0D - Start byte</para>
/// <para> 1. .... - Length: max. 254</para>
/// <para> 2. .... - Control byte</para>
/// <para>3+n. .... - Payload</para>
/// <para>n-3. .... - aligned byte</para>
/// <para>n-2. .... - CRC16 0 </para>
/// <para>n-1. .... - CRC16 1 </para>
/// <para>n-2. .... - Checksum 0 </para>
/// <para>n-1. .... - Checksum 1 </para>
/// </summary>
public static byte[] FromIrdaMessage(this byte[] bytes, int start, out int length)
public static bool FromUI1236Message(this byte[] bytes, out byte[] message, out int start, out Int32 length)
{
length = OxOO;
var payload = new byte[length];
message = default(byte[]);
length = default(int);
start = default(int);
if (bytes is null)
{
return payload;
return false;
}
var bytesLength = bytes.Length;
var payloadLengthIndex = start + 2;
start = Array.IndexOf(bytes, UI1236_START);
if (bytesLength <= payloadLengthIndex)
if (start < 0)
{
return payload;
return false;
}
var payloadLength = bytes[payloadLengthIndex] * 2;
length = payloadLength + IRDA_MIN_LENGTH;
start += 1;
if (payloadLength <= OxOO)
if (start >= bytes.Length)
{
return payload;
return false;
}
payload = new byte[payloadLength];
var payloadStart = payloadLengthIndex + 1;
length = bytes[start] - UI1236_HEAD_LENGTH;
Buffer.BlockCopy(bytes, payloadStart, payload, 0, payloadLength);
return payload;
}
/// <summary>
/// <para>Irda structure:</para>
/// <para> 0. .... - Start byte</para>
/// <para> 1. .... - Direction</para>
/// <para> 2. .... - Length / 2</para>
/// <para>3+n. .... - Payload</para>
/// <para>n-3. .... - aligned byte</para>
/// <para>n-2. .... - CRC16 0 </para>
/// <para>n-1. .... - CRC16 1 </para>
/// </summary>
public static byte[] FromIrdaMessage(this byte[] bytes, int start)
{
var bytesLength = bytes.Length;
if (bytes is null || bytesLength <= start)
if (length <= 0)
{
return new byte[] { };
return false;
}
var _length = bytes[start + 2] * 2;
var _start = start + 3;
start += 2;
if (_start + _length >= bytesLength)
if (start + length >= bytes.Length)
{
return new byte[] { };
return false;
}
var data = new byte[_length];
message = new byte[length];
Buffer.BlockCopy(bytes, _start, data, 0, _length);
Buffer.BlockCopy(bytes, start, message, 0, length);
return data;
return true;
}
public static byte[] CalculateCRC8408(this byte[] message, int start, int length)
@@ -1,168 +0,0 @@
namespace OmniPlus.Connections
{
using System;
using System.Collections.Generic;
using System.Threading;
internal abstract class SerialDataReader : SerialDataStream
{
protected bool read;
private Thread thread;
private List<byte> stream;
private Queue<byte[]> messages;
protected ManualResetEventSlim awaiter;
protected SerialDataReader(SerialPortSettings settings) : base(settings)
{
}
public bool IsAlive
{
get
{
if (this.thread is null)
{
return false;
}
return this.thread.IsAlive;
}
}
public override void Dispose()
{
try
{
this.messages = null;
this.stream = null;
this.thread?.Abort();
this.thread = null;
}
catch (Exception e)
{
this.NotifyStateChanged(e.ToString());
}
base.Dispose();
}
protected virtual void BeginRead(byte[] bytes)
{
}
protected void ClearMessages()
{
if (this.messages != null)
{
this.messages.Clear();
}
}
protected byte[] DequeueMessage()
{
if (this.messages != null && this.messages.Count > 0)
{
return this.messages.Dequeue();
}
return null;
}
protected void EnqueueMessage(byte[] message)
{
if (this.messages != null)
{
this.messages.Enqueue(message);
}
}
protected void RemoveRange(int length)
{
if (this.stream != null)
{
this.stream.RemoveRange(0, length);
}
}
protected void StartListening()
{
try
{
if (!this.IsOpen)
{
base.Open();
}
if (!this.IsAlive)
{
this.stream = new List<byte>();
this.messages = new Queue<byte[]>();
this.thread = new Thread(this.BeginRead);
this.thread.Start();
}
if (this.awaiter?.IsSet == true)
{
this.awaiter.Set();
}
this.awaiter = new ManualResetEventSlim();
this.read = true;
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
protected void StopListening()
{
try
{
this.stream.Clear();
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
try
{
this.messages.Clear();
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
this.read = false;
this.awaiter.Set();
}
private void BeginRead()
{
this.NotifyStateChanged($"{nameof(IrdaStream)} - reading thread started.");
while (this.IsAlive)
{
if (!this.read)
{
this.awaiter.Wait();
}
var bytes = this.ReadBytes();
if (bytes.Length > 0)
{
this.stream.AddRange(bytes);
}
this.BeginRead(this.stream?.ToArray());
}
this.NotifyStateChanged($"{nameof(IrdaStream)} - reading thread stoped.");
}
}
}
@@ -1,29 +1,36 @@
namespace OmniPlus.Connections
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
internal class SerialDataStream : SerialPortStream
internal abstract class SerialDataStream : SerialPortStream
{
public SerialDataStream(SerialPortSettings settings) : base(settings)
private readonly ManualResetEventSlim waitHandle;
private readonly SerialDataEncoder encoder;
private readonly List<byte> buffer;
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private Task readingTask;
protected SerialDataStream(SerialDataEncoder encoder, SerialPortSettings settings) : base(settings)
{
this.encoder = encoder;
this.buffer = new List<byte>();
this.waitHandle = new ManualResetEventSlim();
}
protected virtual byte[] ReadBytes()
{
var bytes = new byte[0];
protected event Action<byte[]> DataReceived;
public override void Close()
{
try
{
if (this.IsOpen)
if (this.cancellationTokenSource != null)
{
var length = this.serialPort.BytesToRead;
if (length > 1)
{
bytes = new byte[length];
this.serialPort.Read(bytes, 0, length);
}
this.cancellationTokenSource.Cancel();
}
}
catch (Exception e)
@@ -31,27 +38,161 @@
this.NotifyStateChanged(e);
}
return bytes;
base.Close();
}
protected virtual void WriteBytes(params byte[] bytes)
public override void Open()
{
base.Open();
try
{
if (this.IsOpen)
{
var _lock = new object();
lock (_lock)
{
this.serialPort.Write(bytes, 0, bytes.Length);
}
}
this.StartReading();
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
protected void StartListening()
{
try
{
this.buffer.Clear();
this.waitHandle.Set();
this.NotifyStateChanged($"--- start listening");
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
protected void StopListening()
{
try
{
this.waitHandle.Reset();
this.buffer.Clear();
this.NotifyStateChanged($"--- stop listening");
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
protected void WriteEncoded(params byte[] bytes)
{
this.EnsureOpened();
try
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
this.Write(message, 0, message.Length);
}
this.NotifyStateChanged($">>> {BitConverter.ToString(bytes)}");
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
protected void WritePlain(params byte[] bytes)
{
this.EnsureOpened();
try
{
this.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
private void EnsureOpened()
{
if (this.serialPort is null)
{
this.Open();
}
else if (!this.serialPort.IsOpen)
{
this.Close();
this.Open();
}
}
private void ReadingTaskHandler()
{
while (true)
{
this.waitHandle.Wait();
try
{
var size = this.serialPort.BytesToRead;
if (size > 0)
{
var buffer = new byte[size];
this.serialPort.Read(buffer, 0, size);
this.buffer.AddRange(buffer);
var data = this.buffer.ToArray();
if (this.encoder.TryDecode(data, out byte[] message, out int start, out int _))
{
this.DataReceived?.Invoke(message);
this.NotifyStateChanged($"<<< {BitConverter.ToString(message)}");
}
if (start < 0)
{
this.buffer.Clear();
}
}
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
}
private void StartReading()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
this.readingTask = Task.Factory
.StartNew(this.ReadingTaskHandler, this.cancellationToken);
this.readingTask.ContinueWith(task =>
{
if (task.Exception != null)
{
this.NotifyStateChanged(task.Exception);
}
this.StartReading();
});
}
private void Write(byte[] bytes, int start, int length)
{
var _lock = new object();
lock (_lock)
{
this.serialPort.Write(bytes, 0, length);
}
}
}
}
@@ -3,7 +3,9 @@
using System;
using System.IO.Ports;
internal abstract class SerialPortStream : IDisposable
public delegate void StateChanged(object state);
internal abstract class SerialPortStream
{
protected SerialPort serialPort;
@@ -11,27 +13,17 @@
protected SerialPortStream(SerialPortSettings settings)
{
if (settings is null)
{
throw new ArgumentNullException($"{nameof(SerialPortSettings)} are required.");
}
this.settings = settings;
}
public event StateChanged StateChanged;
public event Action Connected;
public event Action Disconnected;
public event Action<object> StateChanged;
public bool IsOpen
{
get
{
if (this.serialPort is null)
{
return false;
}
return this.serialPort.IsOpen;
}
}
public virtual void Dispose()
public virtual void Close()
{
try
{
@@ -40,9 +32,8 @@
this.serialPort.Close();
this.serialPort.Dispose();
this.serialPort = null;
this.NotifyStateChanged($"{this} - disposed.");
this.Disconnected?.Invoke();
this.NotifyStateChanged($"--- {this} - disconnected.");
}
}
catch (Exception e)
@@ -53,11 +44,6 @@
public virtual void Open()
{
if (this.serialPort != null)
{
this.Dispose();
}
try
{
this.serialPort = new SerialPort
@@ -67,15 +53,12 @@
Parity = this.settings.Parity,
PortName = this.settings.PortName,
StopBits = this.settings.StopBits,
DtrEnable = true
};
this.serialPort.Open();
if (this.IsOpen)
{
this.NotifyStateChanged($"{this} - connected.");
this.Connected?.Invoke();
}
this.NotifyStateChanged($"--- {this} - connected.");
}
catch (Exception e)
{
@@ -93,7 +76,7 @@
$"{this.settings.Parity}, " +
$"{this.settings.StopBits}";
}
else
else
{
return $"{this.serialPort.PortName}, " +
$"{this.serialPort.BaudRate}, " +
@@ -103,6 +86,8 @@
}
}
public abstract byte[] Send(params byte[] message);
protected void NotifyStateChanged(object state)
{
this.StateChanged?.Invoke(state);
@@ -1,19 +0,0 @@
namespace OmniPlus.Connections
{
internal class UI1236Encoder : SerialDataEncoder
{
public override bool TryDecode(byte[] encoded, out byte[] decoded)
{
decoded = encoded.FromUI1236Message();
return decoded.Length > 0;
}
public override bool TryEncode(byte[] decoded, out byte[] encoded)
{
encoded = decoded.ToUI1236Message();
return encoded.Length > 0;
}
}
}
@@ -1,102 +0,0 @@
namespace OmniPlus.Connections
{
using System;
using System.IO;
using System.Threading;
internal class UI1236Stream : IrdaStream
{
private readonly string fileName;
private readonly UI1236Encoder encoder;
public UI1236Stream(SerialPortSettings settings) : base(settings)
{
var directiry = Directory.CreateDirectory(".\\UI1236");
this.fileName = Path.Combine(directiry.FullName, $"[{settings.PortName}].txt");
this.encoder = new UI1236Encoder();
File.AppendAllText(Path.Combine(directiry.FullName, $"[{settings.PortName}].txt"), string.Empty);
this.StateChanged += this.UI1236Stream_StateChanged;
}
public byte[] Write(params byte[] bytes)
{
this.LogToFile($">>> {BitConverter.ToString(bytes)}");
this.StartListening();
Thread.Sleep(500);
this.WriteBytes(bytes);
var response = new byte[0];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
var message = this.DequeueMessage();
if (message != null)
{
if (this.encoder.TryDecode(message, out response))
{
this.ClearMessages();
break;
}
else
{
Thread.Sleep(500);
}
}
else
{
Thread.Sleep(500);
}
}
if (response.Length > 0)
{
break;
}
this.LogToFile($"<<< {BitConverter.ToString(response)}");
Thread.Sleep(500);
}
this.StopListening();
this.LogToFile($"<<< {BitConverter.ToString(response)}");
this.LogToFile(string.Empty);
return response;
}
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
base.WriteBytes(message);
}
}
private void LogToFile(string value)
{
try
{
File.AppendAllText(this.fileName, $"{value}{Environment.NewLine}");
}
catch (Exception e)
{
}
}
private void UI1236Stream_StateChanged(object state)
{
this.LogToFile($"{state}");
}
}
}
@@ -1,21 +0,0 @@
namespace OmniPlus.Connections
{
internal class UniProEncoder : SerialDataEncoder
{
public object Device2PC { get; } = SerialDataExtensions.UNIPRO_REG2PC;
public override bool TryDecode(byte[] encoded, out byte[] decoded)
{
decoded = encoded.FromUniProMessage();
return decoded.Length > 0;
}
public override bool TryEncode(byte[] decoded, out byte[] encoded)
{
encoded = decoded.FromUniProMessage();
return encoded.Length > 0;
}
}
}
@@ -1,86 +0,0 @@
namespace OmniPlus.Connections
{
using System;
using System.Threading;
internal class UniProStream : SerialDataReader
{
private readonly UniProEncoder encoder;
public UniProStream(SerialPortSettings settings) : base(settings)
{
this.encoder = new UniProEncoder();
}
public byte[] Write(params byte[] bytes)
{
this.StartListening();
this.WriteBytes(bytes);
var response = new byte[0];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
var message = this.DequeueMessage();
if (message != null)
{
if (this.encoder.TryDecode(message, out response))
{
this.ClearMessages();
break;
}
else
{
Thread.Sleep(200);
}
}
else
{
Thread.Sleep(200);
}
}
if (response.Length > 0)
{
break;
}
Thread.Sleep(200);
}
this.StopListening();
return response;
}
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
base.WriteBytes(message);
}
}
protected override void BeginRead(byte[] buffer)
{
var start = Array.IndexOf(buffer, this.encoder.Device2PC);
if (start >= 0)
{
if (this.encoder.TryDecode(buffer, out byte[] message))
{
this.EnqueueMessage(message);
this.RemoveRange(message.Length);
}
}
else
{
this.RemoveRange(buffer.Length);
}
}
}
}
@@ -29,8 +29,9 @@
public void ToASCIIString(byte[] buffer, int start, int end)
{
var value = string.Empty;
var length = buffer.Length;
while (start <= end)
while (start < length && start <= end)
{
value += (char)buffer[start];
start++;
@@ -62,13 +63,12 @@
{
var buffer = ASCII.GetBytes(value);
var bufferLength = buffer.Length;
var i = 0;
var bufferIndex = 0;
var i = 1;
while (i < this.length && i < bufferLength)
{
this.bytes[i] = buffer[i];
i++;
this.bytes[i++] = buffer[bufferIndex++];
}
}
}
@@ -88,9 +88,9 @@
get => this.programmableID;
set
{
this.SetASCIIBytes(value, 0, 20);
this.SetASCIIBytes(value, 1, 20);
this.programmableID = this.bytes.ToASCIIString(0, 20);
this.programmableID = this.bytes.ToASCIIString(1, 20);
}
}
@@ -105,9 +105,9 @@
get => this.factoryID;
set
{
this.SetASCIIBytes(value, 21, 13);
this.SetASCIIBytes(value, 22, 33);
this.factoryID = this.bytes.ToASCIIString(21, 13);
this.factoryID = this.bytes.ToASCIIString(22, 33);
}
}
@@ -139,9 +139,9 @@
get => this.readingPreset;
set
{
this.SetASCIIBytes(value, 38, 9);
this.SetASCIIBytes(value, 39, 47);
this.readingPreset = this.bytes.ToASCIIString(38, 9);
this.readingPreset = this.bytes.ToASCIIString(36, 47);
}
}
@@ -240,9 +240,9 @@
get => this.buildInfo;
set
{
this.SetASCIIBytes(value, 64, 14);
this.SetASCIIBytes(value, 65, 79);
this.buildInfo = this.bytes.ToASCIIString(64, 14);
this.buildInfo = this.bytes.ToASCIIString(65, 79);
}
}
@@ -257,13 +257,13 @@
get => this.deviceID;
set
{
this.SetASCIIBytes(value, 80, 9);
this.SetASCIIBytes(value, 81, 89);
this.deviceID = this.bytes.ToASCIIString(80, 9);
this.deviceID = this.bytes.ToASCIIString(81, 89);
}
}
private void SetASCIIBytes(string value, int start, int length)
private void SetASCIIBytes(string value, int start, int end)
{
if (string.IsNullOrWhiteSpace(value))
{
@@ -276,9 +276,7 @@
var asciiLength = asciiBytes.Length;
var asciiIndex = 0;
length += start;
while (start >= 0 && start < length && asciiIndex < asciiLength)
while (start >= 0 && start <= end && asciiIndex < asciiLength)
{
this.bytes[start++] = asciiBytes[asciiIndex++];
}
@@ -28,6 +28,6 @@
set => this.SecondsSince = (uint)(value - epoch).TotalSeconds;
}
public static uint UTCNow => new Epoch20000101 { DateTime = DateTime.UtcNow }.SecondsSince + 10;
public static uint UTCNow => new Epoch20000101 { DateTime = DateTime.UtcNow }.SecondsSince + 3;
}
}
@@ -26,7 +26,7 @@
this.Status = (Status)response[0];
}
if (responseLength > this.length)
if (responseLength > 1)
{
Array.Copy(response, 1, this.bytes, 0, this.length);
}
@@ -1,6 +1,6 @@
namespace OmniPlus.Features
{
internal class Features
public class Features
{
/// <summary>
/// The View Factory ID command shall cause the slave device to transmit the factory ID.
@@ -86,11 +86,11 @@
return subarray;
}
public static string ToASCIIString(this byte[] bytes, int start, int length)
public static string ToASCIIString(this byte[] bytes, int start, int end)
{
var asciiString = string.Empty;
while (start >= 0 && start < bytes.Length)
while (start >= 0 && end < bytes.Length && start < end)
{
asciiString += (char)bytes[start++];
}
@@ -44,6 +44,6 @@
set => this.bytes[5] = value;
}
public double MlPerRotation { get; set; }
public ushort IntPartFull => BitConverter.ToUInt16(this.bytes, 0);
}
}
@@ -1,6 +1,7 @@
namespace OmniPlus.Features
{
using OmniPlus.Features.Enums;
using System.Text;
/// <summary>
/// Versions B1.24 of this command are supported. Total Forward and Total Reverse are not supported.
@@ -18,10 +19,14 @@
/// </summary>
public class ReadingPreset : FeatureRequest
{
const int LENGTH = 2;
const int LENGTH = 11;
public ReadingPreset() : base(LENGTH)
{
for (int i = 2; i < 11; i++)
{
this.bytes[i] = (byte)'0';
}
}
public byte SensorID
@@ -52,14 +52,54 @@
public byte FlowUnits
{
get => this.bytes[8].GetUint8(0, 4);
set => FeaturesExtensions.SetUint8(ref this.bytes[8], 0, 4, value);
get
{
var src = this.bytes[8].GetBits();
var dst = new byte[8];
Array.Copy(src, 0, dst, 0, 4);
return dst.ToUint8();
}
set
{
var srcIndex = 0;
var srcBits = value.GetBits();
var dstBits = this.bytes[8].GetBits();
for (int dstIndex = 0; dstIndex < 4; dstIndex++)
{
dstBits[dstIndex] = srcBits[srcIndex++];
}
this.bytes[8] = dstBits.ToUint8();
}
}
public byte FlowRate
{
get => this.bytes[8].GetUint8(4, 4);
set => FeaturesExtensions.SetUint8(ref this.bytes[8], 4, 4, value);
get
{
var src = this.bytes[8].GetBits();
var dst = new byte[8];
Array.Copy(src, 4, dst, 0, 4);
return dst.ToUint8();
}
set
{
var srcIndex = 0;
var srcBits = value.GetBits();
var dstBits = this.bytes[8].GetBits();
for (int dstIndex = 4; dstIndex < 8; dstIndex++)
{
dstBits[dstIndex] = srcBits[srcIndex++];
}
this.bytes[8] = dstBits.ToUint8();
}
}
public sbyte FactoryCorrection
@@ -82,14 +122,54 @@
public byte PulseWidth
{
get => this.bytes[12].GetUint8(0, 3);
set => FeaturesExtensions.SetUint8(ref this.bytes[12], 0, 3, value);
get
{
var src = this.bytes[12].GetBits();
var dst = new byte[8];
Array.Copy(src, 0, dst, 0, 3);
return dst.ToUint8();
}
set
{
var srcIndex = 0;
var srcBits = value.GetBits();
var dstBits = this.bytes[12].GetBits();
for (int dstIndex = 0; dstIndex < 3; dstIndex++)
{
dstBits[dstIndex] = srcBits[srcIndex++];
}
this.bytes[12] = dstBits.ToUint8();
}
}
public byte PulseUpdate
{
get => this.bytes[12].GetUint8(3, 3);
set => FeaturesExtensions.SetUint8(ref this.bytes[12], 3, 3, value);
get
{
var src = this.bytes[12].GetBits();
var dst = new byte[8];
Array.Copy(src, 3, dst, 0, 3);
return dst.ToUint8();
}
set
{
var srcIndex = 0;
var srcBits = value.GetBits();
var dstBits = this.bytes[12].GetBits();
for (int dstIndex = 3; dstIndex < 6; dstIndex++)
{
dstBits[dstIndex] = srcBits[srcIndex++];
}
this.bytes[12] = dstBits.ToUint8();
}
}
}
}
@@ -1,41 +0,0 @@
namespace OmniPlus.Inspection
{
using System;
internal static class OmniPlusExtensions
{
public static double MlPerRotation(byte intPart, ushort fraction, short correctionFactor)
=> (intPart + (double)fraction / ushort.MaxValue) * correctionFactor;
public static double GPM2M3H(double value)
=> value * 3785.411784 / 1000 / 1000 * 60;
public static double GetCorrectionFactor(this double[] points)
{
if (points?.Length != 3)
{
return double.MinValue;
}
var min = points[0];
var mid = points[1];
var max = points[2];
if (Math.Abs(mid - max) <= 3 && Math.Max(mid, max) - min <= 6.5)
{
var avgMidMax = (mid + max) / 2;
if (100 - avgMidMax + min < 95)
{
return 95 - min;
}
else
{
return 100 - avgMidMax;
}
}
return double.MaxValue;
}
}
}
@@ -4,21 +4,85 @@
public static class OmniPlusFormulas
{
public static double MlPerRotation(byte intPart, ushort fraction, short correctionFactor)
public static double MilliliterPerRotation(byte intPart, ushort fraction, short correctionFactor)
{
return (intPart + (double)fraction / ushort.MaxValue) * correctionFactor;
const int FRACTION_FACTOR = ushort.MaxValue + 1;
const int PULSES_PER_ROTATION = 8;
var fractionPart = (double)fraction / FRACTION_FACTOR;
var mlPlain = intPart + fractionPart;
var mlPulse = intPart + fractionPart;
var mlr = mlPulse * PULSES_PER_ROTATION;
return mlr;
}
public static double GPM2M3H(double value)
public static double MilliliterPerRotation(this OmniPlusType type)
{
return value * 3785.411784 / 1000 / 1000 * 60;
return MilliliterPerRotation(type.IntPart, type.Fraction, type.CorrectionFactor);
}
public static double GPM2M3H(this double gal_min)
{
const double ML_IN_GAL = 3785.411784;
var ml_min = gal_min * ML_IN_GAL;
var l_min = ml_min / 1000;
var m3_min = l_min / 1000;
var m3_h = m3_min * 60;
return m3_h;
}
public static ushort DurationInSeconds(this ushort rotations, double mlr, double flowM3H)
{
var ml_h = flowM3H * 1000 * 1000;
var ml_s = ml_h / 3600;
var s_r = mlr / ml_s * 100;
var duration = s_r * rotations;
return (ushort)(Math.Truncate(duration) + 1);
}
public static ushort ResponseFlowM3H(this ushort rotations, double mlr, double flowM3H)
{
var ml_h = flowM3H * 1000 * 1000;
var ml_s = ml_h / 3600;
var s_r = mlr / ml_s * 100;
var duration = s_r * rotations;
return (ushort)(Math.Truncate(duration) + 1);
}
public static double DifferencePercentage(this OmniPlusTest test)
{
try
{
return 100 + (test.MeterFlowM3S - test.ReferenceFlowM3S) / test.ReferenceFlowM3S * 100;
}
catch
{
return -1;
}
}
public static double MeterFlowM3S(double rotations, double mlr, double duration)
{
var seconds = duration * (1D / (short.MaxValue + 1));
return rotations * mlr / seconds / 1000D / 1000D * 100;
}
public static double MeterFlowM3S(this OmniPlusTestPoint point, OmniPlusTest test)
{
return MeterFlowM3S(test.Rotations, point.MLR, test.Duration);
}
public static double GetCorrectionFactor(this double[] points)
{
if (points?.Length != 3)
if (points is null || points.Length != 3)
{
return double.MinValue;
return -1;
}
var min = points[0];
@@ -39,7 +103,7 @@
}
}
return double.MaxValue;
return -1;
}
}
}
@@ -6,23 +6,8 @@
public double Duration { get; set; }
public double MeterVolume { get; set; }
public double MeterFlowM3S { get; set; }
public double VolumeMessured { get; set; }
public double DifferencePercentage
{
get
{
try
{
return 100 + (this.MeterVolume - this.VolumeMessured) / this.VolumeMessured;
}
catch
{
return -1;
}
}
}
public double ReferenceFlowM3S { get; set; }
}
}
@@ -4,9 +4,29 @@
public struct OmniPlusTestPoint : IComparable<OmniPlusTestPoint>
{
public double GalPerMin { get; set; }
private double gpm;
public double GPM
{
get => this.gpm;
set
{
this.gpm = value;
this.RequiredFlowM3H = this.gpm.GPM2M3H();
}
}
public ushort Rotations { get; set; }
public ushort rotations;
public ushort Rotations
{
get => this.rotations;
set
{
this.rotations = value;
this.Duration = this.rotations.DurationInSeconds(this.MLR, this.RequiredFlowM3H);
}
}
public double MLR { get; set; }
public ushort Duration { get; set; }
@@ -14,25 +34,11 @@
public double MaxDiff { get; set; }
public double MlPerRotation { get; set; }
public double RequiredFlowM3H { get; private set; }
public double VolumeM3H
=> OmniPlusExtensions.GPM2M3H(this.GalPerMin);
public int CompareTo(OmniPlusTestPoint other)
=> this.Rotations.CompareTo(other.Rotations);
public double VolumeM3(double rotations, double duration)
public int CompareTo(OmniPlusTestPoint other)
{
var seconds = duration / 32768;
var milliliter = rotations * this.MlPerRotation;
return seconds * milliliter / 1000 / 1000;
}
public double VolumeM3(OmniPlusTest test)
{
return this.VolumeM3(test.Rotations, test.Duration);
return this.GPM.CompareTo(other.GPM);
}
}
}
@@ -42,18 +42,6 @@
public short CorrectionFactor { get; set; }
public double MlPerRotation
{
get
{
var mlPerRotation = OmniPlusExtensions.MlPerRotation(this.IntPart, this.Fraction, this.CorrectionFactor);
this.InputVolume.MlPerRotation = mlPerRotation;
return OmniPlusExtensions.MlPerRotation(this.IntPart, this.Fraction, this.CorrectionFactor);
}
}
public InputVolume InputVolume { get; }
= new InputVolume();
@@ -1,73 +1,19 @@
namespace OmniPlus
{
using OmniPlus.Connections;
using OmniPlus.Features;
using System;
using System.IO.Ports;
using static OmniPlus.Features.Features;
internal delegate byte[] MessageHandler(params byte[] bytes);
public delegate byte[] MessageHandler(params byte[] bytes);
public delegate void StateChanged(object state);
public sealed class OmniPlusConnection
public abstract class OmniConnection
{
private Func<bool> connected;
private readonly UI1236Stream ui1236;
private readonly UniProStream unipro;
protected MessageHandler MessageHandler { get; set; }
public OmniPlusConnection(string portName)
{
this.ui1236 = new UI1236Stream(new SerialPortSettings
{
BaudRate = 115200,
DataBits = 8,
Parity = Parity.None,
PortName = portName,
StopBits = StopBits.One
});
this.unipro = new UniProStream(new SerialPortSettings
{
BaudRate = 2400,
DataBits = 8,
Parity = Parity.None,
PortName = portName,
StopBits = StopBits.One
});
}
public abstract void Close();
internal MessageHandler MessageHandler;
public bool Connected
=> this.connected?.Invoke() ?? false;
public bool ConnectIrda()
{
this.unipro.Dispose();
this.ui1236.Open();
this.connected = () => this.ui1236.IsOpen;
this.MessageHandler = this.ui1236.Write;
return this.ui1236.IsOpen;
}
public bool ConnectUniPro()
{
this.ui1236.Dispose();
this.unipro.Open();
this.connected = () => this.unipro.IsOpen;
this.MessageHandler = this.unipro.Write;
return this.unipro.IsOpen;
}
public void Disconnect()
{
this.unipro.Dispose();
this.ui1236.Dispose();
}
public abstract void Open();
public FactoryID ViewFactoryID()
{
@@ -132,7 +78,7 @@
return new RateResolution(response);
}
public Readings ViewReadings(Readings reading)
public Readings ViewReadings()
{
var response = this.MessageHandler.Invoke(VIEW_READINGS);
@@ -153,6 +99,13 @@
return new BuildInfo(response);
}
public ChamberCalibrationResponse Set(ChamberCalibrationRequest chamberCalibrationRequest)
{
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, CHAMBER_CALIBRATION);
return new ChamberCalibrationResponse(response);
}
public SystemParameters ViewSystemParameters()
{
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_SYSTEM_PARAMETERS);
@@ -8,11 +8,11 @@
using System.IO;
using System.Linq;
public class OmniPlusDatabase
public class OmniDatabase
{
private readonly string connectionString;
public OmniPlusDatabase(string omniDatabase)
public OmniDatabase(string omniDatabase)
=> this.connectionString = omniDatabase;
public void AddOrUpdate(int position, SystemParameters parameters)
@@ -144,7 +144,7 @@
omniType.Direction = sqlDataReader.GetValue<byte>(field++);
omniType.IntPart = sqlDataReader.GetValue<byte>(field++);
omniType.Fraction = (ushort)sqlDataReader.GetValue<int>(field++);
omniType.PulsePerRotation = sqlDataReader.GetValue<double>(field++);
omniType.PulsePerRotation = sqlDataReader.GetValue<byte>(field++);
omniType.CorrectionFactor = sqlDataReader.GetValue<short>(field++);
}
}
@@ -168,7 +168,7 @@
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
var mlPerRotation = omniType.MlPerRotation;
var milliliterPerRotation = omniType.MilliliterPerRotation();
while (sqlDataReader.Read())
{
@@ -176,8 +176,8 @@
omniType.TestPoints.Add(new OmniPlusTestPoint
{
MlPerRotation = mlPerRotation,
GalPerMin = sqlDataReader.GetValue<double>(field++),
MLR = milliliterPerRotation,
GPM = sqlDataReader.GetValue<double>(field++),
Rotations = (ushort)sqlDataReader.GetValue<short>(field++),
Duration = (ushort)sqlDataReader.GetValue<short>(field++),
MinDiff = sqlDataReader.GetValue<double>(field++),
+30
View File
@@ -0,0 +1,30 @@
namespace OmniPlus
{
using System;
using ExchangeHub;
public class OmniExchange
{
private readonly ExchangeConnection connection;
public OmniExchange()
{
this.connection = new ExchangeConnection();
}
public void Connect(string url)
{
this.connection.Connect(url);
}
public void Disconnect()
{
this.connection.Disconnect();
}
public void StopFlow()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,71 @@
namespace OmniPlus
{
using OmniPlus.Connections;
using System;
using System.IO;
using System.IO.Ports;
public sealed class OmniIrdaConnection : OmniConnection
{
private readonly OmniIrdaStream stream;
private readonly string stateFile;
public OmniIrdaConnection(string portName)
{
this.stateFile = this.GetOrCreateStateFile(portName);
this.stream = new OmniIrdaStream(
encoder: new OmniIrdaEncoder(),
settings: new SerialPortSettings
{
BaudRate = 115200,
DataBits = 8,
Parity = Parity.None,
PortName = portName,
StopBits = StopBits.One
});
this.stream.StateChanged += this.OnStateChanged;
this.MessageHandler = this.stream.Send;
}
public override void Close()
{
this.stream.Close();
}
public override void Open()
{
this.stream.Open();
}
private void OnStateChanged(object state)
{
try
{
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fffffff}] {state}{Environment.NewLine}");
}
catch (Exception e)
{
try
{
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fffffff}] {e}");
}
catch (Exception _)
{
// TODO: throw;
}
}
}
private string GetOrCreateStateFile(string portName)
{
var stateFile = $"{portName}_{DateTime.Now:yyyy_MM_dd}.txt";
var directory = Directory.CreateDirectory(".\\OmniIrda");
stateFile = Path.Combine(directory.FullName, stateFile);
File.AppendAllText(stateFile, string.Empty);
return stateFile;
}
}
}
+38
View File
@@ -0,0 +1,38 @@
namespace OmniPlus
{
using System.Collections.Generic;
public sealed class OmniIrdaEOL
{
private readonly IDictionary<int, OmniConnection> connections;
private readonly IDictionary<int, OmniMeter> meters;
private readonly OmniExchange exchangeHub;
private readonly OmniDatabase database;
public OmniIrdaEOL(string connectionString)
{
this.connections = new Dictionary<int, OmniConnection>();
this.meters = new Dictionary<int, OmniMeter>();
this.exchangeHub = new OmniExchange();
this.database = new OmniDatabase(connectionString);
}
public void AddConnection(string portName)
{
var nr = this.connections.Count + 1;
this.connections[nr] = new OmniIrdaConnection(portName);
this.meters[nr] = new OmniMeter();
}
public void Clear()
{
foreach (var connection in this.connections.Values)
{
connection.Close();
}
this.connections.Clear();
this.meters.Clear();
}
}
}
+6
View File
@@ -0,0 +1,6 @@
namespace OmniPlus
{
public class OmniMeter
{
}
}
+18 -14
View File
@@ -46,19 +46,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Connections\IrdaEncoder.cs" />
<Compile Include="Connections\IrdaStream.cs" />
<Compile Include="Connections\Program.cs" />
<Compile Include="Connections\OmniIrdaEncoder.cs" />
<Compile Include="Connections\OmniIrdaStream.cs" />
<Compile Include="Connections\OmniUniProEncoder.cs" />
<Compile Include="Connections\OmniUniProStream.cs" />
<Compile Include="Connections\SerialDataEncoder.cs" />
<Compile Include="Connections\SerialDataExtensions.cs" />
<Compile Include="Connections\SerialDataReader.cs" />
<Compile Include="Connections\SerialDataStream.cs" />
<Compile Include="Connections\SerialPortSettings.cs" />
<Compile Include="Connections\SerialPortStream.cs" />
<Compile Include="Connections\UI1236Encoder.cs" />
<Compile Include="Connections\UI1236Stream.cs" />
<Compile Include="Connections\UniProEncoder.cs" />
<Compile Include="Connections\UniProStream.cs" />
<Compile Include="Connections\UI1236Control.cs" />
<Compile Include="Features\Enums\MessurementUnits.cs" />
<Compile Include="Features\Enums\ReadingSettings.cs" />
<Compile Include="Features\Enums\Status.cs" />
@@ -98,14 +95,16 @@
<Compile Include="Features\SystemTime.cs" />
<Compile Include="Features\VersionAndType.cs" />
<Compile Include="Inspection\OmniPlusFormulas.cs" />
<Compile Include="OmniPlusConnection.cs" />
<Compile Include="OmniPlusConnectionsPool.cs" />
<Compile Include="OmniPlusDatabase.cs" />
<Compile Include="Inspection\OmniPlusExtensions.cs" />
<Compile Include="OmniConnection.cs" />
<Compile Include="OmniExchange.cs" />
<Compile Include="OmniIrdaEOL.cs" />
<Compile Include="OmniIrdaConnection.cs" />
<Compile Include="OmniMeter.cs" />
<Compile Include="OmniDatabase.cs" />
<Compile Include="Inspection\OmniPlusTest.cs" />
<Compile Include="Inspection\OmniPlusTestPoint.cs" />
<Compile Include="Inspection\OmniPlusType.cs" />
<Compile Include="Connections\UI1236Control.cs" />
<Compile Include="OmniUniProConnection.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@@ -115,6 +114,11 @@
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\..\ExchangeHub\ExchangeHub.csproj">
<Project>{6033FF0C-CF32-4BC5-8EFE-4774CCDC663D}</Project>
<Name>ExchangeHub</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -1,498 +0,0 @@
using OmniPlus.Features;
using OmniPlus.Inspection;
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
namespace OmniPlus
{
public class OmniPlusConnectionsPool : IDisposable
{
public event Action Done;
private readonly ConcurrentDictionary<int, OmniPlusConnection> connections;
private readonly ConcurrentDictionary<int, OmniPlusMeter> meters;
private readonly CancellationTokenSource cancellationTokenSource;
private readonly CancellationToken cancellationToken;
private readonly OmniPlusExchangeSlave exchangeSlave;
private readonly OmniPlusDatabase database;
private readonly OmniPlusType omniType;
private byte size;
private string variant;
private BackgroundWorker background;
public OmniPlusConnectionsPool(string dbConnectionString, string signalRURL)
{
this.connections = new ConcurrentDictionary<int, OmniPlusConnection>();
this.meters = new ConcurrentDictionary<int, OmniPlusMeter>();
this.cancellationTokenSource = new CancellationTokenSource();
this.exchangeSlave = new OmniPlusExchangeSlave(signalRURL);
this.database = new OmniPlusDatabase(dbConnectionString);
this.omniType = new OmniPlusType();
this.size = 5;
this.variant = "C2";
this.cancellationToken = this.cancellationTokenSource.Token;
this.cancellationToken.Register(this.CancellationCallback);
}
public void Dispose()
{
this.exchangeSlave.Dispose();
// Disposes all OmniPlus connections.
foreach (var connectionKVP in this.connections)
{
connectionKVP.Value?.Disconnect();
}
// Clears collected connections and their meters.
this.connections.Clear();
this.meters.Clear();
}
public void InitializeInspection(params string[] portNames)
{
OmniPlusConnection connection;
OmniPlusMeter meter;
int position = 1;
bool connected;
foreach (var portName in portNames)
{
connection = new OmniPlusConnection(portName);
connected = connection.ConnectIrda();
if (connected)
{
}
else
{
connection.Disconnect();
connection = default(OmniPlusConnection);
meter = default(OmniPlusMeter);
}
this.connections.TryAdd(position, connection);
position++;
}
this.database.LoadOmniDefaults(this.size, this.variant, this.omniType);
}
public void CancelExecution()
=> this.cancellationTokenSource.Cancel(false);
//public void StartInspection()
//{
// foreach (var position in this.connections.Keys)
// {
// this.StartOmniInitialization(position);
// //foreach (var point in this.omniType.TestPoints)
// //{
// // this.StartOmniInspection(position, point);
// //}
// //this.CalculateCorrectionFactor(position);
// this.FinishOmniInspection(position);
// }
//}
public void StartInspection()
{
this.background = new BackgroundWorker();
this.background.DoWork += this.StartInspection;
this.background.RunWorkerAsync();
}
private void StartInspection(object sender, EventArgs args)
{
var connectionsCount = this.connections.Count;
var tasks = new Task[connectionsCount];
foreach (var position in this.connections.Keys)
{
tasks[position - 1] = Task.Factory.StartNew(() => this.StartOmniInitialization(position), this.cancellationToken);
}
foreach (var point in this.omniType.TestPoints)
{
// TODO: 600 = 10min * 60sec - change for production.
//if (!this.exchangeSlave.SetQAndWaitUntilReached(point.VolumeM3H))
//{
// this.CancelExecution();
// break;
//}
tasks = new Task[connectionsCount];
foreach (var position in this.connections.Keys)
{
tasks[position - 1] = Task.Factory.StartNew(() => this.StartOmniInspection(position, point), this.cancellationToken);
}
//var volume = this.exchangeSlave.RequestRefV();
//foreach (var position in this.connections.Keys)
//{
// this.SetPointDifference(position, point, volume);
//}
}
foreach (var position in this.connections.Keys)
{
this.CalculateCorrectionFactor(position);
}
tasks = new Task[connectionsCount];
foreach (var position in this.connections.Keys)
{
tasks[position - 1] = Task.Factory.StartNew(() => this.FinishOmniInspection(position), this.cancellationToken);
}
this.Done?.Invoke();
}
private void StartOmniInitialization(int position)
{
if (this.TryGetOmni(position, out var connection, out var meter))
{
var systemParameters = connection.ViewSystemParameters();
// connection.Set(this.omniType.InputVolume).Succeeded;
}
else
{
}
}
private void StartOmniInspection(int position, OmniPlusTestPoint point)
{
var header = $"{point.VolumeM3H:0.0000}m³/h";
if (this.TryGetOmni(position, out var connection, out var meter) /*&& meter.Initialized && meter.CanCalibrate*/)
{
var activationResponse = connection.StartChamberCalibration(point.Rotations, point.Duration);
if (activationResponse.Succeeded)
{
var calibrationResult = new ChamberCalibrationResponse();
var duration = point.Duration + 3;
this.NotifyWhileThreadSleep(position, header, point.Duration + 3);
for (int i = 0; i < 3; i++)
{
calibrationResult = connection.ViewChamberCalibration();
if (calibrationResult.Succeeded)
{
break;
}
Thread.Sleep(1000);
}
}
else // activation failed
{
}
}
else // not connected
{
}
}
private void SetPointDifference(int position, OmniPlusTestPoint point, double volume)
{
//var header = $"{point.VolumeM3H:0.0000}m³/h";
//if (this.TryGetOmni(position, out var _, out var meter) && meter.Initialized && meter.CanCalibrate)
//{
// var difference = meter.AddCalibrationVolume(point, volume);
// this.StateChanged?.Invoke(position, 0, header, $"{difference:0.00}%");
//}
//else // not connected
//{
// this.StateChanged?.Invoke(position, 0, header, null);
//}
}
private void CalculateCorrectionFactor(int position)
{
//if (this.TryGetOmni(position, out var _, out var meter) && meter.Initialized && meter.CanCalibrate)
//{
// var correctionFactor = meter.GetCorrectionFactor();
// this.StateChanged?.Invoke(position, meter.CanCalibrate ? 1 : -1, CORRECTION, $"{correctionFactor:0.00}%");
//}
//else // not connected
//{
// this.StateChanged?.Invoke(position, 0, CORRECTION, null);
//}
}
private void FinishOmniInspection(int position)
{
//if (this.TryGetOmni(position, out var connection, out var meter)/* && meter.Calibrated*/)
//{
// var configurationParameters = connection.ViewConfigurationParameters();
// var canContinue = configurationParameters.Succeeded;
// if (canContinue)
// {
// meter.AddConfigurationParameters(configurationParameters);
// this.database.AddOrUpdate(position, configurationParameters);
// }
// if (canContinue)
// {
// // TODO: Uncomment in production
// //var systemTimeReset = connection.SetSystemTime();
// //canContinue = systemTimeReset.Succeeded;
// }
// if (canContinue)
// {
// var registerSettings = new RegisterSettings();
// registerSettings.IntPart = this.omniType.IntPart;
// registerSettings.Fraction = this.omniType.Fraction;
// registerSettings.Size = this.omniType.Size;
// registerSettings.Range = this.omniType.Range;
// registerSettings.VolumePerPulseUnit = 0x00;
// registerSettings.MeterUnits = (byte)MessurementUnits.USGallons;
// registerSettings.FlowUnits = (byte)MessurementUnits.USGallons;
// registerSettings.FlowRate = (byte)TimeUnits.Minutes;
// registerSettings.FactoryCorrection = meter.FactoryCorrection;
// registerSettings.FieldCorrection = 0x00;
// registerSettings.PulseWeight = 0x01;
// registerSettings.PulseWidth = 0x02;
// registerSettings.PulseUpdate = 0x00;
// var response = connection.Set(registerSettings);
// canContinue = response.Succeeded;
// if (canContinue)
// {
// meter.AddRegisterSettings(registerSettings);
// }
// }
// if (canContinue)
// {
// var configurationParametersSet = new ConfigurationParametersSet();
// configurationParametersSet.ProgrammableID = "816232411983";
// configurationParametersSet.FactoryID = "816232411983";
// configurationParametersSet.NumberOfReadingDigits = 8; // meter.ReadingDigits;
// configurationParametersSet.ReadingPreset = "000000000";
// configurationParametersSet.OptionalUniDirFields = 1; // meter.OptionalUniDirFields;
// configurationParametersSet.AlarmPercistancePeriodDays = 31;
// configurationParametersSet.DataLogIntervalMinutes = 60;
// configurationParametersSet.ManifacturingTime = Epoch20000101.UTCNow - 30000; // meter.ManifacturingTime;
// configurationParametersSet.SystemTime = Epoch20000101.UTCNow;
// configurationParametersSet.RebootCount = 0;
// configurationParametersSet.BuildInfo = "816232411983"; // meter.BuildInfo;
// // configurationParametersSet.DeviceID = "OMNI-01";
// var response = connection.Set(configurationParametersSet);
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.ClearDisplay();
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.Set(new LeakAlarm
// {
// FlowRateGal = 0.25F, // 0.25 gpm
// TimeLimit = 24 * 60 * 60 // 24 hours => 86400sec
// });
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.Set(new HighFlowAlarm
// {
// FlowRateGal = 25F, // 25 gpm
// TimeLimit = 1 * 60 * 60 // 1 hours => 86400sec
// });
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.Set(new ReverseFlowAlarm
// {
// FlowRateGal = -1F, // -1 gpm
// TimeLimit = 60 // 1 hours => 86400sec
// });
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.ClearAlarms();
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var alarmsState = connection.ViewAlarmsState();
// canContinue = alarmsState.Succeeded;
// //&& alarmsState.UsrEnabled
// //&& alarmsState.PreEnabledInactive;
// //TODO: Check alarms
// }
// if (canContinue)
// {
// var response = connection.EnableNFC();
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var registerSettingsAfter = connection.ViewRegisterSettings();
// canContinue = registerSettingsAfter.Succeeded
// && meter.Compare(registerSettingsAfter);
// }
// if (canContinue)
// {
// var systemParametersAfter = connection.ViewSystemParameters();
// canContinue = systemParametersAfter.Succeeded;
// //&& meter.Compare(systemParametersAfter);
// }
// if (canContinue)
// {
// var configurationParametersAfter = connection.ViewConfigurationParameters();
// canContinue = configurationParametersAfter.Succeeded;
// //&& meter.Compare(configurationParametersAfter);
// }
// if (canContinue)
// {
// var alarmsState = connection.ViewAlarmsState();
// canContinue = alarmsState.Succeeded;
// //&& alarmsState.UsrEnabled
// //&& alarmsState.PreEnabledInactive;
// }
// if (canContinue)
// {
// var response = connection.ViewAlarmSettings(0x01);
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.ViewAlarmSettings(0x02);
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// var response = connection.ViewAlarmSettings(0x04);
// canContinue = response.Succeeded;
// }
// if (canContinue)
// {
// //connection.Set(new FactorySeal
// //{
// // Sealed = true,
// //});
// //var factorySeal = connection.ViewFactorySeal();
// //canContinue = factorySeal.Succeeded && factorySeal.Sealed;
// }
//}
//else // meter or connection not in use
//{
//}
}
/// <summary>
/// Returns only connected connections and meters.
/// </summary>
/// <param name="position">The position of connection and meter.</param>
/// <param name="connection"><see cref="OmniPlusConnection"/></param>
/// <param name="meter"><see cref="OmniPlusMeter"/></param>
/// <returns>Returns true if connection and meter are found and are not null and the meter is connected, otherwise false.</returns>
private bool TryGetOmni(int position, out OmniPlusConnection connection, out OmniPlusMeter meter)
{
var connectionFound = this.connections.TryGetValue(position, out connection);
var meterFound = this.meters.TryGetValue(position, out meter);
return connectionFound
&& connection != null
&& meterFound
&& meter != null;
}
private void NotifyWhileThreadSleep(int position, string header, int duration)
{
//var seconds = 0;
//var timer = new System.Timers.Timer(1000)
//{
// Enabled = true,
// AutoReset = true,
//};
//timer.Elapsed += (_, _1) =>
//{
// this.StateChanged?.Invoke(position, 0, header, $"{seconds++}/{duration}");
//};
//timer.Start();
//Thread.Sleep(duration * 1000);
//timer.Stop();
}
private void CancellationCallback()
{
// TODO: Update database.
this.Dispose();
}
}
internal class OmniPlusExchangeSlave
{
private String signalRURL;
public OmniPlusExchangeSlave(String signalRURL)
{
this.signalRURL = signalRURL;
}
internal void Dispose()
{
throw new NotImplementedException();
}
}
internal class OmniPlusMeter
{
}
}
+7 -89
View File
@@ -45,119 +45,37 @@ CREATE TABLE [OmniTestPoints] (
INSERT INTO [OmniTestPoints]
([OmniTypeId], [OmniVariant], [GalPerMin], [Rotations], [Duration], [MinDiff], [MaxDiff])
------------------------------------------------------------------------------------------
VALUES ( 1, 'C2', 200.00, 900, 36, NULL, NULL)
, ( 1, 'C2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'C2', 150.00, 600, 32, NULL, NULL)
, ( 1, 'C2', 2.50, 10, 32, NULL, NULL)
, ( 1, 'C2', 2.00, 8, 32, NULL, NULL)
, ( 1, 'C2', 1.50, 6, 32, NULL, NULL)
, ( 1, 'C2', 1.25, 6, 38, NULL, NULL)
VALUES ( 1, 'C2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'C2', 1.00, 4, 32, 98.5, 101.5)
, ( 1, 'C2', 0.75, 4, 43, NULL, NULL)
, ( 1, 'C2', 0.25, 4, 127, 95.0, 101.5)
------------------------------------------------------------------------------------------
, ( 1, 'F2', 200.00, 900, 36, NULL, NULL)
, ( 1, 'F2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'F2', 150.00, 600, 32, NULL, NULL)
, ( 1, 'F2', 2.50, 10, 32, NULL, NULL)
, ( 1, 'F2', 2.00, 8, 32, NULL, NULL)
, ( 1, 'F2', 1.50, 6, 32, NULL, NULL)
, ( 1, 'F2', 1.25, 6, 38, NULL, NULL)
, ( 1, 'F2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'F2', 1.00, 4, 32, 98.5, 101.5)
, ( 1, 'F2', 0.75, 4, 43, NULL, NULL)
, ( 1, 'F2', 0.25, 4, 127, 95.0, 101.5)
------------------------------------------------------------------------------------------
, ( 1, 'R2', 200.00, 900, 36, NULL, NULL)
, ( 1, 'R2', 160.00, 700, 35, NULL, NULL)
, ( 1, 'R2', 150.00, 600, 32, 98.5, 101.5)
, ( 1, 'R2', 2.50, 10, 32, NULL, NULL)
, ( 1, 'R2', 2.00, 8, 32, 98.5, 101.5)
, ( 1, 'R2', 1.50, 6, 32, NULL, NULL)
, ( 1, 'R2', 1.25, 6, 38, NULL, NULL)
, ( 1, 'R2', 1.00, 4, 32, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 1, 'R2', 150.00, 600, 32, 98.5, 101.5)
, ( 1, 'R2', 2.00, 8, 32, 98.5, 101.5)
, ( 1, 'R2', 0.75, 4, 43, 95.0, 101.5)
, ( 1, 'R2', 0.25, 4, 127, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 1, 'T2', 200.00, 900, 36, NULL, NULL)
, ( 1, 'T2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'T2', 150.00, 600, 32, NULL, NULL)
, ( 1, 'T2', 2.50, 10, 32, NULL, NULL)
, ( 1, 'T2', 2.00, 8, 32, NULL, NULL)
, ( 1, 'T2', 1.50, 6, 32, NULL, NULL)
, ( 1, 'T2', 160.00, 700, 35, 98.5, 101.5)
, ( 1, 'T2', 1.25, 6, 38, 98.5, 101.5)
, ( 1, 'T2', 1.00, 4, 32, NULL, NULL)
, ( 1, 'T2', 0.75, 4, 43, 95.0, 101.5)
, ( 1, 'T2', 0.25, 4, 127, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 2, 'C2', 200.00, 1000, 40, NULL, NULL)
, ( 2, 'C2', 160.00, 800, 40, 98.5, 101.5)
, ( 2, 'C2', 2.50, 10, 32, NULL, NULL)
, ( 2, 'C2', 1.50, 8, 43, NULL, NULL)
, ( 2, 'C2', 1.00, 4, 32, 98.5, 101.5)
, ( 2, 'C2', 0.25, 4, 127, 95.0, 101.5)
------------------------------------------------------------------------------------------
, ( 2, 'F2', 200.00, 1000, 40, NULL, NULL)
, ( 2, 'F2', 160.00, 800, 40, 98.5, 101.5)
, ( 2, 'F2', 2.50, 10, 32, NULL, NULL)
, ( 2, 'F2', 1.50, 8, 43, NULL, NULL)
, ( 2, 'F2', 1.00, 4, 32, 98.5, 101.5)
, ( 2, 'F2', 0.25, 4, 127, 95.0, 101.5)
------------------------------------------------------------------------------------------
, ( 2, 'R2', 200.00, 1000, 40, 98.5, 101.5)
, ( 2, 'R2', 160.00, 800, 40, NULL, NULL)
, ( 2, 'R2', 2.50, 10, 32, 98.5, 101.5)
, ( 2, 'R2', 1.50, 8, 43, NULL, NULL)
, ( 2, 'R2', 1.00, 4, 32, 95.0, 101.5)
, ( 2, 'R2', 0.25, 4, 127, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 2, 'T2', 200.00, 1000, 40, 98.5, 101.5)
, ( 2, 'T2', 160.00, 800, 40, NULL, NULL)
, ( 2, 'T2', 2.50, 10, 32, NULL, NULL)
, ( 2, 'T2', 1.50, 8, 43, 98.5, 101.5)
, ( 2, 'T2', 1.00, 4, 32, 95.0, 101.5)
, ( 2, 'T2', 0.25, 4, 127, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 3, NULL, 500.00, 700, 38, NULL, NULL)
, ( 3, NULL, 400.00, 580, 40, NULL, NULL)
, ( 3, NULL, 350.00, 450, 35, NULL, NULL)
, ( 3, NULL, 20.00, 30, 41, NULL, NULL)
, ( 3, NULL, 10.00, 16, 44, NULL, NULL)
, ( 3, NULL, 2.50, 4, 44, NULL, NULL)
, ( 3, NULL, 2.00, 4, 55, NULL, NULL)
, ( 3, NULL, 1.50, 4, 73, NULL, NULL)
, ( 3, NULL, 0.50, 4, 217, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 4, NULL, 1000.00, 1200, 33, NULL, NULL)
, ( 4, NULL, 800.00, 1100, 38, NULL, NULL)
, ( 4, NULL, 30.00, 40, 37, NULL, NULL)
, ( 4, NULL, 3.00, 4, 37, NULL, NULL)
, ( 4, NULL, 2.00, 4, 55, NULL, NULL)
, ( 4, NULL, 1.50, 4, 73, NULL, NULL)
, ( 4, NULL, 0.75, 4, 145, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 5, NULL, 2000.00, 800, 39, NULL, NULL)
, ( 5, NULL, 1600.00, 660, 40, NULL, NULL)
, ( 5, NULL, 50.00, 20, 39, NULL, NULL)
, ( 5, NULL, 5.00, 4, 77, NULL, NULL)
, ( 5, NULL, 4.00, 4, 96, NULL, NULL)
, ( 5, NULL, 3.00, 4, 127, NULL, NULL)
, ( 5, NULL, 2.50, 4, 153, NULL, NULL)
, ( 5, NULL, 1.50, 4, 254, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 6, NULL, 3500.00, 500, 34, NULL, NULL)
, ( 6, NULL, 2700.00, 400, 36, NULL, NULL)
, ( 6, NULL, 7.00, 4, 136, NULL, NULL)
, ( 6, NULL, 5.00, 4, 191, NULL, NULL)
, ( 6, NULL, 4.00, 4, 238, NULL, NULL)
, ( 6, NULL, 3.00, 4, 317, NULL, NULL)
, ( 6, NULL, 2.50, 4, 381, NULL, NULL)
------------------------------------------------------------------------------------------
, ( 7, NULL, 5500.00, 550, 36, NULL, NULL)
, ( 7, NULL, 4000.00, 400, 36, NULL, NULL)
, ( 7, NULL, 2500.00, 260, 37, NULL, NULL)
, ( 7, NULL, 14.00, 4, 102, NULL, NULL)
, ( 7, NULL, 5.00, 4, 284, NULL, NULL)
, ( 7, NULL, 3.50, 4, 406, NULL, NULL);
, ( 2, 'T2', 1.00, 4, 32, 95.0, 101.5);
CREATE TABLE [OmniTestStates] (
[Position] INT NOT NULL,
@@ -0,0 +1,65 @@
namespace OmniPlus
{
using OmniPlus.Connections;
using System;
using System.IO;
using System.IO.Ports;
public class OmniUniProConnection : OmniConnection
{
private readonly OmniUniProStream stream;
private readonly string stateFile;
public OmniUniProConnection(string portName)
{
this.stateFile = this.GetOrCreateStateFile(portName);
this.stream = new OmniUniProStream(
encoder: new OmniUniProEncoder(),
settings: new SerialPortSettings
{
BaudRate = 2400,
DataBits = 8,
Parity = Parity.None,
PortName = portName,
StopBits = StopBits.One
});
this.stream.StateChanged += this.OnStateChanged;
this.MessageHandler = this.stream.Send;
}
public override void Close()
{
this.stream.Close();
}
public override void Open()
{
this.stream.Open();
}
private void OnStateChanged(object state)
{
try
{
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {state}{Environment.NewLine}");
}
catch (Exception)
{
// TODO: throw;
}
}
private string GetOrCreateStateFile(string portName)
{
var stateFile = $"{portName}_{DateTime.Now:yyyy_MM_dd}.txt";
var directory = Directory.CreateDirectory(".\\OmniUniPro");
stateFile = Path.Combine(directory.FullName, stateFile);
File.AppendAllText(stateFile, string.Empty);
return stateFile;
}
}
}