make collector aware of "secret" limp string alarms/warnings (too many broken cells)

This commit is contained in:
ig 2023-08-29 13:57:52 +02:00
parent 6964f49b8b
commit db6fe5ecbf
15 changed files with 149 additions and 223 deletions

View File

@ -4,6 +4,7 @@
<PropertyGroup> <PropertyGroup>
<RootNamespace>InnovEnergy.App.Collector</RootNamespace> <RootNamespace>InnovEnergy.App.Collector</RootNamespace>
<IsTrimmable>false</IsTrimmable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -90,16 +90,16 @@ public static class BatteryDataParser
private static UInt64 ParseUInt64Register(this Data data, Int32 register) private static UInt64 ParseUInt64Register(this Data data, Int32 register)
{ {
return Enumerable return Enumerable
.Range(register, 4) .Range(register, 4)
.Reverse() .Reverse()
.Select(data.ParseUInt16Register) .Select(data.ParseUInt16Register)
.Aggregate(0ul, (a, b) => a << 16 | b); .Aggregate(0ul, (a, b) => a << 16 | b);
} }
private static Decimal ParseDecimalRegister(this Data data, private static Decimal ParseDecimalRegister(this Data data,
Int32 register, Int32 register,
Decimal scaleFactor = 1, Decimal scaleFactor = 1,
Decimal offset = 0) Decimal offset = 0)
{ {
var i = register.RegToIndex(); var i = register.RegToIndex();
Int32 n = data.ParseUInt16(i); Int32 n = data.ParseUInt16(i);
@ -175,6 +175,7 @@ public static class BatteryDataParser
MPMM = Warning(38), MPMM = Warning(38),
TCMM = Warning(39), TCMM = Warning(39),
TCdi = Warning(40), TCdi = Warning(40),
LMPW = Warning(44)
}; };
} }
@ -215,18 +216,20 @@ public static class BatteryDataParser
TbCM = Alarm(36), TbCM = Alarm(36),
HTFS = Alarm(42), HTFS = Alarm(42),
DATA = Alarm(43), DATA = Alarm(43),
LMPA = Alarm(45),
HEBT = Alarm(46),
}; };
} }
private static BatteryStatus ParseBatteryStatus(this Data data, private static BatteryStatus ParseBatteryStatus(this Data data,
String installation, String installation,
String batteryId, String batteryId,
Decimal temperature, Decimal temperature,
Warnings warnings, Warnings warnings,
Alarms alarms, Alarms alarms,
DateTime lastSeen, DateTime lastSeen,
IPEndPoint endPoint) IPEndPoint endPoint)
{ {
var activeWarnings = Active(warnings); var activeWarnings = Active(warnings);
var activeAlarms = Active(alarms); var activeAlarms = Active(alarms);
@ -265,10 +268,10 @@ public static class BatteryDataParser
}; };
static IReadOnlyCollection<String> Active(BatteryRecord record) => record static IReadOnlyCollection<String> Active(BatteryRecord record) => record
.GetFields() .GetFields()
.Where(f => f.value is Boolean b && b) .Where(f => f.value is true)
.Select(f => f.key) .Select(f => f.key)
.ToList(); .ToList();
} }

View File

@ -72,9 +72,9 @@ public static class BatteryDataParserV4
private static String NextString(this IEnumerator<ArraySegment<Byte>> enumerator) private static String NextString(this IEnumerator<ArraySegment<Byte>> enumerator)
{ {
return enumerator return enumerator
.Next() .Next()
.ToArray() .ToArray()
.Apply(Encoding.UTF8.GetString); .Apply(Encoding.UTF8.GetString);
} }
@ -98,9 +98,9 @@ public static class BatteryDataParserV4
private static UInt64 ParseUInt64Register (this Data data, Int32 register) private static UInt64 ParseUInt64Register (this Data data, Int32 register)
{ {
return Enumerable return Enumerable
.Range(0, 4) .Range(0, 4)
.Select(i => Convert.ToUInt64(data.ParseUInt16Register(register + i)) << (i * 16)) .Select(i => Convert.ToUInt64(data.ParseUInt16Register(register + i)) << (i * 16))
.Aggregate(0ul, (a, b) => a + b); // Sum() does not work for UInt64 :( .Aggregate(0ul, (a, b) => a + b); // Sum() does not work for UInt64 :(
} }
private static Decimal ParseDecimalRegister(this Data data, private static Decimal ParseDecimalRegister(this Data data,
@ -182,6 +182,7 @@ public static class BatteryDataParserV4
MPMM = Warning(38), MPMM = Warning(38),
TCMM = Warning(39), TCMM = Warning(39),
TCdi = Warning(40), TCdi = Warning(40),
LMPW = Warning(44)
}; };
} }
@ -222,18 +223,20 @@ public static class BatteryDataParserV4
TbCM = Alarm(36), TbCM = Alarm(36),
HTFS = Alarm(42), HTFS = Alarm(42),
DATA = Alarm(43), DATA = Alarm(43),
LMPA = Alarm(45),
HEBT = Alarm(46),
}; };
} }
private static BatteryStatus ParseBatteryStatus(this Data data, private static BatteryStatus ParseBatteryStatus(this Data data,
String installation, String installation,
String batteryId, String batteryId,
Decimal temperature, Decimal temperature,
Warnings warnings, Warnings warnings,
Alarms alarms, Alarms alarms,
DateTime lastSeen, DateTime lastSeen,
IPEndPoint endPoint) IPEndPoint endPoint)
{ {
var activeWarnings = Active(warnings); var activeWarnings = Active(warnings);
var activeAlarms = Active(alarms); var activeAlarms = Active(alarms);

View File

@ -18,29 +18,29 @@ public static class InfluxRecord
} }
public static IEnumerable<(String key, Object value)> GetFields(this Object record) public static IEnumerable<(String key, Object? value)> GetFields(this Object record)
{ {
return record return record
.GetProperties() .GetProperties()
.Where(p => p.HasAttribute<FieldAttribute>()) .Where(p => p.HasAttribute<FieldAttribute>())
.Where(p => p.IsReadable) .Where(p => p.IsReadable)
.Select(p => (key: p.Name, value: ConvertField(p))); .Select(p => (key: p.Name, value: ConvertField(p)));
} }
private static Object ConvertField(Property p) private static Object? ConvertField(Property p)
{ {
var value = p.Get(); var value = p.Get();
var type = p.GetAttributes<FieldAttribute>().Single().Type; var type = p.GetAttributes<FieldAttribute>().Single().Type;
return type != null return type != null
? Convert.ChangeType(value, type, InvariantCulture) ? Convert.ChangeType(value, type, InvariantCulture)
: value; : value;
} }
private static String ConvertTag(Property p) private static String ConvertTag(Property p)
{ {
return p.Get().ToString(); return p.Get()?.ToString()!;
} }
public static String Serialize(this Object record) public static String Serialize(this Object record)
@ -73,7 +73,7 @@ public static class InfluxRecord
fieldDelimiter = ','; fieldDelimiter = ',';
sb.Append(EscapeName(key)); sb.Append(EscapeName(key));
sb.Append('='); sb.Append('=');
sb.Append(FormatValue(value)); sb.Append(FormatValue(value!));
} }

View File

@ -14,9 +14,7 @@ using static InnovEnergy.Lib.Utils.ExceptionHandling;
namespace InnovEnergy.App.Collector; namespace InnovEnergy.App.Collector;
// TODO: net6 // dotnet publish Collector.csproj -c Release -r linux-x64 -p:PublishTrimmed=false -p:PublishSingleFile=true --self-contained true ; scp ./bin/Release/net6.0/linux-x64/publish/* ig@salidomo.innovenergy.ch:~/collector
// dotnet publish Collector.csproj -c Release -r linux-x64 -p:PublishSingleFile=true --self-contained true ; scp ./bin/Release/netcoreapp5.0/linux-x64/publish/* ig@salidomo.innovenergy.ch:~/collector
internal record BatteryData internal record BatteryData
( (
@ -33,9 +31,9 @@ internal static class Program
//private static readonly Logger Logger = new Logger(Settings.LoggingEndPoint); //private static readonly Logger Logger = new Logger(Settings.LoggingEndPoint);
private static UdpClient _incomingSocket = new UdpClient(Settings.IncomingEndPoint); private static UdpClient _incomingSocket = new UdpClient(Settings.IncomingEndPoint);
private static UdpClient _dbSocket = new UdpClient(); private static UdpClient _dbSocket = new UdpClient();
private static readonly Subject<BatteryData> Batteries = new Subject<BatteryData>(); private static readonly Subject<BatteryData> Batteries = new Subject<BatteryData>();
private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { WriteIndented = true }; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { WriteIndented = true };
public static void Main(String[] args) public static void Main(String[] args)
@ -62,9 +60,9 @@ internal static class Program
{ {
return new HttpResponse return new HttpResponse
{ {
Content = json.Apply(UTF8.GetBytes), Content = json.Apply(UTF8.GetBytes),
ContentType = ContentType.ApplicationJson, ContentType = ContentType.ApplicationJson,
Headers = new[] { new HttpHeader("Access-Control-Allow-Origin", "*") } Headers = new[] { new HttpHeader("Access-Control-Allow-Origin", "*") }
}; };
} }
@ -163,13 +161,13 @@ internal static class Program
private static void ResetDbSocket(Exception e) private static void ResetDbSocket(Exception e)
{ {
_dbSocket?.Dispose(); _dbSocket.Dispose();
_dbSocket = new UdpClient(); _dbSocket = new UdpClient();
} }
private static void ResetIncomingSocket(Exception e) private static void ResetIncomingSocket(Exception e)
{ {
_incomingSocket?.Dispose(); _incomingSocket.Dispose();
_incomingSocket = new UdpClient(Settings.IncomingEndPoint); _incomingSocket = new UdpClient(Settings.IncomingEndPoint);
} }
} }

View File

@ -8,34 +8,36 @@ namespace InnovEnergy.App.Collector.Records;
public class Alarms : BatteryRecord public class Alarms : BatteryRecord
{ {
[Tag] public String Installation { get; set; } [Tag] public required String Installation { get; init; }
[Tag] public String BatteryId { get; set; } [Tag] public required String BatteryId { get; init; }
[Field(typeof(Int32))] public Boolean Tam { get; set; } [Field(typeof(Int32))] public required Boolean Tam { get; init; }
[Field(typeof(Int32))] public Boolean TaM2 { get; set; } [Field(typeof(Int32))] public required Boolean TaM2 { get; init; }
[Field(typeof(Int32))] public Boolean Tbm { get; set; } [Field(typeof(Int32))] public required Boolean Tbm { get; init; }
[Field(typeof(Int32))] public Boolean TbM2 { get; set; } [Field(typeof(Int32))] public required Boolean TbM2 { get; init; }
[Field(typeof(Int32))] public Boolean VBm2 { get; set; } [Field(typeof(Int32))] public required Boolean VBm2 { get; init; }
[Field(typeof(Int32))] public Boolean VBM2 { get; set; } [Field(typeof(Int32))] public required Boolean VBM2 { get; init; }
[Field(typeof(Int32))] public Boolean IDM2 { get; set; } [Field(typeof(Int32))] public required Boolean IDM2 { get; init; }
[Field(typeof(Int32))] public Boolean MSWE { get; set; } [Field(typeof(Int32))] public required Boolean MSWE { get; init; }
[Field(typeof(Int32))] public Boolean FUSE { get; set; } [Field(typeof(Int32))] public required Boolean FUSE { get; init; }
[Field(typeof(Int32))] public Boolean HTRE { get; set; } [Field(typeof(Int32))] public required Boolean HTRE { get; init; }
[Field(typeof(Int32))] public Boolean TCPE { get; set; } [Field(typeof(Int32))] public required Boolean TCPE { get; init; }
[Field(typeof(Int32))] public Boolean CME { get; set; } [Field(typeof(Int32))] public required Boolean CME { get; init; }
[Field(typeof(Int32))] public Boolean HWFL { get; set; } [Field(typeof(Int32))] public required Boolean HWFL { get; init; }
[Field(typeof(Int32))] public Boolean HWEM { get; set; } [Field(typeof(Int32))] public required Boolean HWEM { get; init; }
[Field(typeof(Int32))] public Boolean ThM { get; set; } [Field(typeof(Int32))] public required Boolean ThM { get; init; }
[Field(typeof(Int32))] public Boolean vsm1 { get; set; } [Field(typeof(Int32))] public required Boolean vsm1 { get; init; }
[Field(typeof(Int32))] public Boolean vsm2 { get; set; } [Field(typeof(Int32))] public required Boolean vsm2 { get; init; }
[Field(typeof(Int32))] public Boolean vsM2 { get; set; } [Field(typeof(Int32))] public required Boolean vsM2 { get; init; }
[Field(typeof(Int32))] public Boolean iCM2 { get; set; } [Field(typeof(Int32))] public required Boolean iCM2 { get; init; }
[Field(typeof(Int32))] public Boolean iDM2 { get; set; } [Field(typeof(Int32))] public required Boolean iDM2 { get; init; }
[Field(typeof(Int32))] public Boolean MID2 { get; set; } [Field(typeof(Int32))] public required Boolean MID2 { get; init; }
[Field(typeof(Int32))] public Boolean CCBF { get; set; } [Field(typeof(Int32))] public required Boolean CCBF { get; init; }
[Field(typeof(Int32))] public Boolean AhFL { get; set; } [Field(typeof(Int32))] public required Boolean AhFL { get; init; }
[Field(typeof(Int32))] public Boolean TbCM { get; set; } [Field(typeof(Int32))] public required Boolean TbCM { get; init; }
[Field(typeof(Int32))] public Boolean HTFS { get; set; } [Field(typeof(Int32))] public required Boolean HTFS { get; init; }
[Field(typeof(Int32))] public Boolean DATA { get; set; } [Field(typeof(Int32))] public required Boolean DATA { get; init; }
[Field(typeof(Int32))] public Boolean ISOB { get; set; } [Field(typeof(Int32))] public required Boolean ISOB { get; init; }
[Field(typeof(Int32))] public required Boolean LMPA { get; init; }
[Field(typeof(Int32))] public required Boolean HEBT { get; init; }
} }

View File

@ -1,35 +1,32 @@
using InnovEnergy.App.Collector.Influx; using InnovEnergy.App.Collector.Influx;
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable MemberCanBePrivate.Global
namespace InnovEnergy.App.Collector.Records; namespace InnovEnergy.App.Collector.Records;
public class BatteryStatus : BatteryRecord public class BatteryStatus : BatteryRecord
{ {
[Tag] public String InstallationName { get; set; } [Tag] public required String InstallationName { get; init; }
[Tag] public String BatteryId { get; set; } [Tag] public required String BatteryId { get; init; }
[Field] public String HardwareVersion { get; set; } [Field] public required String HardwareVersion { get; init; }
[Field] public String FirmwareVersion { get; set; } [Field] public required String FirmwareVersion { get; init; }
[Field] public String BmsVersion { get; set; } [Field] public required String BmsVersion { get; init; }
[Field] public UInt32 AmpereHours { get; set; } [Field] public required UInt32 AmpereHours { get; init; }
[Field] public UInt32 RtcCounter { get; set; } [Field] public required UInt32 RtcCounter { get; init; }
[Field] public Decimal Voltage { get; set; } [Field] public required Decimal Voltage { get; init; }
[Field] public Decimal Current { get; set; } [Field] public required Decimal Current { get; init; }
[Field] public Decimal BusVoltage { get; set; } [Field] public required Decimal BusVoltage { get; init; }
[Field] public Decimal Soc { get; set; } [Field] public required Decimal Soc { get; init; }
[Field] public Decimal Temperature { get; set; } [Field] public required Decimal Temperature { get; init; }
[Field] public Int32 NumberOfWarnings { get; set; } [Field] public required Int32 NumberOfWarnings { get; init; }
[Field] public Int32 NumberOfAlarms { get; set; } [Field] public required Int32 NumberOfAlarms { get; init; }
[Field] public UInt64 WarningsBitmap { get; set; } [Field] public required UInt64 WarningsBitmap { get; init; }
[Field] public UInt64 AlarmsBitmap { get; set; } [Field] public required UInt64 AlarmsBitmap { get; init; }
[Field] public Int64 LastSeen { get; set; } [Field] public required Int64 LastSeen { get; init; }
[Field] public String IpAddress { get; set; } [Field] public required String IpAddress { get; init; }
[Field] public Int32 Port { get; set; } [Field] public required Int32 Port { get; init; }
} }

View File

@ -1,11 +0,0 @@
using InnovEnergy.App.Collector.Influx;
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace InnovEnergy.App.Collector.Records;
public class Error : BatteryRecord
{
[Field] public String Message { get; set; }
[Field] public String IpAddress { get; set; }
}

View File

@ -1,65 +0,0 @@
using InnovEnergy.App.Collector.Influx;
namespace InnovEnergy.App.Collector.Records;
public class InstallationStatus : BatteryRecord
{
[Tag] public String InstallationName { get; set; }
[Field] public Decimal Voltage { get; set; }
[Field] public Decimal Current { get; set; }
[Field] public Decimal BusVoltage { get; set; }
[Field] public Decimal Soc { get; set; }
[Field] public Decimal Temperature { get; set; }
[Field] public Int64 LastSeen { get; set; }
[Field] public String IpAddress { get; set; }
[Field] public Int32 Port { get; set; }
// Warnings
[Field(typeof(Int32))] public Boolean TaM1 { get; set; }
[Field(typeof(Int32))] public Boolean TbM1 { get; set; }
[Field(typeof(Int32))] public Boolean VBm1 { get; set; }
[Field(typeof(Int32))] public Boolean VBM1 { get; set; }
[Field(typeof(Int32))] public Boolean IDM1 { get; set; }
[Field(typeof(Int32))] public Boolean vsM1 { get; set; }
[Field(typeof(Int32))] public Boolean iCM1 { get; set; }
[Field(typeof(Int32))] public Boolean iDM1 { get; set; }
[Field(typeof(Int32))] public Boolean MID1 { get; set; }
[Field(typeof(Int32))] public Boolean BLPW { get; set; }
[Field(typeof(Int32))] public Boolean Ah_W { get; set; }
[Field(typeof(Int32))] public Boolean MPMM { get; set; }
[Field(typeof(Int32))] public Boolean TCMM { get; set; }
[Field(typeof(Int32))] public Boolean TCdi { get; set; }
// Alarms
[Field(typeof(Int32))] public Boolean Tam { get; set; }
[Field(typeof(Int32))] public Boolean TaM2 { get; set; }
[Field(typeof(Int32))] public Boolean Tbm { get; set; }
[Field(typeof(Int32))] public Boolean TbM2 { get; set; }
[Field(typeof(Int32))] public Boolean VBm2 { get; set; }
[Field(typeof(Int32))] public Boolean VBM2 { get; set; }
[Field(typeof(Int32))] public Boolean IDM2 { get; set; }
[Field(typeof(Int32))] public Boolean MSWE { get; set; }
[Field(typeof(Int32))] public Boolean FUSE { get; set; }
[Field(typeof(Int32))] public Boolean HTRE { get; set; }
[Field(typeof(Int32))] public Boolean TCPE { get; set; }
[Field(typeof(Int32))] public Boolean CME { get; set; }
[Field(typeof(Int32))] public Boolean HWFL { get; set; }
[Field(typeof(Int32))] public Boolean HWEM { get; set; }
[Field(typeof(Int32))] public Boolean ThM { get; set; }
[Field(typeof(Int32))] public Boolean vsm1 { get; set; }
[Field(typeof(Int32))] public Boolean vsm2 { get; set; }
[Field(typeof(Int32))] public Boolean vsM2 { get; set; }
[Field(typeof(Int32))] public Boolean iCM2 { get; set; }
[Field(typeof(Int32))] public Boolean iDM2 { get; set; }
[Field(typeof(Int32))] public Boolean MID2 { get; set; }
[Field(typeof(Int32))] public Boolean CCBF { get; set; }
[Field(typeof(Int32))] public Boolean AhFL { get; set; }
[Field(typeof(Int32))] public Boolean TbCM { get; set; }
[Field(typeof(Int32))] public Boolean HTFS { get; set; }
[Field(typeof(Int32))] public Boolean DATA { get; set; }
[Field(typeof(Int32))] public Boolean ISOB { get; set; }
}

View File

@ -1,20 +1,18 @@
using InnovEnergy.App.Collector.Influx; using InnovEnergy.App.Collector.Influx;
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace InnovEnergy.App.Collector.Records; namespace InnovEnergy.App.Collector.Records;
public class IoStatus : BatteryRecord public class IoStatus : BatteryRecord
{ {
[Tag] public String Installation { get; set; } [Tag] public required String Installation { get; init; }
[Tag] public String BatteryId { get; set; } [Tag] public required String BatteryId { get; init; }
[Field(typeof(Int32))] public Boolean MainSwitchClosed { get; set; }
[Field(typeof(Int32))] public Boolean AlarmOutActive { get; set; }
[Field(typeof(Int32))] public Boolean InternalFanActive { get; set; }
[Field(typeof(Int32))] public Boolean VoltMeasurementAllowed { get; set; }
[Field(typeof(Int32))] public Boolean AuxRelay { get; set; }
[Field(typeof(Int32))] public Boolean RemoteState { get; set; }
[Field(typeof(Int32))] public Boolean HeatingOn { get; set; }
[Field(typeof(Int32))] public required Boolean MainSwitchClosed { get; init; }
[Field(typeof(Int32))] public required Boolean AlarmOutActive { get; init; }
[Field(typeof(Int32))] public required Boolean InternalFanActive { get; init; }
[Field(typeof(Int32))] public required Boolean VoltMeasurementAllowed { get; init; }
[Field(typeof(Int32))] public required Boolean AuxRelay { get; init; }
[Field(typeof(Int32))] public required Boolean RemoteState { get; init; }
[Field(typeof(Int32))] public required Boolean HeatingOn { get; init; }
} }

View File

@ -7,13 +7,13 @@ namespace InnovEnergy.App.Collector.Records;
public class Leds : BatteryRecord public class Leds : BatteryRecord
{ {
[Tag] public String Installation { get; set; } [Tag] public required String Installation { get; init; }
[Tag] public String BatteryId { get; set; } [Tag] public required String BatteryId { get; init; }
[Field] public LedState Green { get; set; } [Field] public required LedState Green { get; set; }
[Field] public LedState Amber { get; set; } [Field] public required LedState Amber { get; set; }
[Field] public LedState Blue { get; set; } [Field] public required LedState Blue { get; set; }
[Field] public LedState Red { get; set; } [Field] public required LedState Red { get; set; }
} }

View File

@ -1,26 +1,30 @@
using InnovEnergy.App.Collector.Influx; using System.Diagnostics.CodeAnalysis;
using InnovEnergy.App.Collector.Influx;
namespace InnovEnergy.App.Collector.Records; namespace InnovEnergy.App.Collector.Records;
#pragma warning disable CS8618 #pragma warning disable CS8618
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "IdentifierTypo")]
public class Warnings : BatteryRecord public class Warnings : BatteryRecord
{ {
[Tag] public String Installation { get; init; } [Tag] public required String Installation { get; init; }
[Tag] public String BatteryId { get; init; } [Tag] public required String BatteryId { get; init; }
[Field(typeof(Int32))] public Boolean TaM1 { get; init; } [Field(typeof(Int32))] public required Boolean TaM1 { get; init; }
[Field(typeof(Int32))] public Boolean TbM1 { get; init; } [Field(typeof(Int32))] public required Boolean TbM1 { get; init; }
[Field(typeof(Int32))] public Boolean VBm1 { get; init; } [Field(typeof(Int32))] public required Boolean VBm1 { get; init; }
[Field(typeof(Int32))] public Boolean VBM1 { get; init; } [Field(typeof(Int32))] public required Boolean VBM1 { get; init; }
[Field(typeof(Int32))] public Boolean IDM1 { get; init; } [Field(typeof(Int32))] public required Boolean IDM1 { get; init; }
[Field(typeof(Int32))] public Boolean vsM1 { get; init; } [Field(typeof(Int32))] public required Boolean vsM1 { get; init; }
[Field(typeof(Int32))] public Boolean iCM1 { get; init; } [Field(typeof(Int32))] public required Boolean iCM1 { get; init; }
[Field(typeof(Int32))] public Boolean iDM1 { get; init; } [Field(typeof(Int32))] public required Boolean iDM1 { get; init; }
[Field(typeof(Int32))] public Boolean MID1 { get; init; } [Field(typeof(Int32))] public required Boolean MID1 { get; init; }
[Field(typeof(Int32))] public Boolean BLPW { get; init; } [Field(typeof(Int32))] public required Boolean BLPW { get; init; }
[Field(typeof(Int32))] public Boolean Ah_W { get; init; } [Field(typeof(Int32))] public required Boolean Ah_W { get; init; }
[Field(typeof(Int32))] public Boolean MPMM { get; init; } [Field(typeof(Int32))] public required Boolean MPMM { get; init; }
[Field(typeof(Int32))] public Boolean TCMM { get; init; } [Field(typeof(Int32))] public required Boolean TCMM { get; init; }
[Field(typeof(Int32))] public Boolean TCdi { get; init; } [Field(typeof(Int32))] public required Boolean TCdi { get; init; }
[Field(typeof(Int32))] public required Boolean LMPW { get; init; }
} }

View File

@ -22,15 +22,15 @@ public readonly struct Property
public String Name => PropertyInfo.Name; public String Name => PropertyInfo.Name;
public Type Type => PropertyInfo.PropertyType; public Type Type => PropertyInfo.PropertyType;
public Object Get() => PropertyInfo.GetValue(Instance); public Object? Get() => PropertyInfo.GetValue(Instance);
public T Get<T>() => (T) PropertyInfo.GetValue(Instance); public T? Get<T>() => (T?) PropertyInfo.GetValue(Instance);
public void Set(Object value) => PropertyInfo.SetValue(Instance, value); public void Set(Object value) => PropertyInfo.SetValue(Instance, value);
public IEnumerable<T> GetAttributes<T> () where T : Attribute => PropertyInfo public IEnumerable<T> GetAttributes<T> () where T : Attribute => PropertyInfo
.GetCustomAttributes(inherit: false) .GetCustomAttributes(inherit: false)
.OfType<T>(); .OfType<T>();
public Boolean HasAttribute<T> () where T : Attribute => GetAttributes<T>().Any(); public Boolean HasAttribute<T> () where T : Attribute => GetAttributes<T>().Any();
@ -41,9 +41,9 @@ public static class PropertyExtensions
public static IEnumerable<Property> GetProperties(this Object instance) public static IEnumerable<Property> GetProperties(this Object instance)
{ {
return instance return instance
.GetType() .GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public) .GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Unless(p => p.GetIndexParameters().Any()) // no indexers please .Unless(p => p.GetIndexParameters().Any()) // no indexers please
.Select(pi => new Property(instance, pi)); .Select(pi => new Property(instance, pi));
} }
} }

View File

@ -2,11 +2,8 @@
public static class Utils public static class Utils
{ {
public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static IEnumerable<ArraySegment<Byte>> ParseLengthValueEncoded(this Byte[] source) public static IEnumerable<ArraySegment<Byte>> ParseLengthValueEncoded(this Byte[] source)
{ {
var index = 0; var index = 0;

View File

@ -1,7 +1,6 @@
using InnovEnergy.Lib.Protocols.Modbus.Channels; using InnovEnergy.Lib.Protocols.Modbus.Channels;
using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Clients;
using InnovEnergy.Lib.Protocols.Modbus.Slaves; using InnovEnergy.Lib.Protocols.Modbus.Slaves;
using InnovEnergy.Lib.Time.Unix;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;