This commit is contained in:
Sina Blattmann 2023-03-08 13:01:56 +01:00
commit 40f5c8c391
30 changed files with 62 additions and 48 deletions

View File

@ -4,6 +4,7 @@ using Innovenergy.Backend.Database;
using Innovenergy.Backend.Model; using Innovenergy.Backend.Model;
using Innovenergy.Backend.Model.Relations; using Innovenergy.Backend.Model.Relations;
using Innovenergy.Backend.Utils; using Innovenergy.Backend.Utils;
using InnovEnergy.Lib.Utils;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor; using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor;
@ -173,7 +174,8 @@ public class Controller
using var db = Db.Connect(); using var db = Db.Connect();
var folders = db var folders = db
.GetDirectlyAccessibleFolders(caller) // ReSharper disable once AccessToDisposedClosure .GetDirectlyAccessibleFolders(caller)
.Do(f => f.ParentId = 0) // ReSharper disable once AccessToDisposedClosure
.Select(f => PopulateChildren(db, f)); .Select(f => PopulateChildren(db, f));
var installations = db.GetDirectlyAccessibleInstallations(caller); var installations = db.GetDirectlyAccessibleInstallations(caller);

Binary file not shown.

View File

@ -0,0 +1,10 @@
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
[Flags]
public enum Endianness
{
LittleEndian32BitIntegers = 0,
LittleEndian32Floats = 0,
BigEndian32BitIntegers = 1,
BigEndian32Floats = 2,
}

View File

@ -1,6 +1,6 @@
using System.Threading.Channels;
using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.Protocols.Modbus.Connections;
using InnovEnergy.Lib.Protocols.Modbus.Conversions; using InnovEnergy.Lib.Protocols.Modbus.Conversions;
using static InnovEnergy.Lib.Protocols.Modbus.Clients.Endianness;
namespace InnovEnergy.Lib.Protocols.Modbus.Clients; namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
@ -13,8 +13,9 @@ public abstract class ModbusClient
{ {
protected ModbusConnection Connection { get; } protected ModbusConnection Connection { get; }
protected Byte SlaveId { get; } protected Byte SlaveId { get; }
protected Endianness Endianness { get; }
// TODO: add additional functions: coils... // TODO: add additional functions: coils...
public abstract Coils ReadDiscreteInputs (UInt16 readAddress, UInt16 nValues); public abstract Coils ReadDiscreteInputs (UInt16 readAddress, UInt16 nValues);
@ -40,11 +41,11 @@ public abstract class ModbusClient
return WriteRegisters(writeAddress, (IReadOnlyList<UInt16>)values); return WriteRegisters(writeAddress, (IReadOnlyList<UInt16>)values);
} }
protected ModbusClient(ModbusConnection connection, Byte slaveId, Endianness endianness = LittleEndian32BitIntegers | LittleEndian32Floats)
protected ModbusClient(ModbusConnection connection, Byte slaveId)
{ {
Connection = connection; Connection = connection;
SlaveId = slaveId; SlaveId = slaveId;
Endianness = endianness;
} }
public void CloseConnection() => Connection.Close(); public void CloseConnection() => Connection.Close();

View File

@ -4,13 +4,13 @@ using InnovEnergy.Lib.Protocols.Modbus.Conversions;
using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands;
using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies;
using InnovEnergy.Lib.Protocols.Modbus.Tcp; using InnovEnergy.Lib.Protocols.Modbus.Tcp;
using static InnovEnergy.Lib.Protocols.Modbus.Clients.Endianness;
namespace InnovEnergy.Lib.Protocols.Modbus.Clients; namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
using UInt16s = IReadOnlyList<UInt16>; using UInt16s = IReadOnlyList<UInt16>;
using Coils = IReadOnlyList<Boolean>; using Coils = IReadOnlyList<Boolean>;
public class ModbusTcpClient : ModbusClient public class ModbusTcpClient : ModbusClient
{ {
public const UInt16 DefaultPort = 502; public const UInt16 DefaultPort = 502;
@ -20,7 +20,7 @@ public class ModbusTcpClient : ModbusClient
private UInt16 NextId() => unchecked(++_Id); private UInt16 NextId() => unchecked(++_Id);
public ModbusTcpClient(ModbusConnection connection, Byte slaveId) : base(connection, slaveId) public ModbusTcpClient(ModbusConnection connection, Byte slaveId, Endianness endianness = LittleEndian32BitIntegers | LittleEndian32Floats) : base(connection, slaveId, endianness)
{ {
} }

View File

@ -1,4 +1,5 @@
using System.Collections; using System.Collections;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.Protocols.Modbus.Conversions; namespace InnovEnergy.Lib.Protocols.Modbus.Conversions;
@ -8,7 +9,7 @@ public partial class ModbusRegisters
{ {
var offset = index - StartRegister; var offset = index - StartRegister;
var byteArray = BitConverter.GetBytes(Registers[offset]).Reverse().ToArray(); var byteArray = Registers[offset].Apply(BitConverter.GetBytes).Reverse().ToArray();
var bitArray = new BitArray(byteArray); var bitArray = new BitArray(byteArray);
return bitArray.Get(bitIndex); return bitArray.Get(bitIndex);
@ -18,7 +19,7 @@ public partial class ModbusRegisters
{ {
var offset = index - StartRegister; var offset = index - StartRegister;
var byteArray = BitConverter.GetBytes(Registers[offset]).Reverse().ToArray(); var byteArray = Registers[offset].Apply(BitConverter.GetBytes).Reverse().ToArray();
var bitArray = new BitArray(byteArray); var bitArray = new BitArray(byteArray);
bitArray.Set(bitIndex, value); bitArray.Set(bitIndex, value);

View File

@ -9,7 +9,7 @@ public partial class ModbusRegisters
var bytearray = BitConverter.GetBytes(value).Reverse().ToArray(); var bytearray = BitConverter.GetBytes(value).Reverse().ToArray();
var value32 = BitConverter.ToUInt32(bytearray); var value32 = BitConverter.ToUInt32(bytearray);
Registers[index - StartRegister] = (UInt16)(value32 >> 16); Registers[index - StartRegister ] = (UInt16)(value32 >> 16);
Registers[index - StartRegister + 1] = (UInt16)(value32 & 0xFFFF); Registers[index - StartRegister + 1] = (UInt16)(value32 & 0xFFFF);
} }

View File

@ -9,8 +9,8 @@ public static class Accessors
public static MbWord WordAt (this ArraySegment<Byte> data, Byte i) => new MbWord(data, i); public static MbWord WordAt (this ArraySegment<Byte> data, Byte i) => new MbWord(data, i);
public static MbAddress AddressAt(this ArraySegment<Byte> data, Byte i) => new MbAddress(data, i); public static MbAddress AddressAt(this ArraySegment<Byte> data, Byte i) => new MbAddress(data, i);
public static MbWords WordsAt(this ArraySegment<Byte> data, Byte i) => new MbWords(data, i); public static MbRegisters RegistersAt(this ArraySegment<Byte> data, Byte i) => new MbRegisters(data, i);
public static MbBits BitsAt (this ArraySegment<Byte> data, Byte i) => new MbBits(data, i); public static MbBits BitsAt (this ArraySegment<Byte> data, Byte i) => new MbBits(data, i);
public static MbByte<T> ByteAt<T>(this ArraySegment<Byte> data,Byte i) where T : struct, IConvertible => new MbByte<T>(data, i); public static MbByte<T> ByteAt<T>(this ArraySegment<Byte> data,Byte i) where T : struct, IConvertible => new MbByte<T>(data, i);

View File

@ -3,30 +3,30 @@ using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors; namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors;
public readonly struct MbWords : IReadOnlyList<UInt16> public readonly struct MbRegisters : IReadOnlyList<UInt16>
{ {
private readonly ArraySegment<Byte> _Data; private readonly ArraySegment<Byte> _Data;
internal MbWords(ArraySegment<Byte> data, Byte startIndex) : this(data, startIndex, CountWords(data, startIndex)) internal MbRegisters(ArraySegment<Byte> data, Byte startIndex) : this(data, startIndex, CountWords(data, startIndex))
{ } { }
internal MbRegisters(ArraySegment<Byte> data, Byte startIndex, UInt16 wordCount) : this(data.Array!, startIndex, wordCount)
{
}
internal MbRegisters(Byte[] data, Byte startIndex, UInt16 wordCount)
{
_Data = new ArraySegment<Byte>(data, startIndex, wordCount * 2);
}
private static UInt16 CountWords(ArraySegment<Byte> data, Byte startIndex) private static UInt16 CountWords(ArraySegment<Byte> data, Byte startIndex)
{ {
var wordCount = (data.Count - startIndex) / 2; var wordCount = (data.Count - startIndex) / 2;
return wordCount.ConvertTo<UInt16>(); return wordCount.ConvertTo<UInt16>();
} }
internal MbWords(ArraySegment<Byte> data, Byte startIndex, UInt16 wordCount) : this(data.Array!, startIndex, wordCount)
{
}
internal MbWords(Byte[] data, Byte startIndex, UInt16 wordCount)
{
_Data = new ArraySegment<Byte>(data, startIndex, wordCount * 2);
}
internal IReadOnlyCollection<UInt16> Set(IReadOnlyCollection<UInt16> values) internal IReadOnlyCollection<UInt16> Set(IReadOnlyCollection<UInt16> values)
{ {
if (values.Count != _Data.Count / 2) if (values.Count != _Data.Count / 2)

View File

@ -16,7 +16,7 @@ internal class ReadWriteRegistersCommandFrame : ModbusFrame
public MbAddress WriteAddress => Data.AddressAt(6); public MbAddress WriteAddress => Data.AddressAt(6);
public MbWord NbToWrite => Data.WordAt(8); public MbWord NbToWrite => Data.WordAt(8);
public MbByte ByteCount => Data.ByteAt(10); public MbByte ByteCount => Data.ByteAt(10);
public MbWords RegistersToWrite => Data.WordsAt(11); public MbRegisters RegistersToWrite => Data.RegistersAt(11);
public Int32 ExpectedResponseSize => ReadWriteRegistersResponseFrame.ExpectedSize(NbToRead); public Int32 ExpectedResponseSize => ReadWriteRegistersResponseFrame.ExpectedSize(NbToRead);

View File

@ -14,7 +14,7 @@ internal class WriteRegistersCommandFrame : ModbusFrame
public MbAddress WriteAddress => Data.AddressAt(2); public MbAddress WriteAddress => Data.AddressAt(2);
public MbWord NbOfRegisters => Data.WordAt(4); public MbWord NbOfRegisters => Data.WordAt(4);
public MbByte ByteCount => Data.ByteAt(6); public MbByte ByteCount => Data.ByteAt(6);
public MbWords RegistersToWrite => Data.WordsAt(7); public MbRegisters RegistersToWrite => Data.RegistersAt(7);
public Int32 ExpectedResponseSize => WriteRegistersResponseFrame.ExpectedSize(); public Int32 ExpectedResponseSize => WriteRegistersResponseFrame.ExpectedSize();

View File

@ -11,7 +11,7 @@ internal class ReadHoldingRegistersResponseFrame : ModbusFrame
internal new const Int32 MinSize = 3; internal new const Int32 MinSize = 3;
public MbByte ByteCount => Data.ByteAt(2); public MbByte ByteCount => Data.ByteAt(2);
public MbWords RegistersRead => Data.WordsAt(3); public MbRegisters RegistersRead => Data.RegistersAt(3);
public ReadHoldingRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count)) public ReadHoldingRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count))

View File

@ -12,7 +12,7 @@ internal class ReadInputRegistersResponseFrame : ModbusFrame
internal new const Int32 MinSize = 3; internal new const Int32 MinSize = 3;
public MbByte ByteCount => Data.ByteAt(2); public MbByte ByteCount => Data.ByteAt(2);
public MbWords RegistersRead => Data.WordsAt(3); public MbRegisters RegistersRead => Data.RegistersAt(3);
public ReadInputRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count)) public ReadInputRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count))
{ {

View File

@ -12,7 +12,7 @@ internal class ReadWriteRegistersResponseFrame : ModbusFrame
internal new const Int32 MinSize = 3; internal new const Int32 MinSize = 3;
public MbByte ByteCount => Data.ByteAt(2); public MbByte ByteCount => Data.ByteAt(2);
public MbWords RegistersRead => Data.WordsAt(3); public MbRegisters RegistersRead => Data.RegistersAt(3);
public ReadWriteRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count)) public ReadWriteRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count))
{ {

View File

@ -1,26 +1,14 @@
using System.Text.Json;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using static InnovEnergy.Lib.Units.Units;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
public abstract record DeviceStatus public abstract record DeviceStatus
{ {
private static readonly JsonSerializerOptions JsonSerializerOptions;
static DeviceStatus()
{
JsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
JsonConverters.ForEach(JsonSerializerOptions.Converters.Add); // how stupid is that?!!
}
public String DeviceType => GetType() public String DeviceType => GetType()
.Generate(t => t.BaseType!) .Unfold(t => t.BaseType)
.First(t => t.IsAbstract) .First(t => t.IsAbstract)
.Name .Name
.Replace("Status", ""); .Replace("Status", "");
public String ToJson() => JsonSerializer.Serialize(this, GetType(), JsonSerializerOptions);
} }

View File

@ -6,7 +6,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Utils\Utils.csproj" /> <ProjectReference Include="../Utils/Utils.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Angle; using T = Angle;
[JsonConverter(typeof(AngleConverter))]
public readonly partial struct Angle public readonly partial struct Angle
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = ApparentPower; using T = ApparentPower;
[JsonConverter(typeof(ApparentPowerConverter))]
public readonly partial struct ApparentPower public readonly partial struct ApparentPower
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Current; using T = Current;
[JsonConverter(typeof(CurrentConverter))]
public readonly partial struct Current public readonly partial struct Current
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Frequency; using T = Frequency;
[JsonConverter(typeof(FrequencyConverter))]
public readonly partial struct Frequency public readonly partial struct Frequency
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Template; using T = Template;
[JsonConverter(typeof(TemplateConverter))]
public readonly partial struct Template public readonly partial struct Template
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Number; using T = Number;
[JsonConverter(typeof(NumberConverter))]
public readonly partial struct Number public readonly partial struct Number
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Power; using T = Power;
[JsonConverter(typeof(PowerConverter))]
public readonly partial struct Power public readonly partial struct Power
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = ReactivePower; using T = ReactivePower;
[JsonConverter(typeof(ReactivePowerConverter))]
public readonly partial struct ReactivePower public readonly partial struct ReactivePower
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Resistance; using T = Resistance;
[JsonConverter(typeof(ResistanceConverter))]
public readonly partial struct Resistance public readonly partial struct Resistance
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Temperature; using T = Temperature;
[JsonConverter(typeof(TemperatureConverter))]
public readonly partial struct Temperature public readonly partial struct Temperature
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -6,7 +6,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Utils\Utils.csproj" /> <ProjectReference Include="../Utils/Utils.csproj" />
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">

View File

@ -16,4 +16,5 @@ public readonly partial struct Voltage
// P=UI // P=UI
public static Power operator *(Voltage voltage, Current current) => new Power(current.Value * voltage.Value); public static Power operator *(Voltage voltage, Current current) => new Power(current.Value * voltage.Value);
} }

View File

@ -10,6 +10,7 @@ namespace InnovEnergy.Lib.Units;
using T = Voltage; using T = Voltage;
[JsonConverter(typeof(VoltageConverter))]
public readonly partial struct Voltage public readonly partial struct Voltage
{ {
public Decimal Value { get; } public Decimal Value { get; }

View File

@ -243,7 +243,7 @@ public static class EnumerableUtils
return ts.ElementAtOrDefault(index) ?? defaultValue; return ts.ElementAtOrDefault(index) ?? defaultValue;
} }
public static IEnumerable<T> Generate<T>(this T seed, Func<T, T> next) public static IEnumerable<T> Unfold<T>(this T seed, Func<T, T?> next)
{ {
var value = seed; var value = seed;
while (value is not null) while (value is not null)