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>
<RootNamespace>InnovEnergy.App.Collector</RootNamespace>
<IsTrimmable>false</IsTrimmable>
</PropertyGroup>
<ItemGroup>

View File

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

View File

@ -72,9 +72,9 @@ public static class BatteryDataParserV4
private static String NextString(this IEnumerator<ArraySegment<Byte>> enumerator)
{
return enumerator
.Next()
.ToArray()
.Apply(Encoding.UTF8.GetString);
.Next()
.ToArray()
.Apply(Encoding.UTF8.GetString);
}
@ -98,9 +98,9 @@ public static class BatteryDataParserV4
private static UInt64 ParseUInt64Register (this Data data, Int32 register)
{
return Enumerable
.Range(0, 4)
.Select(i => Convert.ToUInt64(data.ParseUInt16Register(register + i)) << (i * 16))
.Aggregate(0ul, (a, b) => a + b); // Sum() does not work for UInt64 :(
.Range(0, 4)
.Select(i => Convert.ToUInt64(data.ParseUInt16Register(register + i)) << (i * 16))
.Aggregate(0ul, (a, b) => a + b); // Sum() does not work for UInt64 :(
}
private static Decimal ParseDecimalRegister(this Data data,
@ -182,6 +182,7 @@ public static class BatteryDataParserV4
MPMM = Warning(38),
TCMM = Warning(39),
TCdi = Warning(40),
LMPW = Warning(44)
};
}
@ -222,18 +223,20 @@ public static class BatteryDataParserV4
TbCM = Alarm(36),
HTFS = Alarm(42),
DATA = Alarm(43),
LMPA = Alarm(45),
HEBT = Alarm(46),
};
}
private static BatteryStatus ParseBatteryStatus(this Data data,
String installation,
String batteryId,
Decimal temperature,
Warnings warnings,
Alarms alarms,
DateTime lastSeen,
IPEndPoint endPoint)
String installation,
String batteryId,
Decimal temperature,
Warnings warnings,
Alarms alarms,
DateTime lastSeen,
IPEndPoint endPoint)
{
var activeWarnings = Active(warnings);
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
.GetProperties()
.Where(p => p.HasAttribute<FieldAttribute>())
.Where(p => p.IsReadable)
.Select(p => (key: p.Name, value: ConvertField(p)));
.GetProperties()
.Where(p => p.HasAttribute<FieldAttribute>())
.Where(p => p.IsReadable)
.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 type = p.GetAttributes<FieldAttribute>().Single().Type;
return type != null
? Convert.ChangeType(value, type, InvariantCulture)
: value;
? Convert.ChangeType(value, type, InvariantCulture)
: value;
}
private static String ConvertTag(Property p)
{
return p.Get().ToString();
return p.Get()?.ToString()!;
}
public static String Serialize(this Object record)
@ -73,7 +73,7 @@ public static class InfluxRecord
fieldDelimiter = ',';
sb.Append(EscapeName(key));
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;
// TODO: net6
// 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
// 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
internal record BatteryData
(
@ -33,9 +31,9 @@ internal static class Program
//private static readonly Logger Logger = new Logger(Settings.LoggingEndPoint);
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 };
public static void Main(String[] args)
@ -62,9 +60,9 @@ internal static class Program
{
return new HttpResponse
{
Content = json.Apply(UTF8.GetBytes),
Content = json.Apply(UTF8.GetBytes),
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)
{
_dbSocket?.Dispose();
_dbSocket.Dispose();
_dbSocket = new UdpClient();
}
private static void ResetIncomingSocket(Exception e)
{
_incomingSocket?.Dispose();
_incomingSocket.Dispose();
_incomingSocket = new UdpClient(Settings.IncomingEndPoint);
}
}

View File

@ -8,34 +8,36 @@ namespace InnovEnergy.App.Collector.Records;
public class Alarms : BatteryRecord
{
[Tag] public String Installation { get; set; }
[Tag] public String BatteryId { get; set; }
[Tag] public required String Installation { get; init; }
[Tag] public required String BatteryId { get; init; }
[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; }
[Field(typeof(Int32))] public required Boolean Tam { get; init; }
[Field(typeof(Int32))] public required Boolean TaM2 { get; init; }
[Field(typeof(Int32))] public required Boolean Tbm { get; init; }
[Field(typeof(Int32))] public required Boolean TbM2 { get; init; }
[Field(typeof(Int32))] public required Boolean VBm2 { get; init; }
[Field(typeof(Int32))] public required Boolean VBM2 { get; init; }
[Field(typeof(Int32))] public required Boolean IDM2 { get; init; }
[Field(typeof(Int32))] public required Boolean MSWE { get; init; }
[Field(typeof(Int32))] public required Boolean FUSE { get; init; }
[Field(typeof(Int32))] public required Boolean HTRE { get; init; }
[Field(typeof(Int32))] public required Boolean TCPE { get; init; }
[Field(typeof(Int32))] public required Boolean CME { get; init; }
[Field(typeof(Int32))] public required Boolean HWFL { get; init; }
[Field(typeof(Int32))] public required Boolean HWEM { get; init; }
[Field(typeof(Int32))] public required Boolean ThM { get; init; }
[Field(typeof(Int32))] public required Boolean vsm1 { get; init; }
[Field(typeof(Int32))] public required Boolean vsm2 { get; init; }
[Field(typeof(Int32))] public required Boolean vsM2 { get; init; }
[Field(typeof(Int32))] public required Boolean iCM2 { get; init; }
[Field(typeof(Int32))] public required Boolean iDM2 { get; init; }
[Field(typeof(Int32))] public required Boolean MID2 { get; init; }
[Field(typeof(Int32))] public required Boolean CCBF { get; init; }
[Field(typeof(Int32))] public required Boolean AhFL { get; init; }
[Field(typeof(Int32))] public required Boolean TbCM { get; init; }
[Field(typeof(Int32))] public required Boolean HTFS { get; init; }
[Field(typeof(Int32))] public required Boolean DATA { get; init; }
[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;
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable MemberCanBePrivate.Global
namespace InnovEnergy.App.Collector.Records;
public class BatteryStatus : BatteryRecord
{
[Tag] public String InstallationName { get; set; }
[Tag] public String BatteryId { get; set; }
[Tag] public required String InstallationName { get; init; }
[Tag] public required String BatteryId { get; init; }
[Field] public String HardwareVersion { get; set; }
[Field] public String FirmwareVersion { get; set; }
[Field] public String BmsVersion { get; set; }
[Field] public UInt32 AmpereHours { get; set; }
[Field] public UInt32 RtcCounter { get; set; }
[Field] public required String HardwareVersion { get; init; }
[Field] public required String FirmwareVersion { get; init; }
[Field] public required String BmsVersion { get; init; }
[Field] public required UInt32 AmpereHours { get; init; }
[Field] public required UInt32 RtcCounter { get; init; }
[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 required Decimal Voltage { get; init; }
[Field] public required Decimal Current { get; init; }
[Field] public required Decimal BusVoltage { get; init; }
[Field] public required Decimal Soc { get; init; }
[Field] public required Decimal Temperature { get; init; }
[Field] public Int32 NumberOfWarnings { get; set; }
[Field] public Int32 NumberOfAlarms { get; set; }
[Field] public required Int32 NumberOfWarnings { get; init; }
[Field] public required Int32 NumberOfAlarms { get; init; }
[Field] public UInt64 WarningsBitmap { get; set; }
[Field] public UInt64 AlarmsBitmap { get; set; }
[Field] public required UInt64 WarningsBitmap { get; init; }
[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 Int32 Port { get; set; }
[Field] public required String IpAddress { get; init; }
[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;
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace InnovEnergy.App.Collector.Records;
public class IoStatus : BatteryRecord
{
[Tag] public String Installation { get; set; }
[Tag] public String BatteryId { get; set; }
[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; }
[Tag] public required String Installation { get; init; }
[Tag] public required String BatteryId { get; init; }
[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
{
[Tag] public String Installation { get; set; }
[Tag] public String BatteryId { get; set; }
[Tag] public required String Installation { get; init; }
[Tag] public required String BatteryId { get; init; }
[Field] public LedState Green { get; set; }
[Field] public LedState Amber { get; set; }
[Field] public LedState Blue { get; set; }
[Field] public LedState Red { get; set; }
[Field] public required LedState Green { get; set; }
[Field] public required LedState Amber { get; set; }
[Field] public required LedState Blue { 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;
#pragma warning disable CS8618
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "IdentifierTypo")]
public class Warnings : BatteryRecord
{
[Tag] public String Installation { get; init; }
[Tag] public String BatteryId { get; init; }
[Tag] public required String Installation { get; init; }
[Tag] public required String BatteryId { get; init; }
[Field(typeof(Int32))] public Boolean TaM1 { get; init; }
[Field(typeof(Int32))] public Boolean TbM1 { get; init; }
[Field(typeof(Int32))] public Boolean VBm1 { get; init; }
[Field(typeof(Int32))] public Boolean VBM1 { get; init; }
[Field(typeof(Int32))] public Boolean IDM1 { get; init; }
[Field(typeof(Int32))] public Boolean vsM1 { get; init; }
[Field(typeof(Int32))] public Boolean iCM1 { get; init; }
[Field(typeof(Int32))] public Boolean iDM1 { get; init; }
[Field(typeof(Int32))] public Boolean MID1 { get; init; }
[Field(typeof(Int32))] public Boolean BLPW { get; init; }
[Field(typeof(Int32))] public Boolean Ah_W { get; init; }
[Field(typeof(Int32))] public Boolean MPMM { get; init; }
[Field(typeof(Int32))] public Boolean TCMM { get; init; }
[Field(typeof(Int32))] public Boolean TCdi { get; init; }
[Field(typeof(Int32))] public required Boolean TaM1 { get; init; }
[Field(typeof(Int32))] public required Boolean TbM1 { get; init; }
[Field(typeof(Int32))] public required Boolean VBm1 { get; init; }
[Field(typeof(Int32))] public required Boolean VBM1 { get; init; }
[Field(typeof(Int32))] public required Boolean IDM1 { get; init; }
[Field(typeof(Int32))] public required Boolean vsM1 { get; init; }
[Field(typeof(Int32))] public required Boolean iCM1 { get; init; }
[Field(typeof(Int32))] public required Boolean iDM1 { get; init; }
[Field(typeof(Int32))] public required Boolean MID1 { get; init; }
[Field(typeof(Int32))] public required Boolean BLPW { get; init; }
[Field(typeof(Int32))] public required Boolean Ah_W { get; init; }
[Field(typeof(Int32))] public required Boolean MPMM { get; init; }
[Field(typeof(Int32))] public required Boolean TCMM { 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 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 IEnumerable<T> GetAttributes<T> () where T : Attribute => PropertyInfo
.GetCustomAttributes(inherit: false)
.OfType<T>();
.GetCustomAttributes(inherit: false)
.OfType<T>();
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)
{
return instance
.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Unless(p => p.GetIndexParameters().Any()) // no indexers please
.Select(pi => new Property(instance, pi));
.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Unless(p => p.GetIndexParameters().Any()) // no indexers please
.Select(pi => new Property(instance, pi));
}
}

View File

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

View File

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