ignored files

This commit is contained in:
Stoyan Zlatev 2025-09-23 15:37:09 +02:00
parent 0dbc6e4210
commit ef06afba64
14 changed files with 1489 additions and 0 deletions

View File

@ -0,0 +1,13 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public enum AppCode
{
BUP = 0x00,
LAT = 0x01,
SEMI = 0x08,
LoggerTelegram = 0x09,
TestTelegram = 0x0A,
DEBUG = 0x0B,
EncapsulatedFlexNet = 0x10
}
}

View File

@ -0,0 +1,11 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public enum DisplayUnits
{
NA = 0,
m3 = 19,
CF = 35,
GAL = 24,
IGAL = 144,
}
}

View File

@ -0,0 +1,35 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
using System;
public class Epoch20000101
{
private static readonly DateTime epoch = new DateTime(2000, 01, 01, 00, 00, 00, DateTimeKind.Utc);
private readonly byte[] bytes;
public Epoch20000101(DateTimeKind dateTimeKind = DateTimeKind.Utc)
=> this.bytes = new byte[4];
public Epoch20000101(uint secondsSince, DateTimeKind dateTimeKind = DateTimeKind.Utc) : this(dateTimeKind)
=> this.SecondsSince = secondsSince;
public uint SecondsSince
{
get => BitConverter.ToUInt32(this.bytes, 0);
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 0);
}
public DateTime DateTime
{
get => epoch.AddSeconds(this.SecondsSince);
set => this.SecondsSince = (uint)(value - epoch).TotalSeconds;
}
public static uint UTCNow => new Epoch20000101 { DateTime = DateTime.UtcNow }.SecondsSince;
public static implicit operator DateTime(Epoch20000101 epoch) => epoch.DateTime;
public static implicit operator uint(Epoch20000101 epoch) => epoch.SecondsSince;
}
}

View File

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

View File

@ -0,0 +1,97 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public class LogContent
{
private readonly byte[] bits = new byte[16];
public LogContent(ushort value = 0)
=> this.bits = value.GetBitsLE();
public bool ForwardCounter
{
get => this.bits[12] == 1;
set => this.bits[12] = (byte)(value ? 1 : 0);
}
public bool TimeOfMinimumFlow
{
get => this.bits[11] == 1;
set => this.bits[11] = (byte)(value ? 1 : 0);
}
public bool MinimumFlow
{
get => this.bits[10] == 1;
set => this.bits[10] = (byte)(value ? 1 : 0);
}
public bool TimeOfBrokenPipe
{
get => this.bits[9] == 1;
set => this.bits[9] = (byte)(value ? 1 : 0);
}
public bool BrokenPipeFlow
{
get => this.bits[8] == 1;
set => this.bits[8] = (byte)(value ? 1 : 0);
}
public bool CurrentFlow
{
get => this.bits[7] == 1;
set => this.bits[7] = (byte)(value ? 1 : 0);
}
public bool TimeOfPeakFlow
{
get => this.bits[6] == 1;
set => this.bits[6] = (byte)(value ? 1 : 0);
}
public bool PeakFlow
{
get => this.bits[5] == 1;
set => this.bits[5] = (byte)(value ? 1 : 0);
}
public bool TimeOfMaximumFlow
{
get => this.bits[4] == 1;
set => this.bits[4] = (byte)(value ? 1 : 0);
}
public bool MaximumFlow
{
get => this.bits[3] == 1;
set => this.bits[3] = (byte)(value ? 1 : 0);
}
public bool BackwardVolume
{
get => this.bits[2] == 1;
set => this.bits[2] = (byte)(value ? 1 : 0);
}
public bool Counter
{
get => this.bits[1] == 1;
set => this.bits[1] = (byte)(value ? 1 : 0);
}
public bool AlarmState
{
get => this.bits[0] == 1;
set => this.bits[0] = (byte)(value ? 1 : 0);
}
public override string ToString()
=> string.Join(string.Empty, this.bits);
public static implicit operator LogContent(ushort value)
=> new LogContent(value);
public static implicit operator ushort(LogContent value)
=> value.bits.ToUIint16LEFromBits();
}
}

View File

@ -0,0 +1,11 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public enum MeterTypes : byte
{
Residential = 0,
CandI = 1,
Cordonel = 0x09,
Residential__0x0B = 11,
CandI__0x0C = 12,
}
}

View File

@ -0,0 +1,62 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public class PAMStatus
{
private readonly byte[] bits;
public PAMStatus(byte _byte)
=> this.bits = _byte.GetBitsLE();
public bool CMD_UNKNOWN => this.bits[0] == 1;
public bool WRONG_AUTH => this.bits[1] == 1;
public bool EXPIRED_AUTH => this.bits[2] == 1;
public bool MIXED_TYPES => this.bits[3] == 1;
public bool OUT_OF_RANGE => this.bits[4] == 1;
public override string ToString()
{
if (this.bits.GetByteLE() == 0)
{
return nameof(OK);
}
if (this.OUT_OF_RANGE)
{
return nameof(this.OUT_OF_RANGE);
}
else if (this.MIXED_TYPES)
{
return nameof(this.MIXED_TYPES);
}
else if (this.CMD_UNKNOWN)
{
return nameof(this.CMD_UNKNOWN);
}
else if (this.EXPIRED_AUTH)
{
return nameof(this.EXPIRED_AUTH);
}
else if (this.WRONG_AUTH)
{
return nameof(this.WRONG_AUTH);
}
else
{
return string.Join(string.Empty, this.bits);
}
}
public static byte OK = 0;
public static byte EXPIREDAUTH = 4;
public static implicit operator byte(PAMStatus status)
=> status?.bits?.GetByteLE() ?? 0xFF;
public static implicit operator string(PAMStatus status)
=> status?.ToString();
}
}

View File

@ -0,0 +1,79 @@
namespace CommonConsole.RFTelegrams.Pams
{
using Common.Hardware.SIRT;
using System.Text;
public class AlarmMask
{
protected readonly byte[] bits;
public AlarmMask(byte value) => this.bits = value.GetBitsLE();
public bool SpecificError
{
get => this.bits[0] == 1;
set => this.bits[0] = (byte)(value ? 1 : 0);
}
public bool MediumAbsent
{
get => this.bits[1] == 1;
set => this.bits[1] = (byte)(value ? 1 : 0);
}
public bool BrokenPipe
{
get => this.bits[2] == 1;
set => this.bits[2] = (byte)(value ? 1 : 0);
}
public bool Backflow
{
get => this.bits[3] == 1;
set => this.bits[3] = (byte)(value ? 1 : 0);
}
public bool MetrologyUnavailable
{
get => this.bits[4] == 1;
set => this.bits[4] = (byte)(value ? 1 : 0);
}
public bool MagneticTamper
{
get => this.bits[5] == 1;
set => this.bits[5] = (byte)(value ? 1 : 0);
}
public bool Leak
{
get => this.bits[6] == 1;
set => this.bits[6] = (byte)(value ? 1 : 0);
}
public bool LowBattery
{
get => this.bits[7] == 1;
set => this.bits[7] = (byte)(value ? 1 : 0);
}
public override string ToString()
{
var alarmMaskBuilder = new StringBuilder();
alarmMaskBuilder.AppendLine($"{nameof(this.SpecificError),20}: {this.SpecificError}");
alarmMaskBuilder.AppendLine($"{nameof(this.MediumAbsent),20}: {this.MediumAbsent}");
alarmMaskBuilder.AppendLine($"{nameof(this.BrokenPipe),20}: {this.BrokenPipe}");
alarmMaskBuilder.AppendLine($"{nameof(this.Backflow),20}: {this.Backflow}");
alarmMaskBuilder.AppendLine($"{nameof(this.MetrologyUnavailable),20}: {this.MetrologyUnavailable}");
alarmMaskBuilder.AppendLine($"{nameof(this.MagneticTamper),20}: {this.MagneticTamper}");
alarmMaskBuilder.AppendLine($"{nameof(this.Leak),20}: {this.Leak}");
alarmMaskBuilder.AppendLine($"{nameof(this.LowBattery),20}: {this.LowBattery}");
return alarmMaskBuilder.ToString().Trim();
}
public static implicit operator byte(AlarmMask alarmMask) => alarmMask.bits.GetByteLE();
}
}

View File

@ -0,0 +1,7 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams.Pams
{
public class DummyPam
{
public static implicit operator byte[](DummyPam dummyPam) => new byte[0];
}
}

View File

@ -0,0 +1,70 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams.Pams
{
public class ResetAlarms
{
private readonly byte[] bits;
public ResetAlarms(byte _byte = 0xFF)
=> this.bits = _byte.GetBitsLE();
public bool SpecificError
{
get => this.bits[0] == 1;
set => this.bits[0] = (byte)(value ? 1 : 0);
}
public bool MediumAbsent
{
get => this.bits[1] == 1;
set => this.bits[1] = (byte)(value ? 1 : 0);
}
public bool BrokenPipe
{
get => this.bits[2] == 1;
set => this.bits[2] = (byte)(value ? 1 : 0);
}
public bool Backflow
{
get => this.bits[3] == 1;
set => this.bits[3] = (byte)(value ? 1 : 0);
}
public bool MetrologyUnavailable
{
get => this.bits[4] == 1;
set => this.bits[4] = (byte)(value ? 1 : 0);
}
public bool MagneticTamper
{
get => this.bits[5] == 1;
set => this.bits[5] = (byte)(value ? 1 : 0);
}
public bool Leak
{
get => this.bits[6] == 1;
set => this.bits[6] = (byte)(value ? 1 : 0);
}
public bool LowBattery
{
get => this.bits[7] == 1;
set => this.bits[7] = (byte)(value ? 1 : 0);
}
public static implicit operator byte[] (ResetAlarms resetAlarms) => new byte[]
{
0x03,
resetAlarms.bits.GetByteLE(),
0x43,
0x01,
0x14,
0x30,
0x68,
0xD0
};
}
}

View File

@ -0,0 +1,91 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
using global::Common.Hardware.SIRT;
using global::Common.Hardware.SIRT.Tasks;
using System;
using System.Collections.Generic;
public class RFTask : WritePamTask
{
private readonly Stack<SIRTMessage> messages = new Stack<SIRTMessage>();
public SIRTMessage AKN { get; private set; }
public SIRTMessage BUP { get; private set; }
public SIRTMessage LAT { get; private set; }
public SIRTMessage DEBUG { get; private set; }
public SIRTMessage SEMI { get; private set; }
public SIRTMessage LastOrDefault()
=> this.messages.Count > 0
? this.messages.Peek()
: new SIRTMessage();
public override string ToString()
=> BitConverter.ToString(this.request.Payload);
protected override void OnMessageSent(SIRTMessage request)
=> this.messages.Push(request);
protected override void OnUnknownReceived(SIRTMessage unknown)
=> this.messages.Push(unknown);
protected override void OnAKNReceived(SIRTMessage akn)
{
this.AKN = akn;
this.messages.Push(akn);
}
protected override void OnBUPReceived(SIRTMessage bup)
{
this.BUP = bup;
this.messages.Push(bup);
}
protected override void OnLATReceived(SIRTMessage lat)
{
this.LAT = lat;
this.messages.Push(lat);
}
protected override void OnDEBUGReceived(SIRTMessage debug)
{
this.DEBUG = debug;
this.messages.Push(debug);
}
protected override void OnSEMIReceived(SIRTMessage semi)
{
if (semi is null || semi.Payload is null || semi.Payload.Length < 11)
{
this.SetPending();
return;
}
// PAM Status: [11]
var pamStatus = new PAMStatus(semi.Payload[11]);
if (pamStatus != PAMStatus.OK)
{
this.SetPending();
return;
}
base.OnSEMIReceived(semi);
this.SEMI = semi;
this.messages.Push(semi);
}
}
}

View File

@ -0,0 +1,42 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
public class RSSI
{
public RSSI(byte value, int mhz)
{
this.Value = value;
if (mhz == 433)
{
this.Dbm = value * 0.5 - 140;
this.Percent = value * 0.7333 - 57.6667;
}
else if (mhz == 868)
{
this.Dbm = value * 0.5 - 131.3;
this.Percent = value * 0.66 - 40.316;
}
if (this.Percent > 100)
{
this.Percent = 100;
}
else if (this.Percent < 0)
{
this.Percent = 0;
}
}
public byte Value { get; }
public double Dbm { get; }
public double Percent { get; }
public override string ToString() => $"{this.Dbm}dBm ({this.Percent:0.0}%)";
public static implicit operator byte(RSSI rssi) => rssi?.Value ?? 0;
public static implicit operator string(RSSI rssi) => rssi?.ToString();
}
}

View File

@ -0,0 +1,176 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
using Pams;
using System;
using System.Text;
/// <summary>
/// TODO: SEMI from the SirtDLL is not complete,
/// </summary>
public class SEMI
{
//public const int MIN_LENGTH = 120;
public const int MIN_LENGTH = 97;
public SEMI(byte[] payload, int mhz)
{
this.AppCode = (AppCode)payload[0];
this.Counter = payload[1];
this.Address = payload.ToUInt32BE(2);
this.Reading = payload.ToInt32BE(6);
this.MainAlarmByte = new ResetAlarms(payload[10]);
this.PAMStatus = new PAMStatus(payload[11]);
this.RSSI = new RSSI(payload[12], mhz);
this.MeterType = (MeterTypes)payload[13];
this.TransmissionInterval = payload.ToUInt16BE(14);
this.LATInterval = payload[16];
this.ActualFlow = payload.ToUInt16BE(17);
this.BackwardVolume = payload.ToUInt32BE(19);
this.Units = (DisplayUnits)payload[23];
this.MBusStatus = payload[24];
this.MBusTransmissionInterval = payload.ToUInt16BE(25);
this.MainAlarmMask = new ResetAlarms(payload[27]);
this.LeakageDetectionParameters = payload[28];
this.BrokenPipeDetectionParameters = payload[29];
this.BatteryRemainingYears = payload.ToUInt16BE(30) / (4D * 365);
this.ReminingBatteryCapacity = payload[32];
this.MaximumFlow = payload.ToUInt16BE(33);
this.TimeSinceMaximumFlow = payload.ToUInt16BE(35);
this.TimeSinceLowBattery = payload.ToUInt16BE(37);
this.AlarmLeakage = new Epoch20000101(payload.ToUInt32BE(39), DateTimeKind.Local);
this.AlarmAirInPipe = new Epoch20000101(payload.ToUInt32BE(43), DateTimeKind.Local);
this.AlarmReverseFlow = new Epoch20000101(payload.ToUInt32BE(47), DateTimeKind.Local);
this.AlarmBrokenPipe = new Epoch20000101(payload.ToUInt32BE(51), DateTimeKind.Local);
this.DataLogContent = payload.ToUInt16BE(55);
this.DataLoggingInterval = payload.ToUInt16BE(57);
this.FDRContent = payload.ToUInt16BE(59);
this.FDRDayOfMonth = payload[61];
this.ActualDateTime = new Epoch20000101(payload.ToUInt32BE(62), DateTimeKind.Local);
this.HistoricalErrorDays = payload[66];
this.CustomerSpecificText = Encoding.ASCII.GetString(payload, 67, 9);
this.TimeOfFDRReset = payload.ToUInt16BE(76);
this.TimeOfLogReset = payload.ToUInt16BE(78);
this.ActualPressure = payload.ToUInt16BE(80);
this.ActualTemperature = payload[82];
this.PressureParameter = Encoding.ASCII.GetString(payload, 83, 7);
this.TemperatureParameter = payload.ToInt32BE(90);
this.PulseOutParameter = payload[94];
this.AlarmByteExtended = payload[95];
this.AlarmMaskExtended = payload[96];
//this.AlarmMaxPressureTime = payload.ToUInt32BE(97);
//this.AlarmMinPressureTime = payload.ToUInt32BE(101);
//this.AlarmMaxTemperatureTime = payload.ToUInt32BE(105);
//this.AlarmMinTemperatureTime = payload.ToUInt32BE(109);
//this.LogContentPressureTemperature = payload.ToUInt16BE(113);
//this.FDRContentPressureTemperature = payload.ToUInt16BE(115);
//this.UnitExtraFlags = payload[117];
//this.MeterSize = payload[118];
//this.PressureCalibrationOffset = payload[119];
}
public AppCode AppCode { get; }
public byte Counter { get; }
public uint Address { get; }
public int Reading { get; }
public ResetAlarms MainAlarmByte { get; }
public PAMStatus PAMStatus { get; }
public RSSI RSSI { get; }
public MeterTypes MeterType { get; }
public ushort TransmissionInterval { get; }
public byte LATInterval { get; }
public ushort ActualFlow { get; }
public uint BackwardVolume { get; }
public DisplayUnits Units { get; }
public byte MBusStatus { get; }
public ushort MBusTransmissionInterval { get; }
public ResetAlarms MainAlarmMask { get; }
public byte LeakageDetectionParameters { get; }
public byte BrokenPipeDetectionParameters { get; }
public double BatteryRemainingYears { get; }
public byte ReminingBatteryCapacity { get; }
public ushort MaximumFlow { get; }
public ushort TimeSinceMaximumFlow { get; }
public ushort TimeSinceLowBattery { get; }
public DateTime AlarmLeakage { get; }
public DateTime AlarmAirInPipe { get; }
public DateTime AlarmReverseFlow { get; }
public DateTime AlarmBrokenPipe { get; }
public LogContent DataLogContent { get; }
public ushort DataLoggingInterval { get; }
public LogContent FDRContent { get; }
public byte FDRDayOfMonth { get; }
public DateTime ActualDateTime { get; }
public byte HistoricalErrorDays { get; }
public string CustomerSpecificText { get; }
public ushort TimeOfFDRReset { get; }
public ushort TimeOfLogReset { get; }
public ushort ActualPressure { get; }
public byte ActualTemperature { get; }
public string PressureParameter { get; }
public int TemperatureParameter { get; }
public byte PulseOutParameter { get; }
public byte AlarmByteExtended { get; }
public byte AlarmMaskExtended { get; }
//public uint AlarmMaxPressureTime { get; }
//public uint AlarmMinPressureTime { get; }
//public uint AlarmMaxTemperatureTime { get; }
//public uint AlarmMinTemperatureTime { get; }
//public ushort LogContentPressureTemperature { get; }
//public ushort FDRContentPressureTemperature { get; }
//public byte UnitExtraFlags { get; }
//public byte MeterSize { get; }
//public byte PressureCalibrationOffset { get; }
}
}

View File

@ -0,0 +1,172 @@
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.RFTelegrams
{
using CommonConsole.RFTelegrams.Pams;
using global::Common.Hardware.SIRT;
using global::Common.Hardware.SIRT.Tasks;
using Pams;
using System;
internal class SIRTServer
{
private static Action<string> messageCallback;
private static Action<string> errorMessageCallback;
private static readonly SIRTHub sirtHub = new SIRTHub();
/// <summary>
/// Connects SIRT's globaly for the application
/// </summary>
/// <param name="messageHandler">Action that receives info messages</param>
/// <param name="errorMessageHandler">Action that receives error messages</param>
/// <param name="comPorts">The COM-Ports to be connected</param>
/// <returns><c>true</c> - if all ports connected otherwise <c>false</c></returns>
public static bool StartServer(Action<string> messageHandler, Action<string> errorMessageHandler, params int[] comPorts)
{
string sirtId;
int frequency;
bool succeeded = true;
messageHandler?.Invoke(new string('-', 100));
foreach (var comport in comPorts)
{
succeeded = ConnectSIRT(comport, out sirtId, out frequency);
if (succeeded)
{
messageHandler?.Invoke($"COM{comport}|{sirtId}|{frequency}MHz - connected");
messageHandler?.Invoke(new string('-', 100));
}
else
{
errorMessageHandler?.Invoke($"SIRT at COM{comport} not connected!");
errorMessageHandler?.Invoke(new string('-', 100));
break;
}
}
if (succeeded)
{
messageCallback = messageHandler;
errorMessageCallback = errorMessageHandler;
}
return succeeded;
}
public static bool StartProgramming(int frequency, uint address, string encryptionKey, int repeatsCount = 3)
{
var succeeded = true;
if (succeeded)
{
succeeded = SendPAM(task =>
{
task.WakeUpCmd = true;
task.DelPamSemi = true;
task.WakeUpModul = true;
task.Frequency = frequency;
task.RequestAddress = address;
task.EncryptionKey = encryptionKey.GetEncryptionKey();
task.Data = new DummyPam();
}
, repeatsCount);
}
if (succeeded)
{
succeeded = SendPAM(task =>
{
task.DelPamSemi = true;
task.Frequency = frequency;
task.RequestAddress = address;
task.EncryptionKey = encryptionKey.GetEncryptionKey();
task.Data = new ResetAlarms(0xFF)
{
MediumAbsent = false
};
}
, repeatsCount);
}
if (succeeded)
{
succeeded = SendPAM(task =>
{
task.DelPamSemi = true;
task.Frequency = frequency;
task.RequestAddress = address;
task.EncryptionKey = encryptionKey.GetEncryptionKey();
task.Data = new ResetAlarms(0xFE);
}
, repeatsCount);
}
return succeeded;
}
/// <summary>
/// Dispose all SIRT's globaly for the application.
/// </summary>
public static void Dispose()
{
void LogState(object state) => messageCallback?.Invoke(state?.ToString());
sirtHub.StateLogging += LogState;
sirtHub.Stop();
sirtHub.StateLogging -= LogState;
messageCallback = null;
errorMessageCallback = null;
}
private static bool ConnectSIRT(int portno, out string sirtId, out int frequency)
=> sirtHub.TryOpen($"COM{portno}", out sirtId, out frequency);
private static bool SendPAM(Action<RFTask> taskOpetions, int repeatsCount = 3)
{
void LogMessage(SIRTMessage message) => messageCallback?.Invoke(message.ToString());
var cordonelTask = new RFTask();
var succeeded = false;
taskOpetions(cordonelTask);
cordonelTask.MessageSent += LogMessage;
cordonelTask.MessageReceived += LogMessage;
for (var i = 1; i <= repeatsCount && cordonelTask.State != SIRTTaskState.Completed && cordonelTask.State != SIRTTaskState.Cancelled; i++)
{
if (sirtHub.Start(cordonelTask))
{
cordonelTask.Wait();
}
}
cordonelTask.MessageReceived -= LogMessage;
cordonelTask.MessageSent -= LogMessage;
if (cordonelTask.State == SIRTTaskState.Completed)
{
succeeded = true;
messageCallback?.Invoke($"{cordonelTask.State} - CMD|{cordonelTask}");
var pam = new PAMStatus(cordonelTask.SEMI.Payload[11]);
messageCallback?.Invoke($"PAM Status: {pam}");
var alarm = new AlarmMask(cordonelTask.SEMI.Payload[10]);
messageCallback?.Invoke(alarm.ToString());
messageCallback?.Invoke(new string('-', 100));
}
else
{
errorMessageCallback?.Invoke($"{cordonelTask.State} - CMD|{cordonelTask}");
errorMessageCallback?.Invoke(new string('-', 100));
}
return succeeded;
}
}
}