PAM 146 in Common.UI

This commit is contained in:
Stoyan Zlatev 2025-06-11 09:29:41 +02:00
parent 27be2f507c
commit 0f0bc7af43
21 changed files with 710 additions and 37 deletions

View File

@ -155,7 +155,7 @@
</site>
<site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\LAA_PRODUCTION\Common\Service\MeterProcessState" />
<virtualDirectory path="/" physicalPath="C:\Users\SZLATEV\source\repos\laa_production\Common\Service\MeterProcessState" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" />

View File

@ -1,20 +1,20 @@
namespace CommonConsole
{
using Common.Hardware.WaterMeter.eRegister.Telegrams;
using Microsoft.SharePoint.Client;
using System;
using System.Security;
public static class Program
{
public static void Main()
{
var semiBytes25747925 = new byte[] { 0x08, 0x03, 0x12, 0x6B, 0x78, 0x41, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x83, 0x0C, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x13, 0x01, 0x88, 0xE1, 0xD5, 0x07, 0x0E, 0x10, 0xEC, 0x56, 0x13, 0xDA, 0x4C, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x1E, 0x00, 0x03, 0x01, 0x2F, 0xBE, 0xCA, 0x47, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xEF, 0xA6 };
var semi25747925 = new SEMI(semiBytes25747925, 868, 0);
var x = (625L * 65536) | 0x80_00_00_00;
var debugBytes25747925 = new byte[] { 0x0B, 0x10, 0x12, 0x6B, 0x78, 0x41, 0x00, 0x0C, 0x11, 0x0B, 0x11, 0x08, 0x04, 0x02, 0x7C, 0x4C, 0x12, 0x84, 0x15, 0x00, 0x66, 0x00, 0x35, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x8F, 0xD2, 0x02, 0x01, 0x01, 0x16, 0x00, 0x1B, 0x02, 0x71, 0x00, 0x00, 0x82, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA0, 0xA5 };
var debug25747925 = new DEBUG(debugBytes25747925, 0);
Console.WriteLine((int)x);
//var semiBytes25747925 = new byte[] { 0x08, 0x03, 0x12, 0x6B, 0x78, 0x41, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x83, 0x0C, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x13, 0x01, 0x88, 0xE1, 0xD5, 0x07, 0x0E, 0x10, 0xEC, 0x56, 0x13, 0xDA, 0x4C, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x1E, 0x00, 0x03, 0x01, 0x2F, 0xBE, 0xCA, 0x47, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xEF, 0xA6 };
//var semi25747925 = new SEMI(semiBytes25747925, 868, 0);
//var debugBytes25747925 = new byte[] { 0x0B, 0x10, 0x12, 0x6B, 0x78, 0x41, 0x00, 0x0C, 0x11, 0x0B, 0x11, 0x08, 0x04, 0x02, 0x7C, 0x4C, 0x12, 0x84, 0x15, 0x00, 0x66, 0x00, 0x35, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x8F, 0xD2, 0x02, 0x01, 0x01, 0x16, 0x00, 0x1B, 0x02, 0x71, 0x00, 0x00, 0x82, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA0, 0xA5 };
//var debug25747925 = new DEBUG(debugBytes25747925, 0);
//var siteUrl = "https://1xylemeur.sharepoint.com/sites/geckoSrc/customer/Pub_CSD/Forms/AllItems.aspx";

View File

@ -81,7 +81,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
public static readonly String StartHit = "GENESISFLOW_StartHit";
public static readonly String NumFirePulses = "GENESISFLOW_NumFirePulses";
public static readonly String LookupFileCrc = "GENESISFLOW_LookupFileCrc";
public static readonly String DisplayUnits = "GENESISFLOW_DisplayUnits";
public static readonly String SealDisplay = "GENESISFLOW_SealDisplay";
};
public static class Powermon

View File

@ -49,6 +49,7 @@
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@ -96,6 +97,7 @@
<Compile Include="Features\LogContent.cs" />
<Compile Include="Features\MBusMode.cs" />
<Compile Include="Features\MessurementUnits.cs" />
<Compile Include="Features\MeterSizes.cs" />
<Compile Include="Features\MeterTypes.cs" />
<Compile Include="Features\FactoryState.cs" />
<Compile Include="Features\OpenMeteringTransmitionIntervalWMBus.cs" />

View File

@ -89,8 +89,7 @@
private EregisterProgrammingParameters GetProgrammingParameters()
{
var alarms = new AlarmsMask(this.SEMIMessage.AlarmActiveInformation);
var alarms = this.SEMIMessage.AlarmActiveInformation;
var dataLogContent = new ChangeDataLoggerSettings();
dataLogContent.SetLogContent(this.SEMIMessage.LogContent);
@ -113,7 +112,7 @@
OffsetTime = this.DEBUGMessage.OffsetTime,
FactoryCalibration = (byte)(this.DEBUGMessage.FactoryCalibration * 10),
UnitsOfMessureSEMI = (byte)this.SEMIMessage.Units,
MeterSize = this.SEMIMessage.MeterSize,
MeterSize = (byte)this.SEMIMessage.MeterSize,
Alarm_Backflow = alarms.Backflow,
Alarm_Broken_Pipe = alarms.BrokenPipe,
Alarm_Leakage = alarms.Leak,

View File

@ -1,6 +1,7 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
using Common.Hardware.SIRT;
using System.Text;
public class AlarmsMask : Pam
{
@ -66,5 +67,21 @@
return base.ToByteArray();
}
public override System.String ToString()
{
var alarmMaskBuilder = new StringBuilder();
alarmMaskBuilder.AppendLine($"{nameof(this.SpecificError)}: {this.SpecificError}");
alarmMaskBuilder.AppendLine($"{nameof(this.MediumAbsent)}: {this.MediumAbsent}");
alarmMaskBuilder.AppendLine($"{nameof(this.BrokenPipe)}: {this.BrokenPipe}");
alarmMaskBuilder.AppendLine($"{nameof(this.Backflow)}: {this.Backflow}");
alarmMaskBuilder.AppendLine($"{nameof(this.MetrologyUnavailable)}: {this.MetrologyUnavailable}");
alarmMaskBuilder.AppendLine($"{nameof(this.MagneticTamper)}: {this.MagneticTamper}");
alarmMaskBuilder.AppendLine($"{nameof(this.Leak)}: {this.Leak}");
alarmMaskBuilder.AppendLine($"{nameof(this.LowBattery)}: {this.LowBattery}");
return alarmMaskBuilder.ToString().Trim(); ;
}
}
}

View File

@ -2,15 +2,15 @@
{
public enum MessurementUnits : byte
{
CubicMeters = 0,
Cubic_Meters = 0,
m3 = 19,
CubicFeet = 1,
Cubic_Feet = 1,
CF = 35,
USGallons = 4,
US_Gallons = 4,
GAL = 24,
ImperialGallons = 5,
Imperial_Gallons = 5,
IGAL = 144,
AcreFeet = 6,
Acre_Feet = 6,
Kiloliters = 7,
kl = 19,
}

View File

@ -0,0 +1,29 @@
namespace Common.Hardware.WaterMeter.eRegister.Features
{
public enum MeterSizes
{
Meistream__DN40 = 23,
Meistream__DN50 = 24,
Meistream__DN65 = 25,
Meistream__DN80 = 26,
Meistream__DN100 = 27,
Meistream__DN125 = 28,
Meistream__DN150 = 29,
Meistream__DN200 = 30,
Meistream__DN250 = 31,
Meistream__DN300 = 32,
Meistream__Plus__DN40 = 36,
Meistream__Plus__DN50 = 37,
Meistream__Plus__DN65 = 38,
Meistream__Plus__DN80 = 39,
Meistream__Plus__DN100 = 40,
Meistream__Plus__DN150 = 41,
Meitwin__DN50 = 45,
Meitwin__DN65 = 46,
Meitwin__DN80 = 47,
Meitwin__DN100 = 48,
Meitwin__MB = 49,
WPV__MS__DN150 = 56,
Nebenzaehler__DN4 = 53,
}
}

View File

@ -4,5 +4,7 @@
{
Residential = 0,
CandI = 1,
Residential__0x0B = 11,
CandI__0x0C = 12,
}
}

View File

@ -31,7 +31,7 @@
this.RegisterMode = payload[34];
this.HistorySize = payload[35];
this.FactoryCalibration = payload[36] / 10F;
this.MeterSize = payload[37];
this.MeterSize = (MeterSizes)payload[37];
this.VolumePerLedPulse = payload.ToUInt32BE(38);
this.VolumePerPulse = payload.ToInt32BE(42);
this.OffsetFactor = payload.ToInt32BE(46);
@ -89,7 +89,7 @@
public float FactoryCalibration { get; }
public byte MeterSize { get; }
public MeterSizes MeterSize { get; }
public uint VolumePerLedPulse { get; }

View File

@ -15,7 +15,7 @@
{
this.PAMStatus = new PAMStatus(payload[11]);
this.RSSI = new RSSI(payload[12], mhz);
this.MeterType = payload[13];
this.MeterType = (MeterTypes)payload[13];
this.TransmissionInterval = payload.ToUInt16BE(14);
this.LATInterval = payload[16];
this.CurrentFlow = payload.ToUInt16BE(17);
@ -25,7 +25,7 @@
this.MeterID = payload.ToUInt32BE(25);
this.MBusStatus = payload[29];
this.MBusTransmissionInterval = payload.ToUInt16BE(30);
this.AlarmActiveInformation = payload[32];
this.AlarmActiveInformation = new AlarmsMask(payload[32]);
this.LeakageDetectionParameters = payload[33];
this.BrokenPipeDetectionParameters = payload[34];
this.BatteryRemainingYears = payload.ToUInt16BE(35) / (4D * 365);
@ -52,7 +52,7 @@
this.CustomerSpecificText = Encoding.ASCII.GetString(payload, 77, 9);
this.TimeOfFDRReset = payload.ToUInt16BE(86);
this.TimeOfLogReset = payload.ToUInt16BE(88);
this.MeterSize = payload[90];
this.MeterSize = (MeterSizes)payload[90];
this.Crc = 0;
if (payload.Length > MIN_LENGTH)
@ -60,16 +60,12 @@
this.Crc = payload.ToUInt16BE(91);
}
}
public uint ModuleAddress { get; }
public AlarmsMask Alarms { get; }
public PAMStatus PAMStatus { get; }
public RSSI RSSI { get; }
public byte MeterType { get; }
public MeterTypes MeterType { get; }
public ushort TransmissionInterval { get; }
@ -89,7 +85,7 @@
public ushort MBusTransmissionInterval { get; }
public byte AlarmActiveInformation { get; }
public AlarmsMask AlarmActiveInformation { get; }
public byte LeakageDetectionParameters { get; }
@ -143,6 +139,6 @@
public ushort TimeOfLogReset { get; }
public byte MeterSize { get; }
public MeterSizes MeterSize { get; }
}
}

View File

@ -168,6 +168,9 @@
<Compile Include="Pages\ManualProgramming.xaml.cs">
<DependentUpon>ManualProgramming.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\SetMetrologyParameters.xaml.cs">
<DependentUpon>SetMetrologyParameters.xaml</DependentUpon>
</Compile>
<Compile Include="ViewModels\Controls\EregisterDebugVM.cs" />
<Compile Include="ViewModels\Controls\SIRTVM.cs" />
<Compile Include="ViewModels\EregisterFinalizeVM.cs" />
@ -179,6 +182,9 @@
<Compile Include="ViewModels\GridItem[T].cs" />
<Compile Include="ViewModels\HomeVM.cs" />
<Compile Include="ViewModels\ManualProgrammingVM.cs" />
<Compile Include="ViewModels\MeterSizeVM.cs" />
<Compile Include="ViewModels\PropertyVM.cs" />
<Compile Include="ViewModels\SetMetrologyParametersVM.cs" />
<Compile Include="ViewModels\SIRTBroadcastersVM.cs" />
<Compile Include="ViewModels\SIRTConnectionVM.cs" />
<Compile Include="Controls\SIRTBroadcasters.xaml.cs">
@ -257,6 +263,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\SetMetrologyParameters.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">

View File

@ -25,9 +25,13 @@
switch (label)
{
case nameof(SIRTTaskState.Pending):; break;
case nameof(SIRTTaskState.Completed): brush = success; break;
case nameof(SIRTTaskState.Cancelled): brush = error; break;
case nameof(SIRTTaskState.Running): brush = warning; break;
case nameof(SIRTConstants.BUP): brush = warning; break;
case nameof(SIRTConstants.LAT): brush = warning; break;
case nameof(SIRTConstants.DEBUG): brush = info; break;
case nameof(SIRTConstants.SEMI): brush = success; break;
case nameof(PAMStatus.OK): brush = success; break;
case "AKN": brush = warning; break;
default: brush = error; break;

View File

@ -20,9 +20,13 @@
switch (label)
{
case nameof(SIRTTaskState.Pending):; break;
case nameof(SIRTTaskState.Completed): brush = Brushes.DarkGreen; break;
case nameof(SIRTTaskState.Cancelled): brush = Brushes.DarkRed; break;
case nameof(SIRTTaskState.Running): brush = Brushes.DarkOrange; break;
case nameof(SIRTConstants.BUP): brush = Brushes.DarkOrange; break;
case nameof(SIRTConstants.LAT): brush = Brushes.DarkOrange; break;
case nameof(SIRTConstants.DEBUG): brush = Brushes.DarkBlue; break;
case nameof(SIRTConstants.SEMI): brush = Brushes.DarkGreen; break;
case nameof(PAMStatus.OK): brush = Brushes.DarkGreen; break;
case "AKN": brush = Brushes.DarkOrange; break;
default: brush = Brushes.DarkRed; break;

View File

@ -4,14 +4,16 @@
public class VMLocator
{
public SIRTBroadcastersVM SIRTBroadcasterVM { get; } = new SIRTBroadcastersVM();
// public SIRTBroadcastersVM SIRTBroadcasterVM { get; } = new SIRTBroadcastersVM();
public EregisterHistoryVM EregisterHistoryVM { get; } = new EregisterHistoryVM();
//public EregisterHistoryVM EregisterHistoryVM { get; } = new EregisterHistoryVM();
public EregisterInitializeVM EregisterInitializeVM { get; } = new EregisterInitializeVM();
//public EregisterInitializeVM EregisterInitializeVM { get; } = new EregisterInitializeVM();
public EregisterFinalizeVM EregisterFinalizeVM { get; } = new EregisterFinalizeVM();
//public EregisterFinalizeVM EregisterFinalizeVM { get; } = new EregisterFinalizeVM();
public ManualProgrammingVM ManualProgrammingVM { get; } = new ManualProgrammingVM();
//public ManualProgrammingVM ManualProgrammingVM { get; } = new ManualProgrammingVM();
public SetMetrologyParametersVM SetMetrologyParametersVM { get; } = new SetMetrologyParametersVM();
}
}

View File

@ -2,6 +2,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ShowsNavigationUI="False"
Source="Pages/ManualProgramming.xaml"
Title="TestBench UI">
Source="Pages/SetMetrologyParameters.xaml"
Title="PAM 146: Set metrology parameters">
</NavigationWindow>

View File

@ -0,0 +1,143 @@
<Page x:Class="Common.UI.Pages.SetMetrologyParameters"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:Common.UI.ViewModels"
DataContext="{Binding SetMetrologyParametersVM, Source={StaticResource VMLocator}}"
FontFamily="Consolas"
FontSize="12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<ScrollViewer Background="Transparent"
BorderThickness="0"
Grid.Column="0"
Margin="0"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto">
<Border BorderBrush="LightGray"
BorderThickness="1 1 0 0">
<ItemsControl ItemsSource="{Binding Properties}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type VM:PropertyVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="8*" />
</Grid.ColumnDefinitions>
<Label Background="WhiteSmoke"
BorderBrush="LightGray"
BorderThickness="0 0 1 1"
Content="{Binding Source}"
FontWeight="Bold"
Grid.Column="0" />
<Label Background="WhiteSmoke"
BorderBrush="LightGray"
BorderThickness="0 0 1 1"
Content="{Binding Name}"
FontWeight="Bold"
Grid.Column="1" />
<Label Background="{Binding Source, Converter={StaticResource TaskStateToBG}}"
BorderBrush="LightGray"
BorderThickness="0 0 1 1"
Content="{Binding Value}"
Foreground="{Binding Source, Converter={StaticResource TaskStateToFG}}"
Grid.Column="2" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</ScrollViewer>
<StackPanel Background="{Binding Status, Converter={StaticResource TaskStateToBG}}"
Grid.Column="1"
Orientation="Vertical">
<TextBlock FontWeight="Bold"
Text="COM Port"
Padding="5 3 5 0" />
<ComboBox ItemsSource="{Binding PortNames}"
Margin="3 3 3 0"
Padding="5 7"
SelectedValue="{Binding PortName}" />
<TextBlock Foreground="Gray"
FontSize="11"
FontStyle="Italic"
Text="{Binding SIRTInfo}"
Padding="5 0" />
<TextBlock FontWeight="Bold"
Text="Address"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding Address}" />
<TextBlock FontWeight="Bold"
Text="Meter size"
Padding="5 3 5 0" />
<ComboBox ItemsSource="{Binding MeterSizes}"
Margin="3 3 3 0"
Padding="5 7"
SelectedValue="{Binding MeterSize}" />
<TextBlock FontWeight="Bold"
Text="Volume per pulse"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding VPP}" />
<TextBlock FontWeight="Bold"
Text="Offset factor"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding OffsetFactor}" />
<TextBlock FontWeight="Bold"
Text="Offset time"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding OffsetTime}" />
<TextBlock FontWeight="Bold"
Text="Factory calibration"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding FactoryCalibration}" />
<TextBlock FontWeight="Bold"
Text="Units"
Padding="5 3 5 0" />
<ComboBox ItemsSource="{Binding MessurementUnitsSource}"
Margin="3 3 3 0"
Padding="5 7"
SelectedValue="{Binding Units}" />
<TextBlock FontWeight="Bold"
Text="Decimal places"
Padding="5 3 5 0" />
<ComboBox ItemsSource="{Binding DecimalPlacesSource}"
Margin="3 3 3 0"
Padding="5 7"
SelectedValue="{Binding DecimalPlaces}" />
<CheckBox Content="Use C&amp;I rules"
IsChecked="{Binding UseCandIRules}"
Margin="3 3 3 0"
Padding="5"
VerticalContentAlignment="Center"/>
<TextBlock FontWeight="Bold"
Text="Volume per LED pulse"
Padding="5 3 5 0" />
<TextBox Margin="3 3 3 0"
Padding="5"
Text="{Binding VPPLED}" />
<Button Command="{Binding SetMetrologyParametersCommand}"
Content="Set Metrolgy Parameters"
Cursor="Hand"
Margin="3 5 3 0"
Padding="5" />
<TextBlock FontSize="13"
FontWeight="Bold"
Foreground="{Binding Status, Converter={StaticResource TaskStateToFG}}"
Text="{Binding Status}"
Padding="5 3 5 0" />
</StackPanel>
</Grid>
</Page>

View File

@ -0,0 +1,9 @@
namespace Common.UI.Pages
{
using System.Windows.Controls;
public partial class SetMetrologyParameters : Page
{
public SetMetrologyParameters() => this.InitializeComponent();
}
}

View File

@ -0,0 +1,15 @@
namespace Common.UI.ViewModels
{
public class MeterSizeVM
{
public string Title { get; set; }
public byte Size { get; set; }
public bool UseCandIRules { get; set; }
public int Vpp { get; set; }
public uint VppLED { get; set; }
}
}

View File

@ -0,0 +1,24 @@
namespace Common.UI.ViewModels
{
using System.Windows.Media;
using Common.UI.Infrastructure;
public class PropertyVM : VM<PropertyVM>
{
public string Name { get; set; }
private string source;
public string Source
{
get => this.source;
set => this.SetValue(x => x.source = value);
}
private string value;
public string Value
{
get => this.value;
set => this.SetValue(x => x.value = value);
}
}
}

View File

@ -0,0 +1,416 @@
namespace Common.UI.ViewModels
{
using Common.Hardware.SIRT;
using Common.Hardware.SIRT.Parameters;
using Common.Hardware.SIRT.Tasks;
using Common.Hardware.WaterMeter.eRegister;
using Common.Hardware.WaterMeter.eRegister.Features;
using Common.Hardware.WaterMeter.eRegister.Telegrams;
using Common.UI.Infrastructure;
using LaaPackages.SqlClient;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
public class SetMetrologyParametersVM : VM<SetMetrologyParametersVM>
{
private readonly Dictionary<string, PropertyVM> telegrams;
private readonly Dictionary<string, MeterSizeVM> meterSizes;
public SetMetrologyParametersVM()
{
AppHost.SIRTHub.Connected += this.SIRTHub_Connected;
AppHost.SIRTHub.Disconnected += this.SIRTHub_Disconnected;
this.SetMetrologyParametersCommand = new Command(this.SetMetrologyParametersCommandHandler);
this.PortNames = SerialPort.GetPortNames();
this.meterSizes = SqlConnection
.CreateSqlConnection(Appsettings.GetSetting("ConnectionString"))
.CreateCommand($@"
SELECT TRIM(CONCAT(
mt.Title
, IIF(mt.Additive IS NULL, NULL, ' ')
, mt.Additive
, IIF(SUBSTRING(nw.Title, 1, 1) BETWEEN '0' AND '9', ' DN', ' ')
, nw.Title))
, mtnw.Value
, ms.Ruecklaufsperre
, ms.Volume_per_Pulse
, ms.Volume_per_LED_Pulse
FROM CSD.MeterType AS mt
JOIN CSD.MeterTypeNominalWidth AS mtnw
ON mt.ID = mtnw.MeterType_ID
JOIN CSD.NominalWidth AS nw
ON mtnw.NominalWidth_ID = nw.ID
JOIN eRegister_Metersize AS ms
ON mtnw.Value = ms.Metersize
WHERE ms.Volume_per_Pulse IS NOT NULL
ORDER BY mt.Value, mtnw.Value")
.ExecuteReader(x => new MeterSizeVM
{
Title = x.GetValue<string>(0),
Size = x.GetValue<byte>(1),
UseCandIRules = x.GetValue<bool>(2),
Vpp = x.GetValue<int>(3),
VppLED = x.GetValue<uint>(4),
})
.ToDictionary(x => x.Title, x => x);
this.MeterSizes = this.meterSizes.Keys.ToArray();
this.DecimalPlacesSource = Enum.GetNames(typeof(DecimalPointLocations));
this.telegrams = new Dictionary<string, PropertyVM>();
foreach (var property in typeof(SEMI).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var name = property.Name;
this.telegrams[name] = new PropertyVM
{
Source = nameof(SEMI),
Name = name
};
}
foreach (var property in typeof(DEBUG).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var name = property.Name;
this.telegrams[name] = new PropertyVM
{
Source = nameof(DEBUG),
Name = name
};
}
foreach (var property in typeof(BUP).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var name = property.Name;
this.telegrams[name] = new PropertyVM
{
Source = nameof(BUP),
Name = name
};
}
foreach (var property in typeof(LAT).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var name = property.Name;
this.telegrams[name] = new PropertyVM
{
Source = nameof(LAT),
Name = name
};
}
this.Properties = this.telegrams.Values.ToArray();
this.MessurementUnitsSource = Enum
.GetValues(typeof(MessurementUnits))
.Cast<MessurementUnits>()
.Where(x => (int)x < 10)
.Select(x => x.ToString())
.ToArray();
}
private string sirtInfo = "No SIRT is connected";
public string SIRTInfo
{
get => this.sirtInfo;
set => this.SetValue(x => x.sirtInfo = value);
}
private SIRTBroadcaster sirt;
private string portName;
public string PortName
{
get => this.portName;
set => this.SetPortName(value);
}
private uint address;
public uint Address
{
get => this.address;
set => this.SetValue(x => x.address = value);
}
private string meterSize;
public string MeterSize
{
get => this.meterSize;
set => this.SetValue(x =>
{
x.meterSize = value;
if (this.meterSizes.TryGetValue($"{x.meterSize}", out var ms))
{
this.VPP = ms.Vpp;
this.VPPLED = ms.VppLED;
this.UseCandIRules = ms.UseCandIRules;
this.Units = $"{MessurementUnits.Cubic_Meters}";
this.DecimalPlaces = $"{(ms.Vpp < 700 ? DecimalPointLocations.Three : DecimalPointLocations.Two)}";
}
});
}
private int vpp;
public int VPP
{
get => this.vpp;
set => this.SetValue(x => x.vpp = value);
}
private uint vppLED;
public uint VPPLED
{
get => this.vppLED;
set => this.SetValue(x => x.vppLED = value);
}
private int offsetFactor;
public int OffsetFactor
{
get => this.offsetFactor;
set => this.SetValue(x => x.offsetFactor = value);
}
private byte offsetTime;
public byte OffsetTime
{
get => this.offsetTime;
set => this.SetValue(x => x.offsetTime = value);
}
private byte factoryCalibration;
public byte FactoryCalibration
{
get => this.factoryCalibration;
set => this.SetValue(x => x.factoryCalibration = value);
}
private string units;
public string Units
{
get => this.units;
set => this.SetValue(x => x.units = value);
}
private string decimalPlaces;
public string DecimalPlaces
{
get => this.decimalPlaces;
set => this.SetValue(x => x.decimalPlaces = value);
}
private bool useCandIRules;
public bool UseCandIRules
{
get => this.useCandIRules;
set => this.SetValue(x => x.useCandIRules = value);
}
private string status;
public string Status
{
get => this.status;
set => this.SetValue(x => x.status = value);
}
public ICommand SetMetrologyParametersCommand { get; }
public string[] PortNames { get; }
public string[] MeterSizes { get; }
public string[] DecimalPlacesSource { get; }
public PropertyVM[] Properties { get; }
public string[] MessurementUnitsSource { get; }
private void SetPortName(string value)
=> this.SetValue(vm =>
{
vm.portName = value;
Task.Run(() =>
{
this.InvokeAsync(() =>
{
vm.SIRTInfo = $"Disconnecting {sirt.PortName} ...";
AppHost.SIRTHub.Close(vm.sirt?.PortName);
});
})
.ContinueWith(_ =>
{
this.InvokeAsync(() =>
{
vm.SIRTInfo = $"Connecting {vm.portName} ...";
AppHost.SIRTHub.TryOpen(vm.PortName, out var _1, out var _2);
});
});
});
private void SIRTHub_Connected(SIRTBroadcaster sirt)
{
this.sirt = sirt;
this.SIRTInfo = $"{this.sirt.Id}|{this.sirt.Frequency}Mhz";
}
private void Ertask_MessageReceived(byte[] bytes)
{
if (bytes is null)
{
return;
}
var message = new SIRTMessage(bytes);
if (message.Command == SIRTConstants.FROM_AIR)
{
var p11 = new P11(message.P1);
var rssi = new RSSI(message.P2, (ushort)this.sirt.Frequency);
var data = message.Payload;
var length = data.Length;
if (length > 0)
{
var type = data[0];
var telegram = default(object);
var background = Brushes.White;
if (type == SIRTConstants.BUP)
{
telegram = new BUP(data, p11);
}
else if (type == SIRTConstants.LAT)
{
telegram = new LAT(data, p11);
}
else if (type == SIRTConstants.DEBUG)
{
telegram = new DEBUG(data, p11);
}
else if (type == SIRTConstants.SEMI)
{
telegram = new SEMI(data, this.sirt.Frequency, p11);
}
if (telegram != null)
{
var sourceType = telegram.GetType();
var sourceName = sourceType.Name;
foreach (var property in sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var name = property.Name;
if (this.telegrams.TryGetValue(name, out var propertyVM))
{
propertyVM.Source = sourceName;
propertyVM.Value = $"{property.GetValue(telegram)}";
}
}
}
}
}
}
private void SIRTHub_Disconnected(SIRTBroadcaster sirt)
{
this.sirt = null;
this.SIRTInfo = $"{sirt.PortName} disconnected";
}
private void SetMetrologyParametersCommandHandler()
{
this.Status = null;
foreach (var property in this.telegrams.Values)
{
property.Value = null;
}
var _vpp = (this.vpp * 65536) | 0x80_00_00_00;
var __vpp = (int)_vpp; // 625 = -2106523648
var task = new EregisterTask(this.sirt.Frequency)
{
DelPamSemi = true,
WakeUpCmd = true,
RequestAddress = this.Address,
Data = new SetMetrologyParameters
{
DecimalPoint = this.VPP < 700 ? DecimalPointLocations.Three : DecimalPointLocations.Two,
MeterSize = this.meterSizes.TryGetValue(this.MeterSize, out var ms) ? ms.Size : (byte)23,
FactoryCalibration = this.FactoryCalibration,
OffsetFactor = this.OffsetFactor,
OffsetTime = this.OffsetTime,
Units = Enum.TryParse<MessurementUnits>($"{this.Units}", out var units)
? units : Hardware.WaterMeter.eRegister.Features.MessurementUnits.Cubic_Meters,
UseCandIRules = this.UseCandIRules,
VppLED = this.vppLED * 65536,
Vpp = __vpp,
}
.Append(new ProvidePin
{
AuthLevel = AuthLevel.III
})
};
Task.Run(() =>
{
void StateChanged(SIRTTask x)
{
this.Status = x.State.ToString();
}
task.MessageReceived += this.Ertask_MessageReceived;
task.StateChanged += StateChanged;
while (task.State != SIRTTaskState.Completed && task.State != SIRTTaskState.Cancelled)
{
AppHost.SIRTHub.Start(task);
task.Wait();
if (task.State == SIRTTaskState.Completed && task.State == SIRTTaskState.Cancelled)
{
break;
}
}
task.Data = new OpticalTelegram().Append(new ProvidePin
{
AuthLevel = AuthLevel.III
});
task.SetPending();
while (task.State != SIRTTaskState.Completed && task.State != SIRTTaskState.Cancelled)
{
AppHost.SIRTHub.Start(task);
task.Wait();
if (task.State == SIRTTaskState.Completed && task.State == SIRTTaskState.Cancelled)
{
break;
}
}
task.StateChanged -= StateChanged;
task.MessageReceived -= this.Ertask_MessageReceived;
});
}
}
}