Merge branch 'main' of https://git.innov.energy/Innovenergy/git_trunk
This commit is contained in:
commit
d90547ecdb
|
@ -156,11 +156,11 @@ public static class SessionMethods
|
||||||
.WithParent(sessionUser)
|
.WithParent(sessionUser)
|
||||||
.Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password))
|
.Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password))
|
||||||
.Do(() => newUser.MustResetPassword = true)
|
.Do(() => newUser.MustResetPassword = true)
|
||||||
.Apply(Db.Create)
|
.Apply(Db.Create);
|
||||||
&& Mailer.Mailer.SendVerificationMessage(newUser);
|
// && Mailer.Mailer.SendVerificationMessage(newUser);
|
||||||
|
|
||||||
//Send Email to new user to verify email and set password
|
//Send Email to new user to verify email and set password
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean Update(this Session? session, User? editedUser)
|
public static Boolean Update(this Session? session, User? editedUser)
|
||||||
|
|
|
@ -182,9 +182,9 @@ public static class UserMethods
|
||||||
{
|
{
|
||||||
return other?.Type switch
|
return other?.Type switch
|
||||||
{
|
{
|
||||||
"installation" => user.HasAccessTo(Db.GetInstallationById(other.ParentId)),
|
"Installation" => user.HasAccessTo(Db.GetFolderById(other.ParentId)),
|
||||||
"user" => user.HasAccessTo(Db.GetUserById(other.ParentId)),
|
"User" => user.HasAccessTo(Db.GetUserById(other.ParentId)),
|
||||||
"folder" => user.HasAccessTo(Db.GetFolderById(other.ParentId)),
|
"Folder" => user.HasAccessTo(Db.GetFolderById(other.ParentId)),
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,21 @@ public static partial class Db
|
||||||
|
|
||||||
private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath);
|
private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath);
|
||||||
|
|
||||||
public static TableQuery<Session> Sessions => Connection.Table<Session>();
|
public static TableQuery<Session> Sessions => Connection.Table<Session>();
|
||||||
public static TableQuery<Folder> Folders => Connection.Table<Folder>();
|
public static TableQuery<Folder> Folders => Connection.Table<Folder>();
|
||||||
public static TableQuery<DeletedFolder> DeletedFolders => Connection.Table<DeletedFolder>();
|
public static TableQuery<Installation> Installations => Connection.Table<Installation>();
|
||||||
public static TableQuery<Installation> Installations => Connection.Table<Installation>();
|
public static TableQuery<User> Users => Connection.Table<User>();
|
||||||
public static TableQuery<DeletedInstallation> DeletedInstallations => Connection.Table<DeletedInstallation>();
|
public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>();
|
||||||
public static TableQuery<User> Users => Connection.Table<User>();
|
public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>();
|
||||||
public static TableQuery<DeletedUser> DeletedUsers => Connection.Table<DeletedUser>();
|
public static TableQuery<OrderNumber2Installation> OrderNumber2Installation => Connection.Table<OrderNumber2Installation>();
|
||||||
public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>();
|
|
||||||
public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>();
|
public static TableQuery<DeletedInstallation> DeletedInstallations => Connection.Table<DeletedInstallation>();
|
||||||
public static TableQuery<OrderNumber2Installation> OrderNumber2Installation => Connection.Table<OrderNumber2Installation>();
|
public static TableQuery<DeletedUser> DeletedUsers => Connection.Table<DeletedUser>();
|
||||||
|
public static TableQuery<DeletedFolder> DeletedFolders => Connection.Table<DeletedFolder>();
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
// used to force static constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ public static partial class Db
|
||||||
Observable.Interval(TimeSpan.FromDays(0.5))
|
Observable.Interval(TimeSpan.FromDays(0.5))
|
||||||
.StartWith(0) // Do it right away (on startup)
|
.StartWith(0) // Do it right away (on startup)
|
||||||
.ObserveOn(TaskPoolScheduler.Default)
|
.ObserveOn(TaskPoolScheduler.Default)
|
||||||
|
.SubscribeOn(TaskPoolScheduler.Default)
|
||||||
.SelectMany(Cleanup)
|
.SelectMany(Cleanup)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
## create a new VRM access token
|
||||||
## USAGE: ./newToken.sh -u Username -p Password -n UniqueTokenName
|
## USAGE: ./newToken.sh -u Username -p Password -n UniqueTokenName
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,23 @@
|
||||||
<Import Project="../InnovEnergy.App.props" />
|
<Import Project="../InnovEnergy.App.props" />
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../../Lib/Devices/Adam6060/Adam6060.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/Adam6060/Adam6060.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/AMPT/Ampt.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/AMPT/Ampt.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/Battery48TL/Battery48TL.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/Battery48TL/Battery48TL.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/EmuMeter/EmuMeter.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/EmuMeter/EmuMeter.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvert/TruConvert.csproj"/>
|
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvert/TruConvert.csproj" />
|
||||||
<ProjectReference Include="../../Lib/StatusApi/StatusApi.csproj"/>
|
<ProjectReference Include="../../Lib/StatusApi/StatusApi.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Utils/Utils.csproj"/>
|
<ProjectReference Include="../../Lib/Utils/Utils.csproj" />
|
||||||
<ProjectReference Include="../../Lib/Time/Time.csproj"/>
|
<ProjectReference Include="../../Lib/Time/Time.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliWrap" Version="3.6.0"/>
|
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||||
<PackageReference Include="Flurl.Http" Version="3.2.4"/>
|
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="7.0.0"/>
|
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||||
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2"/>
|
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,51 +1,53 @@
|
||||||
using InnovEnergy.Lib.Devices.Battery48TL;
|
using InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
|
using InnovEnergy.Lib.StatusApi;
|
||||||
|
using InnovEnergy.Lib.Units;
|
||||||
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
using static InnovEnergy.Lib.Devices.Battery48TL.TemperatureState;
|
||||||
|
|
||||||
namespace InnovEnergy.App.SaliMax.Controller;
|
namespace InnovEnergy.App.SaliMax.Controller;
|
||||||
|
|
||||||
public class AvgBatteriesStatus
|
public static class AvgBatteriesStatus
|
||||||
{
|
{
|
||||||
public Decimal Soc { get; set; }
|
public static CombinedStatus<Battery48TLStatus>? Combine(this IReadOnlyList<Battery48TLStatus> stati)
|
||||||
public Decimal Current { get; set; }
|
|
||||||
public Decimal Voltage { get; set; }
|
|
||||||
public Decimal Power { get; set; }
|
|
||||||
public Decimal BusVoltage { get; set; }
|
|
||||||
public Decimal BatteryTemperature { get; set; }
|
|
||||||
public IReadOnlyList<String> Warnings { get; set; }
|
|
||||||
public IReadOnlyList<String> Alarms { get; set; }
|
|
||||||
public Boolean HeaterOn { get; set; }
|
|
||||||
public Boolean EocReached { get; set; }
|
|
||||||
public Boolean BatteryCold { get; set; }
|
|
||||||
public Decimal MaxChargingPower { get; set; }
|
|
||||||
public Decimal MaxDischargingPower { get; set; }
|
|
||||||
|
|
||||||
public static AvgBatteriesStatus ReadBatteriesStatus(IReadOnlyList<Battery48TLStatus> batteriesStatus)
|
|
||||||
{
|
{
|
||||||
var soc = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Soc) : 0;
|
var combined = stati.Count == 0
|
||||||
var current = batteriesStatus.Select(b => b.Dc.Current).Aggregate(0m,(a, b) => a + b);
|
? null
|
||||||
var voltage = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Dc.Voltage) : 0;
|
: new Battery48TLStatus
|
||||||
var power = batteriesStatus.Select(b => b.Dc.Power).Aggregate(0m,(a, b) => a + b);
|
|
||||||
var busVoltage = batteriesStatus.Any() ? batteriesStatus.Average(b => b.BusVoltage): 0;
|
|
||||||
var batteryTemperature = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Temperature): 0;
|
|
||||||
var heaterOn = batteriesStatus.Any() && batteriesStatus.Select(b => b.HeaterOn).Aggregate((a, b) => a | b);
|
|
||||||
var eocReached = batteriesStatus.All(b => b.EocReached);
|
|
||||||
var batteryCold = batteriesStatus.Any(b => b.BatteryCold);
|
|
||||||
var maxChargingPower = batteriesStatus.Select(b => b.MaxChargingPower).Aggregate(0m, (a, b) => a + b);
|
|
||||||
var maxDischargingPower = batteriesStatus.Select(b => b.MaxDischargingPower).Aggregate(0m, (a, b) => a + b);
|
|
||||||
|
|
||||||
|
|
||||||
return new AvgBatteriesStatus
|
|
||||||
{
|
{
|
||||||
Soc = soc,
|
Soc = stati.Min(b => b.Soc),
|
||||||
Current = current,
|
Temperature = stati.Average(b => b.Temperature),
|
||||||
Voltage = voltage,
|
Dc = new DcBus
|
||||||
Power = power,
|
{
|
||||||
BusVoltage = busVoltage,
|
Voltage = stati.Average(b => b.Dc.Voltage),
|
||||||
BatteryTemperature = batteryTemperature,
|
Current = stati.Sum(b => b.Dc.Current),
|
||||||
HeaterOn = heaterOn,
|
},
|
||||||
EocReached = eocReached,
|
|
||||||
BatteryCold = batteryCold,
|
Alarms = stati.SelectMany(b => b.Alarms).Distinct().ToList(),
|
||||||
MaxChargingPower = maxChargingPower,
|
Warnings = stati.SelectMany(b => b.Warnings).Distinct().ToList(),
|
||||||
MaxDischargingPower = maxDischargingPower
|
|
||||||
|
MaxChargingPower = stati.Sum(b => b.MaxChargingPower),
|
||||||
|
MaxDischargingPower = stati.Sum(b => b.MaxDischargingPower),
|
||||||
|
|
||||||
|
Heating = stati.Any(b => b.Heating),
|
||||||
|
|
||||||
|
AmberLed = LedState.Off, // not used for combined battery
|
||||||
|
BlueLed = LedState.Off,
|
||||||
|
RedLed = LedState.Off,
|
||||||
|
GreenLed = LedState.Off,
|
||||||
|
|
||||||
|
CellsVoltage = stati.Average(b => b.CellsVoltage),
|
||||||
|
ConnectedToDc = stati.Any(b => b.ConnectedToDc),
|
||||||
|
|
||||||
|
TemperatureState = stati.Any(b => b.TemperatureState == OperatingTemperature) // TODO: revisit when we have the overheated state
|
||||||
|
? OperatingTemperature
|
||||||
|
: Cold,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new CombinedStatus<Battery48TLStatus>
|
||||||
|
{
|
||||||
|
Combined = combined!,
|
||||||
|
Children = stati
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,18 +5,19 @@ using InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
using InnovEnergy.Lib.Devices.EmuMeter;
|
using InnovEnergy.Lib.Devices.EmuMeter;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||||
|
using InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
namespace InnovEnergy.App.SaliMax.Controller;
|
namespace InnovEnergy.App.SaliMax.Controller;
|
||||||
|
|
||||||
public record StatusRecord
|
public record StatusRecord
|
||||||
{
|
{
|
||||||
public TruConvertAcStatus? InverterStatus { get; init; }
|
public TruConvertAcStatus? InverterStatus { get; init; }
|
||||||
public TruConvertDcStatus? DcDcStatus { get; init; }
|
public TruConvertDcStatus? DcDcStatus { get; init; }
|
||||||
public Battery48TLStatus[]? BatteriesStatus { get; set; } = Array.Empty<Battery48TLStatus>(); // TODO remove static
|
public CombinedStatus<Battery48TLStatus>? BatteriesStatus { get; init; }
|
||||||
public AvgBatteriesStatus? AvgBatteriesStatus { get; init; }
|
|
||||||
public EmuMeterStatus? GridMeterStatus { get; init; }
|
public EmuMeterStatus? GridMeterStatus { get; init; }
|
||||||
public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
|
public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
|
||||||
public AmptStatus? AmptStatus { get; init; }
|
public AmptStatus? AmptStatus { get; init; }
|
||||||
public EmuMeterStatus? AcInToAcOutMeterStatus { get; init; }
|
public EmuMeterStatus? AcInToAcOutMeterStatus { get; init; }
|
||||||
public SalimaxConfig SalimaxConfig { get; init; } = null!;
|
public SalimaxConfig SalimaxConfig { get; init; } = null!;
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ using InnovEnergy.Lib.Devices.EmuMeter;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||||
using InnovEnergy.Lib.Time.Unix;
|
using InnovEnergy.Lib.Time.Unix;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
#pragma warning disable IL2026
|
#pragma warning disable IL2026
|
||||||
|
|
||||||
|
@ -41,14 +42,26 @@ internal static class Program
|
||||||
{
|
{
|
||||||
Console.WriteLine("Starting SaliMax");
|
Console.WriteLine("Starting SaliMax");
|
||||||
|
|
||||||
|
var batteryNodes = new Byte[] { 2, 3 };
|
||||||
|
|
||||||
|
var batteryTty = "/dev/ttyUSB0";
|
||||||
|
|
||||||
|
var relaysIp = "10.0.1.1";
|
||||||
|
var truConvertAcIp = "10.0.2.1";
|
||||||
|
var truConvertDcIp = "10.0.3.1";
|
||||||
|
var gridMeterIp = "10.0.4.1";
|
||||||
|
var internalMeter = "10.0.4.2";
|
||||||
|
var amptIp = "10.0.5.1";
|
||||||
|
|
||||||
|
|
||||||
var s3Config = new S3Config
|
var s3Config = new S3Config
|
||||||
{
|
{
|
||||||
Bucket = "saliomameiringen",
|
Bucket = "saliomameiringen",
|
||||||
Region = "sos-ch-dk-2",
|
Region = "sos-ch-dk-2",
|
||||||
Provider = "exo.io",
|
Provider = "exo.io",
|
||||||
ContentType = "text/plain; charset=utf-8",
|
ContentType = "text/plain; charset=utf-8",
|
||||||
Key = "EXO2bf0cbd97fbfa75aa36ed46f",
|
Key = "EXO2bf0cbd97fbfa75aa36ed46f",
|
||||||
Secret = "Bn1CDPqOG-XpDSbYjfIJxojcHTm391vZTc8z8l_fEPs"
|
Secret = "Bn1CDPqOG-XpDSbYjfIJxojcHTm391vZTc8z8l_fEPs"
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -62,48 +75,42 @@ internal static class Program
|
||||||
var firstBattery48TlDevice =Battery48TlDevice.Fake();;
|
var firstBattery48TlDevice =Battery48TlDevice.Fake();;
|
||||||
var salimaxConfig = new SalimaxConfig();
|
var salimaxConfig = new SalimaxConfig();
|
||||||
#else
|
#else
|
||||||
#if BatteriesAllowed
|
|
||||||
var firstBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 2);
|
var batteries = batteryNodes.Select(n => new Battery48TlDevice(batteryTty, n)).ToList();
|
||||||
var secondBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 3);
|
|
||||||
#endif
|
|
||||||
var inverterDevice = new TruConvertAcDevice("192.168.1.2");
|
var inverterDevice = new TruConvertAcDevice(truConvertAcIp);
|
||||||
var dcDcDevice = new TruConvertDcDevice("192.168.1.3");
|
var dcDcDevice = new TruConvertDcDevice(truConvertDcIp);
|
||||||
var gridMeterDevice = new EmuMeterDevice("192.168.1.241");
|
|
||||||
var acInToAcOutMeterDevice = new EmuMeterDevice("192.168.1.241"); // TODO: use real device
|
var gridMeterDevice = new EmuMeterDevice(gridMeterIp);
|
||||||
var amptDevice = new AmptCommunicationUnit("192.168.1.249");
|
var acInToAcOutMeterDevice = new EmuMeterDevice(internalMeter); // TODO: use real device
|
||||||
var saliMaxRelaysDevice = new SaliMaxRelaysDevice("192.168.1.242");
|
|
||||||
|
var amptDevice = new AmptCommunicationUnit(amptIp);
|
||||||
|
|
||||||
|
var saliMaxRelaysDevice = new SaliMaxRelaysDevice(relaysIp);
|
||||||
var salimaxConfig = new SalimaxConfig();
|
var salimaxConfig = new SalimaxConfig();
|
||||||
#endif
|
#endif
|
||||||
// This is will be always add manually ? or do we need to read devices automatically in a range of IP @
|
// This is will be always add manually ? or do we need to read devices automatically in a range of IP @
|
||||||
#if BatteriesAllowed
|
|
||||||
|
|
||||||
var battery48TlDevices = new[] { firstBattery48TlDevice, secondBattery48TlDevice };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var dcDcDevices = new[] { dcDcDevice };
|
|
||||||
var inverterDevices = new[] { inverterDevice};
|
|
||||||
|
|
||||||
StatusRecord ReadStatus()
|
StatusRecord ReadStatus()
|
||||||
{
|
{
|
||||||
#if BatteriesAllowed
|
var combinedBatteryStatus = batteries
|
||||||
|
.Select(b => b.ReadStatus())
|
||||||
var battery48TlStatusArray = battery48TlDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
.NotNull()
|
||||||
#endif
|
.ToList()
|
||||||
// var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
.Combine();
|
||||||
|
|
||||||
|
// var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||||
// var inverterStatusArray = inverterDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
// var inverterStatusArray = inverterDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||||
|
|
||||||
return new StatusRecord
|
return new StatusRecord
|
||||||
{
|
{
|
||||||
InverterStatus = inverterDevice.ReadStatus(),
|
InverterStatus = inverterDevice.ReadStatus(),
|
||||||
DcDcStatus = dcDcDevice.ReadStatus(),
|
DcDcStatus = dcDcDevice.ReadStatus(),
|
||||||
#if BatteriesAllowed
|
|
||||||
|
|
||||||
BatteriesStatus = battery48TlStatusArray,
|
BatteriesStatus = combinedBatteryStatus,
|
||||||
AvgBatteriesStatus = AvgBatteriesStatus.ReadBatteriesStatus(battery48TlStatusArray),
|
|
||||||
#else
|
|
||||||
BatteriesStatus = null,
|
|
||||||
AvgBatteriesStatus = null,
|
|
||||||
#endif
|
|
||||||
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
||||||
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
||||||
SaliMaxRelayStatus = saliMaxRelaysDevice.ReadStatus(),
|
SaliMaxRelayStatus = saliMaxRelaysDevice.ReadStatus(),
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
host=ie-entwicklung@10.2.3.115
|
||||||
|
|
||||||
|
tunnel() {
|
||||||
|
name=$1
|
||||||
|
ip=$2
|
||||||
|
rPort=$3
|
||||||
|
lPort=$4
|
||||||
|
|
||||||
|
echo -n "localhost:$lPort $name "
|
||||||
|
ssh -nNTL "$lPort:$ip:$rPort" "$host" 2> /dev/null &
|
||||||
|
|
||||||
|
until nc -vz 127.0.0.1 $lPort 2> /dev/null
|
||||||
|
do
|
||||||
|
echo -n .
|
||||||
|
sleep 0.3
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
tunnel "Trumpf Inverter (http) " 10.0.2.1 80 8001
|
||||||
|
tunnel "Trumpf DCDC (http) " 10.0.3.1 80 8002
|
||||||
|
tunnel "Ext Emu Meter (http) " 10.0.4.1 80 8003
|
||||||
|
tunnel "Int Emu Meter (http) " 10.0.4.2 80 8004
|
||||||
|
tunnel "AMPT (http) " 10.0.5.1 8080 8005
|
||||||
|
|
||||||
|
tunnel "Trumpf Inverter (modbus)" 10.0.2.1 502 5001
|
||||||
|
tunnel "Trumpf DCDC (modbus) " 10.0.3.1 502 5002
|
||||||
|
tunnel "Ext Emu Meter (modbus) " 10.0.4.1 502 5003
|
||||||
|
tunnel "Int Emu Meter " 10.0.4.2 502 5004
|
||||||
|
tunnel "AMPT (modbus) " 10.0.5.1 502 5005
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "press any key to close the tunnels ..."
|
||||||
|
read -r -n 1 -s
|
||||||
|
kill $(jobs -p)
|
||||||
|
echo "done"
|
|
@ -9,8 +9,12 @@
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<InvariantGlobalization>true</InvariantGlobalization>
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
||||||
<RootNamespace>$(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("src/", "").Replace("/",".").Replace("\","."))</RootNamespace>
|
<RootNamespace>Please.reload.the.project.Rider.is.stupid</RootNamespace>
|
||||||
<Authors>$(Company) Team</Authors>
|
<Authors>$(Company) Team</Authors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(SolutionDir)' != ''">
|
||||||
|
<RootNamespace>$(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("/",".").Replace("\","."))</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -60,20 +60,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "Lib/Channels/Ch
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "App/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "App/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Lib/Units/Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Lib\Units\Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemControl", "Lib/Devices/Trumpf/SystemControl/SystemControl.csproj", "{B816BB44-E97E-4E02-B80A-BEDB5B923A96}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C389-44C9-B2C0-ACB560189CF2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C389-44C9-B2C0-ACB560189CF2}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
InnovEnergy.props = InnovEnergy.props
|
InnovEnergy.props = InnovEnergy.props
|
||||||
App\InnovEnergy.App.props = App\InnovEnergy.App.props
|
App/InnovEnergy.App.props = App/InnovEnergy.App.props
|
||||||
Lib\InnovEnergy.Lib.props = Lib\InnovEnergy.Lib.props
|
Lib/InnovEnergy.Lib.props = Lib/InnovEnergy.Lib.props
|
||||||
InnovEnergy.sln.DotSettings = InnovEnergy.sln.DotSettings
|
InnovEnergy.sln.DotSettings = InnovEnergy.sln.DotSettings
|
||||||
..\.gitignore = ..\.gitignore
|
../.gitignore = ../.gitignore
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
|
||||||
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -180,6 +180,10 @@ Global
|
||||||
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{CF4834CB-91B7-4172-AC13-ECDA8613CD17} = {145597B4-3E30-45E6-9F72-4DD43194539A}
|
{CF4834CB-91B7-4172-AC13-ECDA8613CD17} = {145597B4-3E30-45E6-9F72-4DD43194539A}
|
||||||
|
@ -211,5 +215,6 @@ Global
|
||||||
{A56F58C2-B265-435B-A985-53B4D6F49B1A} = {145597B4-3E30-45E6-9F72-4DD43194539A}
|
{A56F58C2-B265-435B-A985-53B4D6F49B1A} = {145597B4-3E30-45E6-9F72-4DD43194539A}
|
||||||
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}
|
{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}
|
||||||
{4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}
|
{4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}
|
||||||
|
{B816BB44-E97E-4E02-B80A-BEDB5B923A96} = {DDDBEFD0-5DEA-4C7C-A9F2-FDB4636CF092}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=MPPT/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=MPPT/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mppts/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mppts/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=nanopi/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=nanopi/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=precharge/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=precharges/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prosumer/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prosumer/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prosumers/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prosumers/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=proxyport/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=proxyport/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
@ -38,6 +40,7 @@
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Trumpf/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Trumpf/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ttyusb/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=ttyusb/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tupled/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tupled/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unhashed/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=victronenergy/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=victronenergy/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|
||||||
</wpf:ResourceDictionary>
|
</wpf:ResourceDictionary>
|
|
@ -1,5 +1,6 @@
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||||
|
using static InnovEnergy.Lib.Devices.Battery48TL.Constants;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
|
|
||||||
|
@ -10,10 +11,10 @@ public class Battery48TlDevice
|
||||||
public Battery48TlDevice(String device, Byte nodeId)
|
public Battery48TlDevice(String device, Byte nodeId)
|
||||||
{
|
{
|
||||||
var serialConnection = new ModbusSerialConnection(device,
|
var serialConnection = new ModbusSerialConnection(device,
|
||||||
Constants.BaudRate,
|
BaudRate,
|
||||||
Constants.Parity,
|
Parity,
|
||||||
Constants.DataBits,
|
DataBits,
|
||||||
Constants.StopBits,
|
StopBits,
|
||||||
Constants.Timeout);
|
Constants.Timeout);
|
||||||
|
|
||||||
Modbus = new ModbusRtuClient(serialConnection, nodeId);
|
Modbus = new ModbusRtuClient(serialConnection, nodeId);
|
||||||
|
@ -34,7 +35,7 @@ public class Battery48TlDevice
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Modbus
|
return Modbus
|
||||||
.ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters)
|
.ReadInputRegisters(BaseAddress, NoOfRegisters)
|
||||||
.ParseBatteryStatus();
|
.ParseBatteryStatus();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using InnovEnergy.Lib.StatusApi;
|
using InnovEnergy.Lib.StatusApi;
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units;
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
|
|
||||||
|
@ -15,22 +14,17 @@ public record Battery48TLStatus : BatteryStatus
|
||||||
public Power MaxChargingPower { get; init; }
|
public Power MaxChargingPower { get; init; }
|
||||||
public Power MaxDischargingPower { get; init; }
|
public Power MaxDischargingPower { get; init; }
|
||||||
|
|
||||||
public State GreenLed { get; init; }
|
public LedState GreenLed { get; init; }
|
||||||
public State AmberLed { get; init; }
|
public LedState AmberLed { get; init; }
|
||||||
public State BlueLed { get; init; }
|
public LedState BlueLed { get; init; }
|
||||||
public State RedLed { get; init; }
|
public LedState RedLed { get; init; }
|
||||||
|
|
||||||
public State Warnings { get; init; }
|
|
||||||
public State Alarms { get; init; }
|
|
||||||
|
|
||||||
public State MainSwitchState { get; init; } // connected to bus | disconnected from bus
|
|
||||||
public State HeaterState { get; init; } // heating | not heating
|
|
||||||
public State EocState { get; init; } // EOC reached | EOC not reached
|
|
||||||
public State TemperatureState { get; init; } // cold | operating temperature | overheated
|
|
||||||
|
|
||||||
|
public IReadOnlyList<String> Warnings { get; init; } = Array.Empty<String>();
|
||||||
|
public IReadOnlyList<String> Alarms { get; init; } = Array.Empty<String>();
|
||||||
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
public Boolean ConnectedToDc { get; init; }
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
public Boolean Heating { get; init; }
|
||||||
|
public TemperatureState TemperatureState { get; init; } // cold | operating temperature | overheated
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public static class Constants
|
||||||
private const Decimal RStringMin = 0.125m;
|
private const Decimal RStringMin = 0.125m;
|
||||||
private const Decimal RStringMax = 0.250m;
|
private const Decimal RStringMax = 0.250m;
|
||||||
private const Decimal IMaxPerString = 20.0m;
|
private const Decimal IMaxPerString = 20.0m;
|
||||||
private const UInt16 NumberOfStrings = 5;
|
private const UInt16 NumberOfStrings = 5;
|
||||||
|
|
||||||
public const Decimal RIntMin = RStringMin / NumberOfStrings;
|
public const Decimal RIntMin = RStringMin / NumberOfStrings;
|
||||||
public const Decimal RIntMax = RStringMax / NumberOfStrings;
|
public const Decimal RIntMax = RStringMax / NumberOfStrings;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
||||||
using InnovEnergy.Lib.Units;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
|
using static InnovEnergy.Lib.Devices.Battery48TL.LedState;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
|
|
||||||
|
@ -10,24 +10,44 @@ public static class ModbusParser
|
||||||
{
|
{
|
||||||
internal static Battery48TLStatus ParseBatteryStatus(this ModbusRegisters data)
|
internal static Battery48TLStatus ParseBatteryStatus(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
|
var greenLed = data.ParseLedState(register: 1005, led: LedColor.Green);
|
||||||
|
var amberLed = data.ParseLedState(register: 1005, led: LedColor.Amber);
|
||||||
|
var blueLed = data.ParseLedState(register: 1005, led: LedColor.Blue);
|
||||||
|
var redLed = data.ParseLedState(register: 1005, led: LedColor.Red);
|
||||||
|
|
||||||
|
var soc = data.ParseSoc();
|
||||||
|
|
||||||
|
var eoc = greenLed is On
|
||||||
|
&& amberLed is Off
|
||||||
|
&& blueLed is Off;
|
||||||
|
|
||||||
|
var maxSoc = eoc ? 100m : 99.9m;
|
||||||
|
|
||||||
|
var batteryCold = greenLed >= BlinkingSlow
|
||||||
|
&& blueLed >= BlinkingSlow;
|
||||||
|
|
||||||
|
var temperatureState = batteryCold
|
||||||
|
? TemperatureState.Cold
|
||||||
|
: TemperatureState.OperatingTemperature; // TODO: overheated
|
||||||
|
|
||||||
|
|
||||||
return new Battery48TLStatus
|
return new Battery48TLStatus
|
||||||
{
|
{
|
||||||
Dc = data.ParseDcBus(),
|
Dc = data.ParseDcBus(),
|
||||||
Alarms = data.ParseAlarms().ToList(),
|
Alarms = data.ParseAlarms().ToList(),
|
||||||
Warnings = data.ParseWarnings().ToList(),
|
Warnings = data.ParseWarnings().ToList(),
|
||||||
Soc = data.ParseSoc(),
|
Soc = Math.Min(soc, maxSoc),
|
||||||
Temperature = data.ParseTemperature(),
|
Temperature = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400),
|
||||||
GreenLed = data.ParseGreenLed(),
|
GreenLed = greenLed,
|
||||||
AmberLed = data.ParseAmberLed(),
|
AmberLed = amberLed,
|
||||||
BlueLed = data.ParseBlueLed(),
|
BlueLed = blueLed,
|
||||||
RedLed = data.ParseRedLed(),
|
RedLed = redLed,
|
||||||
MainSwitchState = data.ParseMainSwitchState(),
|
Heating = data.ParseBool(baseRegister: 1014, bit: 6),
|
||||||
HeaterState = data.ParseHeaterState(),
|
ConnectedToDc = data.ParseBool(baseRegister: 1014, bit: 0),
|
||||||
EocState = data.ParseEocState(),
|
TemperatureState = temperatureState,
|
||||||
TemperatureState = data.ParseTemperatureState(),
|
|
||||||
MaxChargingPower = data.CalcMaxChargePower(),
|
MaxChargingPower = data.CalcMaxChargePower(),
|
||||||
MaxDischargingPower = data.CalcMaxDischargePower(),
|
MaxDischargingPower = data.CalcMaxDischargePower(),
|
||||||
CellsVoltage = data.ParseCellsVoltage(),
|
CellsVoltage = data.ParseDecimal(register: 1000, scaleFactor: 0.01m),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +67,6 @@ public static class ModbusParser
|
||||||
return data.ParseDecimal(register: 1001, scaleFactor: 0.01m, offset: -10000);
|
return data.ParseDecimal(register: 1001, scaleFactor: 0.01m, offset: -10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Decimal ParseCellsVoltage(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseDecimal(register: 1000, scaleFactor: 0.01m);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Decimal ParseBusVoltage(this ModbusRegisters data)
|
internal static Decimal ParseBusVoltage(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
return data.ParseDecimal(register: 1002, scaleFactor: 0.01m);
|
return data.ParseDecimal(register: 1002, scaleFactor: 0.01m);
|
||||||
|
@ -74,57 +89,19 @@ public static class ModbusParser
|
||||||
|
|
||||||
return (hi, lo) switch
|
return (hi, lo) switch
|
||||||
{
|
{
|
||||||
(false, false) => LedState.Off,
|
(false, false) => Off,
|
||||||
(false, true) => LedState.On,
|
(false, true) => On,
|
||||||
(true, false) => LedState.BlinkingSlow,
|
(true, false) => BlinkingSlow,
|
||||||
(true, true) => LedState.BlinkingFast,
|
(true, true) => BlinkingFast,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Boolean ParseEocReached(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return ParseLedState(data, 1005, LedColor.Green) == LedState.On &&
|
|
||||||
ParseLedState(data, 1005, LedColor.Amber) == LedState.Off &&
|
|
||||||
ParseLedState(data, 1005, LedColor.Blue) == LedState.Off;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static State ParseTemperatureState(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseBatteryCold() ? "cold" : "operating temperature"; // TODO: overheated,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Decimal ParseTemperature(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Decimal ParseSoc(this ModbusRegisters data)
|
internal static Decimal ParseSoc(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
return data.ParseDecimal(register: 1054, scaleFactor: 0.1m);
|
return data.ParseDecimal(register: 1054, scaleFactor: 0.1m);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static State ParseEocState(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseEocReached() ? "EOC reached" : "EOC not reached";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static State ParseHeaterState(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseBool(baseRegister: 1014, bit: 6) ? "heating" : "not heating";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static State ParseMainSwitchState(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return data.ParseBool(baseRegister: 1014, bit: 0) ? "connected to bus" : "disconnected from bus";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Boolean ParseBatteryCold(this ModbusRegisters data)
|
|
||||||
{
|
|
||||||
return ParseLedState(data, 1005, LedColor.Green) >= LedState.BlinkingSlow &&
|
|
||||||
ParseLedState(data, 1005, LedColor.Blue) >= LedState.BlinkingSlow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt)
|
private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt)
|
||||||
{
|
{
|
||||||
var dv = vLimit - v;
|
var dv = vLimit - v;
|
||||||
|
@ -161,11 +138,12 @@ public static class ModbusParser
|
||||||
|
|
||||||
internal static Decimal CalcMaxChargePower(this ModbusRegisters data)
|
internal static Decimal CalcMaxChargePower(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
var v = ParseCellsVoltage(data);
|
var v = data.ParseDecimal(register: 1000, scaleFactor: 0.01m);
|
||||||
var i = ParseCurrent(data);
|
var i = ParseCurrent(data);
|
||||||
|
|
||||||
var pLimits = new[]
|
var pLimits = new[]
|
||||||
{
|
{
|
||||||
|
// TODO: review
|
||||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin),
|
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin),
|
||||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax),
|
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax),
|
||||||
CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin),
|
CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin),
|
||||||
|
@ -177,23 +155,20 @@ public static class ModbusParser
|
||||||
return Math.Max(pLimit, 0);
|
return Math.Max(pLimit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static DcBus ParseDcBus(this ModbusRegisters data)
|
internal static DcBus ParseDcBus(this ModbusRegisters data) => new()
|
||||||
{
|
{
|
||||||
return new()
|
Current = data.ParseCurrent(),
|
||||||
{
|
Voltage = data.ParseBusVoltage(),
|
||||||
Current = data.ParseCurrent(),
|
};
|
||||||
Voltage = data.ParseBusVoltage(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Decimal CalcMaxDischargePower(this ModbusRegisters data)
|
internal static Decimal CalcMaxDischargePower(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
var v = ParseCellsVoltage(data);
|
var v = data.ParseDecimal(register: 1000, scaleFactor: 0.01m);
|
||||||
var i = ParseCurrent(data);
|
var i = ParseCurrent(data);
|
||||||
var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400);
|
|
||||||
|
|
||||||
var pLimits = new[]
|
var pLimits = new[]
|
||||||
{
|
{
|
||||||
|
// TODO: review
|
||||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin),
|
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin),
|
||||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax),
|
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax),
|
||||||
CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin),
|
CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin),
|
||||||
|
@ -207,12 +182,6 @@ public static class ModbusParser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal static LedState ParseGreenLed(this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Green);
|
|
||||||
internal static LedState ParseAmberLed(this ModbusRegisters data) => data.ParseLedState(register: 1006, led: LedColor.Amber);
|
|
||||||
internal static LedState ParseBlueLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Blue);
|
|
||||||
internal static LedState ParseRedLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Red);
|
|
||||||
|
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
||||||
internal static IEnumerable<String> ParseAlarms(this ModbusRegisters data)
|
internal static IEnumerable<String> ParseAlarms(this ModbusRegisters data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||||
|
|
||||||
|
public enum TemperatureState
|
||||||
|
{
|
||||||
|
Cold = 0,
|
||||||
|
OperatingTemperature = 1,
|
||||||
|
Overheated = 2,
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
|
public enum AlarmMessage
|
||||||
|
{
|
||||||
|
NoAlarm = 0,
|
||||||
|
BmsCommunicationTimeoutHasOccured = 40302, // BMS communication timeout has occured.
|
||||||
|
Rs485CommunicationAlarm = 40303, // RS-485 communication alarm.
|
||||||
|
SoftwareVersionsOfSystemControlAndModulesDoNotMatch1 = 40412, // Software versions of system control and module(s) do not match.
|
||||||
|
SoftwareVersionsOfSystemControlAndModulesDoNotMatch2 = 40413, // Software versions of system control and module(s) do not match.
|
||||||
|
SoftwareVersionsOfSystemControlAndModulesDoNotMatch3 = 40414, // Software versions of system control and module(s) do not match.
|
||||||
|
SoftwareVersionsOfSystemControlAndModulesDoNotMatch4 = 40415, // Software versions of system control and module(s) do not match.
|
||||||
|
SoftwareVersionsOfSystemControlAndModulesDoNotMatch5 = 40416, // Software versions of system control and module(s) do not match.
|
||||||
|
NoSlaveModuleWasFoundPleaseCheckRs485Connection = 40304, // No slave module was found, please check RS-485 connection(s).
|
||||||
|
NumberOfOrCombinationOfConnectedSlaveTypesNotSupported = 40305, // Number of or combination of connected slave types not supported.
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
public record ControlRecord
|
||||||
|
{
|
||||||
|
private static readonly TimeSpan DefaultCommunicationTimeOut = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// public UInt32 Date { get; init;}
|
||||||
|
// public UInt32 Time { get; init;}
|
||||||
|
// public UInt32 IpAddress { get; init;} //= 0x C0A80102;
|
||||||
|
// public UInt32 Subnet { get; init;} //= 0x FFFFFF00;
|
||||||
|
// public UInt32 Gateway { get; init;} //= 0x C0A80102;
|
||||||
|
// public Boolean ResetParamToDefault { get; init;} = false ; // Coil
|
||||||
|
// public TimeSpan CommunicationTimeout { get; init;} = DefaultCommunicationTimeOut;
|
||||||
|
// public Boolean FactoryResetParameters { get; init;} = false;
|
||||||
|
// public SystemConfig ConnectedSystemConfig { get; init;} = 0;
|
||||||
|
// public UInt16 UpdateSwTrigger { get; init;} = 0;
|
||||||
|
// public UInt16 AutomaticSwUpdate { get; init;} = 0;
|
||||||
|
// public UInt16 CustomerValuesSaveReset { get; init;} = 0;
|
||||||
|
// public UInt16 SerialNumberSystemControl { get; init;} = 0;
|
||||||
|
// public UInt16 SerialNumberAcDc { get; init;} = 0;
|
||||||
|
// public UInt16 IntegrationLevel { get; init;} = 0;
|
||||||
|
// public UInt16 IlBuildnumber { get; init;} = 0;
|
||||||
|
// public Boolean PowerStageEnable { get; init;} = true;
|
||||||
|
// public SymmetricAcOperationMode SetValueConfig { get; init;} = 0;
|
||||||
|
// public Boolean ResetsAlarmAndWarning { get; init;} = false;
|
||||||
|
// public PreChargeDcLinkConfig PreChargeDcLinkConfig { get; init;} = (PreChargeDcLinkConfig)0;
|
||||||
|
// public PowerFactorConvention PowerFactorConvention { get; init;} = 0; //0 = producer
|
||||||
|
// public UInt16 SlaveAddress { get; init;} = Slave.Broadcast;
|
||||||
|
// public ErrorPolicy ErrorHandlingPolicy { get; init;} = 0;
|
||||||
|
// public AcDcGridType GridType { get; init;} = 0;
|
||||||
|
// public UInt16 SubSlaveAddress { get; init;} = 0;
|
||||||
|
// public Boolean UseModbusSlaveIdForAddressing { get; init;} = false;
|
||||||
|
// public UInt16 SubSlaveErrorPolicy { get; init;} = 0; // must be an enum
|
||||||
|
// public Decimal SignedPowerNominalValue { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal SignedPowerSetValueL1 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal SignedPowerSetValueL2 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal SignedPowerSetValueL3 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal PowerSetValue { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal PowerSetValueL1 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal PowerSetValueL2 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal PowerSetValueL3 { get; init;} = 0; // resolution 0.001 and Unit kva,
|
||||||
|
// public Decimal MaximumGridCurrentRmsL1 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Decimal MaximumGridCurrentRmsL2 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Decimal MaximumGridCurrentRmsL3 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Decimal CosPhiSetValueL1 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Decimal CosPhiSetValueL2 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Decimal CosPhiSetValueL3 { get; init;} = 0; // resolution : 0.01
|
||||||
|
// public Boolean PhaseL1IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive
|
||||||
|
// public Boolean PhaseL2IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive
|
||||||
|
// public Boolean PhaseL3IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive
|
||||||
|
// public Boolean PhasesAreCapacitive { get; init;} = true; // True = Capacitive, false = Inductive
|
||||||
|
// public Double SetPointCosPhi { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Double SetPointSinPhi { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Double SetPointSinPhiL1 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Double SetPointSinPhiL2 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Double SetPointSinPhiL3 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Decimal FrequencyOffsetIm { get; init;} = 0; // resolution 0.01
|
||||||
|
// public UInt16 VoltageAdjustmentFactorIm { get; init;} = 0;
|
||||||
|
// public UInt16 PreChargeDcLinkVoltage { get; init;} = 0;
|
||||||
|
// public Decimal MaxPeakCurrentVoltageControlL1 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Decimal MaxPeakCurrentVoltageControlL2 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public Decimal MaxPeakCurrentVoltageControlL3 { get; init;} = 0; // resolution 0.01
|
||||||
|
// public UInt16 GridFormingMode { get; init;} = 1; // 0 = not grid-forming (grid-tied) ,1 = grid-forming
|
||||||
|
// public UInt16 DcLinkRefVoltage { get; init;} = 800;
|
||||||
|
// public UInt16 DcLinkMinVoltage { get; init;} = 780;
|
||||||
|
// public UInt16 DcLinkMaxVoltage { get; init;} = 820;
|
||||||
|
// public UInt16 DcVoltageRefUs { get; init;} = 900;
|
||||||
|
// public UInt16 DcMinVoltageUs { get; init;} = 880;
|
||||||
|
// public UInt16 DcMaxVoltageUs { get; init;} = 920;
|
||||||
|
// // Need to discuss this with Ivo
|
||||||
|
// // public UInt16 FrequencySlopeIslandMode { get; init;} = 200; // resolution 0.01
|
||||||
|
// // public UInt16 VoltageSlopeIslandMode { get; init;} = 500; // resolution 0.01
|
||||||
|
// public UInt16 AcDcGcBypassMode { get; init;} = 0;
|
||||||
|
// public UInt16 AcDcGcPMaxThresholdPercent { get; init;} = 0; // resolution 0.01
|
||||||
|
// public UInt16 AcDcGcStartupRampEnable { get; init;} = 0;
|
||||||
|
// public DcStageConfiguration DcConfigModule { get; init;} = 0; // this must be an enum
|
||||||
|
// public UInt16 DcDcPowerDistribution { get; init;} = 0; // 0.1 resolution
|
||||||
|
// public AcDcDistributionMode AcDcDistributionMode { get; init;} = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
public enum ErrorPolicy : UInt16
|
||||||
|
{
|
||||||
|
Relaxed = 0, // 0 = relaxed (System keeps running even if some slaves are in error state.)
|
||||||
|
Strict = 1, // 1 = strict (System shuts down as soon as one component is in error state.)
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
using AlarmMessages = IReadOnlyList<AlarmMessage>;
|
||||||
|
using WarningMessages = IReadOnlyList<WarningMessage>;
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
|
|
||||||
|
public record StatusRecord
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// public MainState MainState { get; init; }
|
||||||
|
// public String SerialNumber { get; init; }
|
||||||
|
// public AcDcGridType GridType { get; init; }
|
||||||
|
// public WarningMessages Warnings { get; init; }
|
||||||
|
// public AlarmMessages Alarms { get; init; }
|
||||||
|
// public Decimal NumberOfConnectedSlaves { get; init; }
|
||||||
|
// public Decimal NumberOfConnectedSubSlaves { get; init; }
|
||||||
|
// public Frequency AcDcNominalGridFrequency { get; init; }
|
||||||
|
// public Voltage AcDcNominalGridVoltage { get; init; }
|
||||||
|
// public Power AcDcActNominalPower { get; init; }
|
||||||
|
// public Decimal AcDcPowerLimitingStatusAct { get; init; } // TODO: enum
|
||||||
|
// public Voltage AcDcDcVoltageReference { get; init; }
|
||||||
|
// public Voltage AcDcDcLinkVoltageMinAct { get; init; }
|
||||||
|
// public Voltage AcDcDcLinkVoltageMaxAct { get; init; }
|
||||||
|
// public Voltage AcDcDcLinkChargedMinVoltage { get; init; }
|
||||||
|
// public Decimal AcDcStmActCustomer { get; init; }
|
||||||
|
// public Decimal AcDcOverloadIntegratorStatusL1 { get; init; }
|
||||||
|
// public Decimal AcDcOverloadIntegratorStatusL2 { get; init; }
|
||||||
|
// public Decimal AcDcOverloadIntegratorStatusL3 { get; init; }
|
||||||
|
// public Power AcSignedPowerValue { get; init; }
|
||||||
|
// public Voltage ActualDcLinkVoltageUpperHalf { get; init; }
|
||||||
|
// public Voltage ActualDcLinkVoltageLowerHalf { get; init; }
|
||||||
|
// public Voltage ActualDcLinkVoltageUpperHalfExt { get; init; }
|
||||||
|
// public Voltage ActualDcLinkVoltageLowerHalfExt { get; init; }
|
||||||
|
// public Voltage VoltageIntNtoPe { get; init; }
|
||||||
|
// public Voltage VoltageExtNtoPe { get; init; }
|
||||||
|
// public Temperature InletAirTemperature { get; init; }
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
public enum SubSlavesErrorPolicy : UInt16
|
||||||
|
{
|
||||||
|
Strict = 0, // (AC-DC module switches to error state if at least one submodules is in error state
|
||||||
|
Relaxed = 1, // (AC-DC module switches to error state if all submodules are in error state.)
|
||||||
|
Off = 2, // (If possible AC-DC module continues operation even if all submodules are in error state.
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="../../../InnovEnergy.Lib.props" />
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\Protocols\Modbus\Modbus.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,324 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.SystemControlRegisters;
|
||||||
|
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||||
|
public class SystemControlDevice
|
||||||
|
{
|
||||||
|
private ModbusTcpClient ModbusTcpClient { get; }
|
||||||
|
|
||||||
|
public SystemControlDevice(String hostname, UInt16 port = ModbusTcpClient.DefaultPort, Byte slaveAddress = 0)
|
||||||
|
{
|
||||||
|
var connection = new ModbusTcpConnection(hostname, port);
|
||||||
|
ModbusTcpClient = new ModbusTcpClient(connection, slaveAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteControl(ControlRecord c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
WriteRegs(AcControlRegisters.Date, new List<UInt16> { c.Date.ConvertTo<UInt16>()});
|
||||||
|
WriteRegs(AcControlRegisters.Time, new List<UInt16> { c.Time.ConvertTo<UInt16>()});
|
||||||
|
WriteRegs(AcControlRegisters.IpAddress, new List<UInt16> { c.IpAddress.ConvertTo<UInt16>()});
|
||||||
|
WriteRegs(AcControlRegisters.Subnet, new List<UInt16> { c.Subnet.ConvertTo<UInt16>()});
|
||||||
|
WriteRegs(AcControlRegisters.Gateway, new List<UInt16> { c.Gateway.ConvertTo<UInt16>()});
|
||||||
|
WriteCoils(AcControlRegisters.ResetParamToDefault, c.ResetParamToDefault);
|
||||||
|
WriteCoils(AcControlRegisters.FactoryResetParameters, c.FactoryResetParameters);
|
||||||
|
ModbusTcpClient.WriteRegisters(AcControlRegisters.UpdateSwTrigger, c.UpdateSwTrigger, c.AutomaticSwUpdate, c.CustomerValuesSaveReset);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
WriteRegs(CommunicationTimeout, c.CommunicationTimeout.TotalSeconds.ConvertTo<UInt16>());
|
||||||
|
|
||||||
|
WriteRegs(ConnectedSystemConfig, c.ConnectedSystemConfig);
|
||||||
|
|
||||||
|
|
||||||
|
WriteCoils(PowerStageConfig, c.PowerStageEnable,
|
||||||
|
c.SetValueConfig.ConvertTo<Boolean>(),
|
||||||
|
c.ResetsAlarmAndWarning);
|
||||||
|
WriteRegs(PreChargeDcLinkConfigR, c.PreChargeDcLinkConfig,
|
||||||
|
c.PowerFactorConvention, c.SlaveAddress,
|
||||||
|
c.ErrorHandlingPolicy,
|
||||||
|
c.GridType, c.SubSlaveAddress);
|
||||||
|
WriteCoils(ModbusSlaveId, c.UseModbusSlaveIdForAddressing);
|
||||||
|
WriteRegs(SubSlaveErrorPolicy, c.SubSlaveErrorPolicy);
|
||||||
|
|
||||||
|
WriteRegs(SignedPowerNominalValue, -1.0m, c.SignedPowerNominalValue);/*, c.SignedPowerSetValueL1,
|
||||||
|
c.SignedPowerSetValueL2, c.SignedPowerSetValueL3,
|
||||||
|
c.PowerSetValue, c.PowerSetValueL1,
|
||||||
|
c.PowerSetValueL2, c.PowerSetValuesL3);*/
|
||||||
|
|
||||||
|
|
||||||
|
WriteRegs(MaximumGridCurrentRmsL1, 0.01m, c.MaximumGridCurrentRmsL1, c.MaximumGridCurrentRmsL2,
|
||||||
|
c.MaximumGridCurrentRmsL3, c.CosPhiSetValueL1,
|
||||||
|
c.CosPhiSetValueL2, c.CosPhiSetValueL3);
|
||||||
|
|
||||||
|
WriteCoils(PhaseL1IsCapacitive, c.PhaseL1IsCapacitive,
|
||||||
|
c.PhaseL2IsCapacitive,
|
||||||
|
c.PhaseL3IsCapacitive,
|
||||||
|
c.PhasesAreCapacitive);
|
||||||
|
|
||||||
|
/* WriteRegs(SetPointCosPhi, 0.01m, c.SetPointCosPhi.ConvertTo<UInt16>(),
|
||||||
|
c.SetPointSinPhi.ConvertTo<UInt16>(),
|
||||||
|
c.SetPointSinPhiL1.ConvertTo<UInt16>(),
|
||||||
|
c.SetPointSinPhiL2.ConvertTo<UInt16>(),
|
||||||
|
c.SetPointSinPhiL3.ConvertTo<UInt16>(),
|
||||||
|
c.FrequencyOffsetIm);*/
|
||||||
|
|
||||||
|
WriteRegs(VoltageAdjustmentFactorIm, c.VoltageAdjustmentFactorIm);
|
||||||
|
WriteRegs(PreChargeDcLinkVoltage, c.PreChargeDcLinkVoltage);
|
||||||
|
WriteRegs(MaxPeakCurrentVoltageControlL1, 0.01m, c.MaxPeakCurrentVoltageControlL1,
|
||||||
|
c.MaxPeakCurrentVoltageControlL2,
|
||||||
|
c.MaxPeakCurrentVoltageControlL3);
|
||||||
|
WriteRegs(GridFormingMode, c.GridFormingMode, c.DcLinkRefVoltage,
|
||||||
|
c.DcLinkMinVoltage, c.DcLinkMaxVoltage,
|
||||||
|
c.DcVoltageRefUs, c.DcMinVoltageUs, c.DcMaxVoltageUs);
|
||||||
|
WriteRegs(AcDcGcBypassMode, c.AcDcGcBypassMode);
|
||||||
|
WriteRegs(AcDcGcPMaxThresholdPercent, 0.01m, c.AcDcGcPMaxThresholdPercent);
|
||||||
|
WriteRegs(AcDcGcStartupRampEnable, c.AcDcGcStartupRampEnable);
|
||||||
|
WriteRegs(DcConfigModule, c.DcConfigModule);
|
||||||
|
WriteRegs(DcDcPowerDistribution, 0.1m, c.DcDcPowerDistribution);
|
||||||
|
WriteRegs(SystemControlRegisters.AcDcDistributionMode, c.AcDcDistributionMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteRegs (UInt16 a, Decimal res = 1.0m, params Decimal[] regs) => ModbusTcpClient.WriteRegisters(a, regs.ToUInt16(res));
|
||||||
|
private void WriteRegs (UInt16 a, params IConvertible[] regs) => ModbusTcpClient.WriteRegisters(a, regs.Select(v => v.ConvertTo<UInt16>()).ToArray());
|
||||||
|
private void WriteRegs (UInt16 a, params UInt16[] regs) => ModbusTcpClient.WriteRegisters(a, regs);
|
||||||
|
private void WriteCoils(UInt16 a, params Boolean[] coils) => ModbusTcpClient.WriteMultipleCoils(a, coils);
|
||||||
|
|
||||||
|
private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos);
|
||||||
|
|
||||||
|
public StatusRecord? ReadStatus()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return TryReadStatus();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ModbusTcpClient.CloseConnection();
|
||||||
|
Console.WriteLine("Failed to read inverter status");
|
||||||
|
e.Message.WriteLine();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusRecord TryReadStatus()
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Reading Ac Device");
|
||||||
|
|
||||||
|
var acSerialNumber = ModbusTcpClient.ReadInputRegisters(2009, 2);
|
||||||
|
var acActualMain = ModbusTcpClient.ReadInputRegisters(5001, 3);
|
||||||
|
var acActualAcDc = ModbusTcpClient.ReadInputRegisters(5021, 9);
|
||||||
|
var acActualAcDc2 = ModbusTcpClient.ReadInputRegisters(5031, 1);
|
||||||
|
var acActualAcDc3 = ModbusTcpClient.ReadInputRegisters(5131, 6);
|
||||||
|
var acActualMeasurement = ModbusTcpClient.ReadInputRegisters(5141, 3);
|
||||||
|
var acActualMeasurement1 = ModbusTcpClient.ReadInputRegisters(5151, 3);
|
||||||
|
var acActualMeasurement2 = ModbusTcpClient.ReadInputRegisters(5161, 3);
|
||||||
|
var acActualMeasurement3 = ModbusTcpClient.ReadInputRegisters(5171, 3);
|
||||||
|
var acActualMeasurement4 = ModbusTcpClient.ReadInputRegisters(5187, 2);
|
||||||
|
var acActualMeasurement5 = ModbusTcpClient.ReadInputRegisters(5189, 2);
|
||||||
|
var acActualMeasurement6 = ModbusTcpClient.ReadInputRegisters(5191, 2);
|
||||||
|
var acActualMeasurement7 = ModbusTcpClient.ReadInputRegisters(5201, 1);
|
||||||
|
var acActualMeasurement8 = ModbusTcpClient.ReadInputRegisters(5211, 4);
|
||||||
|
var acActualMeasurement9 = ModbusTcpClient.ReadInputRegisters(5221, 2);
|
||||||
|
var acActualTemp = ModbusTcpClient.ReadInputRegisters(5501, 1);
|
||||||
|
var acWarningValues = ModbusTcpClient.ReadInputRegisters(2402, 22);
|
||||||
|
var acAlarmValues = ModbusTcpClient.ReadInputRegisters(2809, 22);
|
||||||
|
var acSetValues = ModbusTcpClient.ReadInputRegisters(4196, 1);
|
||||||
|
|
||||||
|
var warnings = Enumerable
|
||||||
|
.Range(2404, 20)
|
||||||
|
.Select(n => acWarningValues.GetUInt16((UInt16)n).ConvertTo<WarningMessage>())
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var alarms = Enumerable
|
||||||
|
.Range(2811, 20)
|
||||||
|
.Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo<AlarmMessage>())
|
||||||
|
.Where(m => m != AlarmMessage.NoAlarm)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
var dcPower = acActualMeasurement.GetInt16(5141) * 1m + acActualMeasurement.GetInt16(5142) * 1m + acActualMeasurement.GetInt16(5143) * 1m;
|
||||||
|
var dcVoltage = acActualMeasurement8.GetUInt16(5214) + acActualMeasurement8.GetUInt16(5213);
|
||||||
|
var dcCurrent = dcVoltage != 0m
|
||||||
|
? dcPower / dcVoltage
|
||||||
|
: 0m;
|
||||||
|
|
||||||
|
|
||||||
|
// //acActualMeasurement
|
||||||
|
// PowerAcL1 = acActualMeasurement.GetInt16(5141) * 1m, // in Watt
|
||||||
|
// PowerAcL2 = acActualMeasurement.GetInt16(5142) * 1m, // in Watt
|
||||||
|
// PowerAcL3 = acActualMeasurement.GetInt16(5143) * 1m, // in Watt
|
||||||
|
//
|
||||||
|
//acActualMeasurement1
|
||||||
|
// PhaseCurrentL1 = acActualMeasurement1.GetUInt16(5151) * 0.01m,
|
||||||
|
// PhaseCurrentL2 = acActualMeasurement1.GetUInt16(5152) * 0.01m,
|
||||||
|
// PhaseCurrentL3 = acActualMeasurement1.GetUInt16(5153) * 0.01m,
|
||||||
|
|
||||||
|
//acActualMeasurement2
|
||||||
|
// GridVoltageL1 = acActualMeasurement2.GetUInt16(5161) * 0.1m,
|
||||||
|
// GridVoltageL2 = acActualMeasurement2.GetUInt16(5162) * 0.1m,
|
||||||
|
// GridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m,
|
||||||
|
|
||||||
|
//acActualMeasurement3
|
||||||
|
// CosPhiL1 = acActualMeasurement3.GetInt16(5171) * 0.01m,
|
||||||
|
// CosPhiL2 = acActualMeasurement3.GetInt16(5172) * 0.01m,
|
||||||
|
// CosPhiL3 = acActualMeasurement3.GetInt16(5173) * 0.01m,
|
||||||
|
|
||||||
|
// //acActualMeasurement4
|
||||||
|
// SumPowerL1 = acActualMeasurement4.GetUInt32(5187) * 1m, // in Watt
|
||||||
|
// //acActualMeasurement5
|
||||||
|
// SumPowerL2 = acActualMeasurement5.GetUInt32(5189) * 1m, // in Watt
|
||||||
|
// //acActualMeasurement6
|
||||||
|
// SumPowerL3 = acActualMeasurement6.GetUInt32(5191) * 1m, // in Watt
|
||||||
|
// //acActualMeasurement9
|
||||||
|
// GridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m,
|
||||||
|
|
||||||
|
//acActualMeasurement11
|
||||||
|
// VoltageIntNtoPE = acActualMeasurement9.GetInt16(5221) * 0.1m,
|
||||||
|
// VoltageExtNtoPE = acActualMeasurement9.GetInt16(5222) * 0.1m,
|
||||||
|
|
||||||
|
//
|
||||||
|
// ApparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m, // in VA
|
||||||
|
// ApparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m, // in VA
|
||||||
|
// ApparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m, // in VA
|
||||||
|
|
||||||
|
var apparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m;
|
||||||
|
var apparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m;
|
||||||
|
var apparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m;
|
||||||
|
|
||||||
|
var powerAcL1 = acActualMeasurement.GetInt16(5141) * 1m; // in Watt
|
||||||
|
var powerAcL2 = acActualMeasurement.GetInt16(5142) * 1m; // in Watt
|
||||||
|
var powerAcL3 = acActualMeasurement.GetInt16(5143) * 1m; // in Watt
|
||||||
|
|
||||||
|
var phaseCurrentL1 = acActualMeasurement1.GetUInt16(5151) * 0.01m;
|
||||||
|
var phaseCurrentL2 = acActualMeasurement1.GetUInt16(5152) * 0.01m;
|
||||||
|
var phaseCurrentL3 = acActualMeasurement1.GetUInt16(5153) * 0.01m;
|
||||||
|
|
||||||
|
var gridVoltageL1 = acActualMeasurement2.GetUInt16(5161) * 0.1m;
|
||||||
|
var gridVoltageL2 = acActualMeasurement2.GetUInt16(5162) * 0.1m;
|
||||||
|
var gridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m;
|
||||||
|
|
||||||
|
var gridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m;
|
||||||
|
|
||||||
|
return new StatusRecord
|
||||||
|
{
|
||||||
|
Ac = new Ac3Bus
|
||||||
|
{
|
||||||
|
Frequency = gridFrequency,
|
||||||
|
|
||||||
|
L1 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL1,
|
||||||
|
Current = phaseCurrentL1,
|
||||||
|
Phi = ACos(powerAcL1 / apparentPowerAcL1), // TODO: 2pi
|
||||||
|
},
|
||||||
|
L2 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL2,
|
||||||
|
Current = phaseCurrentL2,
|
||||||
|
Phi = ACos(powerAcL2 / apparentPowerAcL2), // TODO: 2pi
|
||||||
|
},
|
||||||
|
L3 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL3,
|
||||||
|
Current = phaseCurrentL3,
|
||||||
|
Phi = ACos(powerAcL3 / apparentPowerAcL3), // TODO: 2pi
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Dc = new DcBus
|
||||||
|
{
|
||||||
|
Current = dcCurrent,
|
||||||
|
Voltage = dcVoltage,
|
||||||
|
},
|
||||||
|
|
||||||
|
MainState = acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
||||||
|
Alarms = alarms,
|
||||||
|
Warnings = warnings,
|
||||||
|
GridType = acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
||||||
|
SerialNumber = acSerialNumber.GetInt32(2009).ToString(), // TODO: why tostring ?
|
||||||
|
NumberOfConnectedSlaves = acActualMain.GetUInt16(5002),
|
||||||
|
NumberOfConnectedSubSlaves = acActualMain.GetUInt16(5003),
|
||||||
|
AcDcNominalGridFrequency = acActualAcDc.GetUInt16(5021) * 0.1m,
|
||||||
|
AcDcNominalGridVoltage = acActualAcDc.GetUInt16(5022),
|
||||||
|
AcDcActNominalPower = acActualAcDc.GetUInt16(5023),
|
||||||
|
AcDcPowerLimitingStatusAct = acActualAcDc.GetUInt16(5025),
|
||||||
|
AcDcDcVoltageReference = acActualAcDc.GetUInt16(5026), // DC link reference
|
||||||
|
AcDcDcLinkVoltageMinAct = acActualAcDc.GetUInt16(5027), // DC link min voltage
|
||||||
|
AcDcDcLinkVoltageMaxAct = acActualAcDc.GetUInt16(5028), // DC link max voltage
|
||||||
|
AcDcDcLinkChargedMinVoltage = acActualAcDc.GetUInt16(5029) * 0.01m,
|
||||||
|
AcDcStmActCustomer = acActualAcDc2.GetUInt16(5031), //need to check
|
||||||
|
AcDcOverloadIntegratorStatusL1 = acActualAcDc3.GetUInt16(5134) * 0.1m,
|
||||||
|
AcDcOverloadIntegratorStatusL2 = acActualAcDc3.GetUInt16(5135) * 0.1m,
|
||||||
|
AcDcOverloadIntegratorStatusL3 = acActualAcDc3.GetUInt16(5136) * 0.1m,
|
||||||
|
AcSignedPowerValue = acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
||||||
|
ActualDcLinkVoltageUpperHalf = acActualMeasurement8.GetUInt16(5211),
|
||||||
|
ActualDcLinkVoltageLowerHalf = acActualMeasurement8.GetUInt16(5212),
|
||||||
|
ActualDcLinkVoltageUpperHalfExt = acActualMeasurement8.GetUInt16(5213),
|
||||||
|
ActualDcLinkVoltageLowerHalfExt = acActualMeasurement8.GetUInt16(5214),
|
||||||
|
VoltageIntNtoPe = acActualMeasurement9.GetInt16(5221) * 0.1m,
|
||||||
|
VoltageExtNtoPe = acActualMeasurement9.GetInt16(5222) * 0.1m,
|
||||||
|
InletAirTemperature = acActualTemp.GetInt16(5501) * 0.1m,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// (
|
||||||
|
// Ac: new Ac3Bus
|
||||||
|
// (
|
||||||
|
// new AcPhase(gridVoltageL1,phaseCurrentL1, ACos(powerAcL1/apparentPowerAcL1)),
|
||||||
|
// new AcPhase(gridVoltageL2,phaseCurrentL2, ACos(powerAcL2/apparentPowerAcL2)),
|
||||||
|
// new AcPhase(gridVoltageL3,phaseCurrentL3, ACos(powerAcL3/apparentPowerAcL3)),
|
||||||
|
// gridFrequency // Gird Frequency
|
||||||
|
// ),
|
||||||
|
// Dc: new DcConnection(dcVoltage, dcCurrent),
|
||||||
|
//
|
||||||
|
// SerialNumber : acSerialNumber.GetInt32(2009).ToString(),
|
||||||
|
//
|
||||||
|
// // acActualMainValues
|
||||||
|
// MainState : acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
||||||
|
// NumberOfConnectedSlaves : acActualMain.GetUInt16(5002),
|
||||||
|
// NumberOfConnectedSubSlaves : acActualMain.GetUInt16(5003),
|
||||||
|
//
|
||||||
|
// //acActualAcDc
|
||||||
|
// AcDcNominalGridFrequency : acActualAcDc.GetUInt16(5021) * 0.1m,
|
||||||
|
// AcDcNominalGridVoltage : acActualAcDc.GetUInt16(5022),
|
||||||
|
// AcDcActNominalPower : acActualAcDc.GetUInt16(5023),
|
||||||
|
// AcDcActiveGridType : acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
||||||
|
// AcDcPowerLimitingStatusAct : acActualAcDc.GetUInt16(5025),
|
||||||
|
// AcDcDcVoltageReference : acActualAcDc.GetUInt16(5026), // DC link reference
|
||||||
|
// AcDcDcLinkVoltageMinAct : acActualAcDc.GetUInt16(5027), // DC link min voltage
|
||||||
|
// AcDcDcLinkVoltageMaxAct : acActualAcDc.GetUInt16(5028), // DC link max voltage
|
||||||
|
// AcDcDcLinkChargedMinVoltage : acActualAcDc.GetUInt16(5029) * 0.01m,
|
||||||
|
//
|
||||||
|
// //ac Actual AcDc 2
|
||||||
|
// AcDcStmActCustomer : acActualAcDc2.GetUInt16(5031), //need to check
|
||||||
|
// AcDcOverloadIntegratorStatusL1 : acActualAcDc3.GetUInt16(5134) * 0.1m,
|
||||||
|
// AcDcOverloadIntegratorStatusL2 : acActualAcDc3.GetUInt16(5135) * 0.1m,
|
||||||
|
// AcDcOverloadIntegratorStatusL3 : acActualAcDc3.GetUInt16(5136) * 0.1m,
|
||||||
|
// AcSignedPowerValue : acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
||||||
|
//
|
||||||
|
// //acActualMeasurement10
|
||||||
|
// ActualDcLinkVoltageUpperHalf : acActualMeasurement8.GetUInt16(5211),
|
||||||
|
// ActualDcLinkVoltageLowerHalf : acActualMeasurement8.GetUInt16(5212),
|
||||||
|
// ActualDcLinkVoltageUpperHalfExt : acActualMeasurement8.GetUInt16(5213),
|
||||||
|
// ActualDcLinkVoltageLowerHalfExt : acActualMeasurement8.GetUInt16(5214),
|
||||||
|
//
|
||||||
|
// VoltageIntNtoPe : acActualMeasurement9.GetInt16(5221) * 0.1m,
|
||||||
|
// VoltageExtNtoPe : acActualMeasurement9.GetInt16(5222) * 0.1m,
|
||||||
|
// //acActualTemp
|
||||||
|
// InletAirTemperature : acActualTemp.GetInt16(5501) * 0.1m,
|
||||||
|
//
|
||||||
|
// Warnings : warnings,
|
||||||
|
// Alarms : alarms
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||||
|
|
||||||
|
public static class SystemControlRegisters
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// public const UInt16 Date = 1001;
|
||||||
|
// public const UInt16 Time = 1003;
|
||||||
|
// public const UInt16 IpAddress = 1005;
|
||||||
|
// public const UInt16 Subnet = 1007;
|
||||||
|
// public const UInt16 Gateway = 1009;
|
||||||
|
// public const UInt16 ResetParamToDefault = 1011;
|
||||||
|
// public const UInt16 CommunicationTimeout = 1017;
|
||||||
|
// public const UInt16 RestartFlag = 1018;
|
||||||
|
// public const UInt16 ConnectedSystemConfig = 1019;
|
||||||
|
// public const UInt16 UpdateSwTrigger = 1027;
|
||||||
|
// public const UInt16 AutomaticSwUpdate = 1028;
|
||||||
|
// public const UInt16 CustomerValuesSaveReset = 1029;
|
||||||
|
// public const UInt16 SerialNumberSystemControl = 2001;
|
||||||
|
// public const UInt16 SerialNumberAcDc = 2009;
|
||||||
|
// public const UInt16 IntegrationLevel = 2051;
|
||||||
|
// public const UInt16 IlBuildnumber = 2052;
|
||||||
|
// public const UInt16 PowerStageConfig = 4001;
|
||||||
|
// public const UInt16 SetValueConfig = 4002;
|
||||||
|
// public const UInt16 ResetsAlarmAndWarning = 4003;
|
||||||
|
// public const UInt16 PreChargeDcLinkConfigR = 4006;
|
||||||
|
// public const UInt16 ReferenceFrameConvention = 4007;
|
||||||
|
// public const UInt16 SlaveAddress = 4008;
|
||||||
|
// public const UInt16 ErrorHandlingPolicy = 4009;
|
||||||
|
// public const UInt16 GridType = 4010;
|
||||||
|
// public const UInt16 SubSlaveAddress = 4011;
|
||||||
|
// public const UInt16 ModbusSlaveId = 4012;
|
||||||
|
// public const UInt16 SubSlaveErrorPolicy = 4013;
|
||||||
|
// public const UInt16 SignedPowerNominalValue = 4196;
|
||||||
|
// public const UInt16 SignedPowerSetValueL1 = 4197;
|
||||||
|
// public const UInt16 SignedPowerSetValueL2 = 4198;
|
||||||
|
// public const UInt16 SignedPowerSetValueL3 = 4199;
|
||||||
|
// public const UInt16 PowerSetValue = 4200;
|
||||||
|
// public const UInt16 PowerSetValueL1 = 4201;
|
||||||
|
// public const UInt16 PowerSetValueL2 = 4202;
|
||||||
|
// public const UInt16 PowerSetValueL3 = 4203;
|
||||||
|
// public const UInt16 MaximumGridCurrentRmsL1 = 4204;
|
||||||
|
// public const UInt16 MaximumGridCurrentRmsL2 = 4205;
|
||||||
|
// public const UInt16 MaximumGridCurrentRmsL3 = 4206;
|
||||||
|
// public const UInt16 CosPhiSetValueL1 = 4207;
|
||||||
|
// public const UInt16 CosPhiSetValueL2 = 4208;
|
||||||
|
// public const UInt16 CosPhiSetValueL3 = 4209;
|
||||||
|
// public const UInt16 PhaseL1IsCapacitive = 4214; // True = Capacitive, false = Inductive
|
||||||
|
// public const UInt16 PhaseL2IsCapacitive = 4215; // True = Capacitive, false = Inductive
|
||||||
|
// public const UInt16 PhaseL3IsCapacitive = 4216; // True = Capacitive, false = Inductive
|
||||||
|
// public const UInt16 PhasesAreCapacitive = 4217; // True = Capacitive, false = Inductive
|
||||||
|
// public const UInt16 SetPointCosPhi = 4218;
|
||||||
|
// public const UInt16 SetPointSinPhi = 4219;
|
||||||
|
// public const UInt16 SetPointSinPhiL1 = 4220;
|
||||||
|
// public const UInt16 SetPointSinPhiL2 = 4221;
|
||||||
|
// public const UInt16 SetPointSinPhiL3 = 4222;
|
||||||
|
// public const UInt16 FrequencyOffsetIm = 4223; //Im: Island mode
|
||||||
|
// public const UInt16 VoltageAdjustmentFactorIm = 4224; //Im: Island mode
|
||||||
|
// public const UInt16 PreChargeDcLinkVoltage = 4226;
|
||||||
|
// public const UInt16 MaxPeakCurrentVoltageControlL1 = 4227;
|
||||||
|
// public const UInt16 MaxPeakCurrentVoltageControlL2 = 4228;
|
||||||
|
// public const UInt16 MaxPeakCurrentVoltageControlL3 = 4229;
|
||||||
|
// public const UInt16 GridFormingMode = 4230;
|
||||||
|
// public const UInt16 DcLinkReferenceVoltage = 4231;
|
||||||
|
// public const UInt16 DcLinkMinVoltage = 4232;
|
||||||
|
// public const UInt16 DcLinkMaxVoltage = 4233;
|
||||||
|
// public const UInt16 AcDcDcVoltageRefUs = 4234;
|
||||||
|
// public const UInt16 AcDcMinDcLinkVoltageUs = 4235;
|
||||||
|
// public const UInt16 AcDcMaxDcLinkVoltageUs = 4236;
|
||||||
|
// // public const UInt16 FrequencySlopeIslandMode = 4237, // Function fN = f(active grid-power) of droop control
|
||||||
|
// // public const UInt16 VoltageSlopeIslandMode = 4238, // VN = f(reactive grid power) of droop control in island operation.
|
||||||
|
// public const UInt16 AcDcGcBypassMode = 4281;
|
||||||
|
// public const UInt16 AcDcGcPMaxThresholdPercent = 4282; // res
|
||||||
|
// public const UInt16 AcDcGcStartupRampEnable = 4283;
|
||||||
|
// public const UInt16 DcConfigModule = 4301; // 0 = DC module is off, battery voltage can be measured
|
||||||
|
// // 1 = DC module is active (DC link voltage control)
|
||||||
|
// // 2 = DC module is active(current source mode orin DC droop mode)
|
||||||
|
// public const UInt16 DcDcPowerDistribution = 4304;
|
||||||
|
// public const UInt16 AcDcDistributionMode = 4307;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ namespace InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
|
|
||||||
public enum MainState : UInt16
|
public enum MainState : UInt16
|
||||||
{
|
{
|
||||||
PowerUp = 0,
|
PowerUp = 0,
|
||||||
Alarm = 1,
|
Alarm = 1,
|
||||||
Idle = 2,
|
Idle = 2,
|
||||||
Operation = 3,
|
Operation = 3,
|
||||||
Maintenance = 4,
|
Maintenance = 4,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
|
||||||
|
|
||||||
public enum AcDcGridType : UInt16
|
|
||||||
{
|
|
||||||
GridTied400V50Hz = 0, // grid-tied, 400V, 50Hz
|
|
||||||
GridTied480V60Hz = 1, // grid-tied, 480V, 60Hz
|
|
||||||
Island400V50Hz = 2, // island mode, 400V, 50Hz
|
|
||||||
Island480V60Hz = 3, // island mode, 480V, 60Hz
|
|
||||||
GridTied380V60Hz = 4, // grid-tied, 380V, 60Hz
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PreChargeDcLinkConfig : UInt16
|
|
||||||
{
|
|
||||||
External = 0, // device waits for external precharge of DC link
|
|
||||||
Internal = 1, // device precharges external DC link to necessary start-up voltage
|
|
||||||
|
|
||||||
InternalWithDc =
|
|
||||||
2, // behaviour similar to 1 with additional support of DC submodules (necessary for island operation)
|
|
||||||
|
|
||||||
InternalWithWait =
|
|
||||||
3 // device precharges external DC link to necessary start-up voltage and waits until PrechargeDcLinkConfig gets set back to 1 or 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum AcErrorPolicy : UInt16
|
|
||||||
{
|
|
||||||
Relaxed = 0, // 0 = relaxed (System keeps running even if some slaves are in error state.)
|
|
||||||
Strict = 1, // 1 = strict (System shuts down as soon as one component is in error state.)
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SymmetricAcOperationMode : UInt16
|
|
||||||
{
|
|
||||||
//Configuration AC set values for phases L1 - L3
|
|
||||||
Asymmetric = 0,
|
|
||||||
Symmetric = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PowerFactorConvention : UInt16
|
|
||||||
{
|
|
||||||
Producer = 0, // 0 = producer reference frame
|
|
||||||
Consumer = 1, // 1 = consumer reference frame
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SubSlavesErrorPolicy : UInt16
|
|
||||||
{
|
|
||||||
Strict = 0, // (AC-DC module switches to error state if at least one submodules is in error state
|
|
||||||
Relaxed = 1, // (AC-DC module switches to error state if all submodules are in error state.)
|
|
||||||
Off = 2, // (If possible AC-DC module continues operation even if all submodules are in error state.
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DcStageConfiguration : UInt16
|
|
||||||
{
|
|
||||||
Off = 0, // DC module is off, power electronic circuit is deactivated, battery voltage can be measured.
|
|
||||||
Active = 1, // DC module is active and the power distribution according to parameters 4303 is active.
|
|
||||||
ActiveIndependent = 2, // DC module is active and operates independent from the AC module. The battery current set point from register 4500 is getting applied.
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum AcDcDistributionMode : UInt16
|
|
||||||
{
|
|
||||||
Power = 0, // power distribution
|
|
||||||
Current = 1, // current distribution
|
|
||||||
Auto = 2, // auto
|
|
||||||
}
|
|
Binary file not shown.
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum AcDcDistributionMode : UInt16
|
||||||
|
{
|
||||||
|
Power = 0, // power distribution
|
||||||
|
Current = 1, // current distribution
|
||||||
|
Auto = 2, // auto
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum AcDcGridType : UInt16
|
||||||
|
{
|
||||||
|
GridTied400V50Hz = 0, // grid-tied, 400V, 50Hz
|
||||||
|
GridTied480V60Hz = 1, // grid-tied, 480V, 60Hz
|
||||||
|
Island400V50Hz = 2, // island mode, 400V, 50Hz
|
||||||
|
Island480V60Hz = 3, // island mode, 480V, 60Hz
|
||||||
|
GridTied380V60Hz = 4, // grid-tied, 380V, 60Hz
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum AcErrorPolicy : UInt16
|
||||||
|
{
|
||||||
|
Relaxed = 0, // 0 = relaxed (System keeps running even if some slaves are in error state.)
|
||||||
|
Strict = 1, // 1 = strict (System shuts down as soon as one component is in error state.)
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum DcStageConfiguration : UInt16
|
||||||
|
{
|
||||||
|
Off = 0, // DC module is off, power electronic circuit is deactivated, battery voltage can be measured.
|
||||||
|
Active = 1, // DC module is active and the power distribution according to parameters 4303 is active.
|
||||||
|
ActiveIndependent = 2, // DC module is active and operates independent from the AC module. The battery current set point from register 4500 is getting applied.
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum PowerFactorConvention : UInt16
|
||||||
|
{
|
||||||
|
Producer = 0, // 0 = producer reference frame
|
||||||
|
Consumer = 1, // 1 = consumer reference frame
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum PreChargeDcLinkConfig : UInt16
|
||||||
|
{
|
||||||
|
External = 0, // device waits for external precharge of DC link
|
||||||
|
Internal = 1, // device precharges external DC link to necessary start-up voltage
|
||||||
|
InternalWithDc = 2, // behaviour similar to 1 with additional support of DC submodules (necessary for island operation)
|
||||||
|
InternalWithWait = 3 // device precharges external DC link to necessary start-up voltage and waits until PrechargeDcLinkConfig gets set back to 1 or 2
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum SubSlavesErrorPolicy : UInt16
|
||||||
|
{
|
||||||
|
Strict = 0, // (AC-DC module switches to error state if at least one submodules is in error state
|
||||||
|
Relaxed = 1, // (AC-DC module switches to error state if all submodules are in error state.)
|
||||||
|
Off = 2, // (If possible AC-DC module continues operation even if all submodules are in error state.
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
|
public enum SymmetricAcOperationMode : UInt16
|
||||||
|
{
|
||||||
|
//Configuration AC set values for phases L1 - L3
|
||||||
|
Asymmetric = 0,
|
||||||
|
Symmetric = 1,
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="../../../InnovEnergy.Lib.props" />
|
<Import Project="../../../InnovEnergy.Lib.props" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../../../Protocols/Modbus/Modbus.csproj" />
|
<ProjectReference Include="../../../Protocols/Modbus/Modbus.csproj" />
|
||||||
<ProjectReference Include="../../../StatusApi/StatusApi.csproj" />
|
<ProjectReference Include="../../../StatusApi/StatusApi.csproj" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
@ -139,22 +140,22 @@ public class TruConvertAcDevice
|
||||||
var acSetValues = ModbusTcpClient.ReadInputRegisters(4196, 1);
|
var acSetValues = ModbusTcpClient.ReadInputRegisters(4196, 1);
|
||||||
|
|
||||||
var warnings = Enumerable
|
var warnings = Enumerable
|
||||||
.Range(2404, 20)
|
.Range(2404, 20)
|
||||||
.Select(n => acWarningValues.GetUInt16((UInt16)n).ConvertTo<WarningMessage>())
|
.Select(n => acWarningValues.GetUInt16((UInt16)n).ConvertTo<WarningMessage>())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var alarms = Enumerable
|
var alarms = Enumerable
|
||||||
.Range(2811, 20)
|
.Range(2811, 20)
|
||||||
.Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo<AlarmMessage>())
|
.Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo<AlarmMessage>())
|
||||||
.Where(m => m != AlarmMessage.NoAlarm)
|
.Where(m => m != AlarmMessage.NoAlarm)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
var dcPower = acActualMeasurement.GetInt16(5141) * 1m + acActualMeasurement.GetInt16(5142) * 1m + acActualMeasurement.GetInt16(5143) * 1m;
|
var dcPower = acActualMeasurement.GetInt16(5141) * 1m + acActualMeasurement.GetInt16(5142) * 1m + acActualMeasurement.GetInt16(5143) * 1m;
|
||||||
var dcVoltage = acActualMeasurement8.GetUInt16(5214) + acActualMeasurement8.GetUInt16(5213);
|
var dcVoltage = acActualMeasurement8.GetUInt16(5214) + acActualMeasurement8.GetUInt16(5213);
|
||||||
var dcCurrent = dcVoltage != 0m
|
var dcCurrent = dcVoltage != 0m
|
||||||
? dcPower / dcVoltage
|
? dcPower / dcVoltage
|
||||||
: 0m;
|
: 0m;
|
||||||
|
|
||||||
|
|
||||||
// //acActualMeasurement
|
// //acActualMeasurement
|
||||||
|
@ -212,56 +213,118 @@ public class TruConvertAcDevice
|
||||||
var gridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m;
|
var gridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m;
|
||||||
|
|
||||||
var gridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m;
|
var gridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m;
|
||||||
|
|
||||||
return new TruConvertAcStatus
|
return new TruConvertAcStatus
|
||||||
(
|
{
|
||||||
Ac: new Ac3Bus
|
Ac = new Ac3Bus
|
||||||
(
|
{
|
||||||
new AcPhase(gridVoltageL1,phaseCurrentL1, ACos(powerAcL1/apparentPowerAcL1)),
|
Frequency = gridFrequency,
|
||||||
new AcPhase(gridVoltageL2,phaseCurrentL2, ACos(powerAcL2/apparentPowerAcL2)),
|
|
||||||
new AcPhase(gridVoltageL3,phaseCurrentL3, ACos(powerAcL3/apparentPowerAcL3)),
|
|
||||||
gridFrequency // Gird Frequency
|
|
||||||
),
|
|
||||||
Dc: new DcConnection(dcVoltage, dcCurrent),
|
|
||||||
|
|
||||||
SerialNumber : acSerialNumber.GetInt32(2009).ToString(),
|
L1 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL1,
|
||||||
|
Current = phaseCurrentL1,
|
||||||
|
Phi = ACos(powerAcL1 / apparentPowerAcL1), // TODO: 2pi
|
||||||
|
},
|
||||||
|
L2 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL2,
|
||||||
|
Current = phaseCurrentL2,
|
||||||
|
Phi = ACos(powerAcL2 / apparentPowerAcL2), // TODO: 2pi
|
||||||
|
},
|
||||||
|
L3 = new AcPhase
|
||||||
|
{
|
||||||
|
Voltage = gridVoltageL3,
|
||||||
|
Current = phaseCurrentL3,
|
||||||
|
Phi = ACos(powerAcL3 / apparentPowerAcL3), // TODO: 2pi
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Dc = new DcBus
|
||||||
|
{
|
||||||
|
Current = dcCurrent,
|
||||||
|
Voltage = dcVoltage,
|
||||||
|
},
|
||||||
|
|
||||||
// acActualMainValues
|
MainState = acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
||||||
MainState : acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
Alarms = alarms,
|
||||||
NumberOfConnectedSlaves : acActualMain.GetUInt16(5002),
|
Warnings = warnings,
|
||||||
NumberOfConnectedSubSlaves : acActualMain.GetUInt16(5003),
|
GridType = acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
||||||
|
SerialNumber = acSerialNumber.GetInt32(2009).ToString(), // TODO: why tostring ?
|
||||||
|
NumberOfConnectedSlaves = acActualMain.GetUInt16(5002),
|
||||||
|
NumberOfConnectedSubSlaves = acActualMain.GetUInt16(5003),
|
||||||
|
AcDcNominalGridFrequency = acActualAcDc.GetUInt16(5021) * 0.1m,
|
||||||
|
AcDcNominalGridVoltage = acActualAcDc.GetUInt16(5022),
|
||||||
|
AcDcActNominalPower = acActualAcDc.GetUInt16(5023),
|
||||||
|
AcDcPowerLimitingStatusAct = acActualAcDc.GetUInt16(5025),
|
||||||
|
AcDcDcVoltageReference = acActualAcDc.GetUInt16(5026), // DC link reference
|
||||||
|
AcDcDcLinkVoltageMinAct = acActualAcDc.GetUInt16(5027), // DC link min voltage
|
||||||
|
AcDcDcLinkVoltageMaxAct = acActualAcDc.GetUInt16(5028), // DC link max voltage
|
||||||
|
AcDcDcLinkChargedMinVoltage = acActualAcDc.GetUInt16(5029) * 0.01m,
|
||||||
|
AcDcStmActCustomer = acActualAcDc2.GetUInt16(5031), //need to check
|
||||||
|
AcDcOverloadIntegratorStatusL1 = acActualAcDc3.GetUInt16(5134) * 0.1m,
|
||||||
|
AcDcOverloadIntegratorStatusL2 = acActualAcDc3.GetUInt16(5135) * 0.1m,
|
||||||
|
AcDcOverloadIntegratorStatusL3 = acActualAcDc3.GetUInt16(5136) * 0.1m,
|
||||||
|
AcSignedPowerValue = acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
||||||
|
ActualDcLinkVoltageUpperHalf = acActualMeasurement8.GetUInt16(5211),
|
||||||
|
ActualDcLinkVoltageLowerHalf = acActualMeasurement8.GetUInt16(5212),
|
||||||
|
ActualDcLinkVoltageUpperHalfExt = acActualMeasurement8.GetUInt16(5213),
|
||||||
|
ActualDcLinkVoltageLowerHalfExt = acActualMeasurement8.GetUInt16(5214),
|
||||||
|
VoltageIntNtoPe = acActualMeasurement9.GetInt16(5221) * 0.1m,
|
||||||
|
VoltageExtNtoPe = acActualMeasurement9.GetInt16(5222) * 0.1m,
|
||||||
|
InletAirTemperature = acActualTemp.GetInt16(5501) * 0.1m,
|
||||||
|
|
||||||
//acActualAcDc
|
};
|
||||||
AcDcNominalGridFrequency : acActualAcDc.GetUInt16(5021) * 0.1m,
|
|
||||||
AcDcNominalGridVoltage : acActualAcDc.GetUInt16(5022),
|
|
||||||
AcDcActNominalPower : acActualAcDc.GetUInt16(5023),
|
|
||||||
AcDcActiveGridType : acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
|
||||||
AcDcPowerLimitingStatusAct : acActualAcDc.GetUInt16(5025),
|
|
||||||
AcDcDcVoltageReference : acActualAcDc.GetUInt16(5026), // DC link reference
|
|
||||||
AcDcDcLinkVoltageMinAct : acActualAcDc.GetUInt16(5027), // DC link min voltage
|
|
||||||
AcDcDcLinkVoltageMaxAct : acActualAcDc.GetUInt16(5028), // DC link max voltage
|
|
||||||
AcDcDcLinkChargedMinVoltage : acActualAcDc.GetUInt16(5029) * 0.01m,
|
|
||||||
|
|
||||||
//ac Actual AcDc 2
|
|
||||||
AcDcStmActCustomer : acActualAcDc2.GetUInt16(5031), //need to check
|
|
||||||
AcDcOverloadIntegratorStatusL1 : acActualAcDc3.GetUInt16(5134) * 0.1m,
|
|
||||||
AcDcOverloadIntegratorStatusL2 : acActualAcDc3.GetUInt16(5135) * 0.1m,
|
|
||||||
AcDcOverloadIntegratorStatusL3 : acActualAcDc3.GetUInt16(5136) * 0.1m,
|
|
||||||
AcSignedPowerValue : acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
|
||||||
|
|
||||||
//acActualMeasurement10
|
|
||||||
ActualDcLinkVoltageUpperHalf : acActualMeasurement8.GetUInt16(5211),
|
|
||||||
ActualDcLinkVoltageLowerHalf : acActualMeasurement8.GetUInt16(5212),
|
|
||||||
ActualDcLinkVoltageUpperHalfExt : acActualMeasurement8.GetUInt16(5213),
|
|
||||||
ActualDcLinkVoltageLowerHalfExt : acActualMeasurement8.GetUInt16(5214),
|
|
||||||
|
|
||||||
VoltageIntNtoPe : acActualMeasurement9.GetInt16(5221) * 0.1m,
|
|
||||||
VoltageExtNtoPe : acActualMeasurement9.GetInt16(5222) * 0.1m,
|
|
||||||
//acActualTemp
|
// (
|
||||||
InletAirTemperature : acActualTemp.GetInt16(5501) * 0.1m,
|
// Ac: new Ac3Bus
|
||||||
|
// (
|
||||||
Warnings : warnings,
|
// new AcPhase(gridVoltageL1,phaseCurrentL1, ACos(powerAcL1/apparentPowerAcL1)),
|
||||||
Alarms : alarms
|
// new AcPhase(gridVoltageL2,phaseCurrentL2, ACos(powerAcL2/apparentPowerAcL2)),
|
||||||
);
|
// new AcPhase(gridVoltageL3,phaseCurrentL3, ACos(powerAcL3/apparentPowerAcL3)),
|
||||||
|
// gridFrequency // Gird Frequency
|
||||||
|
// ),
|
||||||
|
// Dc: new DcConnection(dcVoltage, dcCurrent),
|
||||||
|
//
|
||||||
|
// SerialNumber : acSerialNumber.GetInt32(2009).ToString(),
|
||||||
|
//
|
||||||
|
// // acActualMainValues
|
||||||
|
// MainState : acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
||||||
|
// NumberOfConnectedSlaves : acActualMain.GetUInt16(5002),
|
||||||
|
// NumberOfConnectedSubSlaves : acActualMain.GetUInt16(5003),
|
||||||
|
//
|
||||||
|
// //acActualAcDc
|
||||||
|
// AcDcNominalGridFrequency : acActualAcDc.GetUInt16(5021) * 0.1m,
|
||||||
|
// AcDcNominalGridVoltage : acActualAcDc.GetUInt16(5022),
|
||||||
|
// AcDcActNominalPower : acActualAcDc.GetUInt16(5023),
|
||||||
|
// AcDcActiveGridType : acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
||||||
|
// AcDcPowerLimitingStatusAct : acActualAcDc.GetUInt16(5025),
|
||||||
|
// AcDcDcVoltageReference : acActualAcDc.GetUInt16(5026), // DC link reference
|
||||||
|
// AcDcDcLinkVoltageMinAct : acActualAcDc.GetUInt16(5027), // DC link min voltage
|
||||||
|
// AcDcDcLinkVoltageMaxAct : acActualAcDc.GetUInt16(5028), // DC link max voltage
|
||||||
|
// AcDcDcLinkChargedMinVoltage : acActualAcDc.GetUInt16(5029) * 0.01m,
|
||||||
|
//
|
||||||
|
// //ac Actual AcDc 2
|
||||||
|
// AcDcStmActCustomer : acActualAcDc2.GetUInt16(5031), //need to check
|
||||||
|
// AcDcOverloadIntegratorStatusL1 : acActualAcDc3.GetUInt16(5134) * 0.1m,
|
||||||
|
// AcDcOverloadIntegratorStatusL2 : acActualAcDc3.GetUInt16(5135) * 0.1m,
|
||||||
|
// AcDcOverloadIntegratorStatusL3 : acActualAcDc3.GetUInt16(5136) * 0.1m,
|
||||||
|
// AcSignedPowerValue : acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
||||||
|
//
|
||||||
|
// //acActualMeasurement10
|
||||||
|
// ActualDcLinkVoltageUpperHalf : acActualMeasurement8.GetUInt16(5211),
|
||||||
|
// ActualDcLinkVoltageLowerHalf : acActualMeasurement8.GetUInt16(5212),
|
||||||
|
// ActualDcLinkVoltageUpperHalfExt : acActualMeasurement8.GetUInt16(5213),
|
||||||
|
// ActualDcLinkVoltageLowerHalfExt : acActualMeasurement8.GetUInt16(5214),
|
||||||
|
//
|
||||||
|
// VoltageIntNtoPe : acActualMeasurement9.GetInt16(5221) * 0.1m,
|
||||||
|
// VoltageExtNtoPe : acActualMeasurement9.GetInt16(5222) * 0.1m,
|
||||||
|
// //acActualTemp
|
||||||
|
// InletAirTemperature : acActualTemp.GetInt16(5501) * 0.1m,
|
||||||
|
//
|
||||||
|
// Warnings : warnings,
|
||||||
|
// Alarms : alarms
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,43 +1,45 @@
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Enums;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.StatusApi;
|
||||||
|
using InnovEnergy.Lib.Units;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||||
|
|
||||||
using AlarmMessages = IReadOnlyList<AlarmMessage>;
|
using AlarmMessages = IReadOnlyList<AlarmMessage>;
|
||||||
using WarningMessages = IReadOnlyList<WarningMessage>;
|
using WarningMessages = IReadOnlyList<WarningMessage>;
|
||||||
|
|
||||||
public record TruConvertAcStatus
|
|
||||||
(
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
Ac3Bus Ac,
|
#pragma warning disable CS8618
|
||||||
DcConnection Dc,
|
|
||||||
String SerialNumber,
|
|
||||||
MainState MainState,
|
public record TruConvertAcStatus : ThreePhaseInverterStatus
|
||||||
UInt16 NumberOfConnectedSlaves,
|
|
||||||
UInt16 NumberOfConnectedSubSlaves,
|
|
||||||
Decimal AcDcNominalGridFrequency,
|
|
||||||
Decimal AcDcNominalGridVoltage,
|
|
||||||
Decimal AcDcActNominalPower,
|
|
||||||
AcDcGridType AcDcActiveGridType,
|
|
||||||
Decimal AcDcPowerLimitingStatusAct,
|
|
||||||
Decimal AcDcDcVoltageReference,
|
|
||||||
Decimal AcDcDcLinkVoltageMinAct,
|
|
||||||
Decimal AcDcDcLinkVoltageMaxAct,
|
|
||||||
Decimal AcDcDcLinkChargedMinVoltage,
|
|
||||||
Decimal AcDcStmActCustomer,
|
|
||||||
Decimal AcDcOverloadIntegratorStatusL1,
|
|
||||||
Decimal AcDcOverloadIntegratorStatusL2,
|
|
||||||
Decimal AcDcOverloadIntegratorStatusL3,
|
|
||||||
Decimal AcSignedPowerValue,
|
|
||||||
Decimal ActualDcLinkVoltageUpperHalf,
|
|
||||||
Decimal ActualDcLinkVoltageLowerHalf,
|
|
||||||
Decimal ActualDcLinkVoltageUpperHalfExt,
|
|
||||||
Decimal ActualDcLinkVoltageLowerHalfExt,
|
|
||||||
Decimal VoltageIntNtoPe,
|
|
||||||
Decimal VoltageExtNtoPe,
|
|
||||||
Decimal InletAirTemperature,
|
|
||||||
WarningMessages Warnings,
|
|
||||||
AlarmMessages Alarms
|
|
||||||
) : ThreePhaseInverter(Ac, Dc)
|
|
||||||
{
|
{
|
||||||
}
|
public MainState MainState { get; init; }
|
||||||
|
public String SerialNumber { get; init; }
|
||||||
|
public AcDcGridType GridType { get; init; }
|
||||||
|
public WarningMessages Warnings { get; init; }
|
||||||
|
public AlarmMessages Alarms { get; init; }
|
||||||
|
public Decimal NumberOfConnectedSlaves { get; init; }
|
||||||
|
public Decimal NumberOfConnectedSubSlaves { get; init; }
|
||||||
|
public Frequency AcDcNominalGridFrequency { get; init; }
|
||||||
|
public Voltage AcDcNominalGridVoltage { get; init; }
|
||||||
|
public Power AcDcActNominalPower { get; init; }
|
||||||
|
public Decimal AcDcPowerLimitingStatusAct { get; init; } // TODO: enum
|
||||||
|
public Voltage AcDcDcVoltageReference { get; init; }
|
||||||
|
public Voltage AcDcDcLinkVoltageMinAct { get; init; }
|
||||||
|
public Voltage AcDcDcLinkVoltageMaxAct { get; init; }
|
||||||
|
public Voltage AcDcDcLinkChargedMinVoltage { get; init; }
|
||||||
|
public Decimal AcDcStmActCustomer { get; init; }
|
||||||
|
public Decimal AcDcOverloadIntegratorStatusL1 { get; init; }
|
||||||
|
public Decimal AcDcOverloadIntegratorStatusL2 { get; init; }
|
||||||
|
public Decimal AcDcOverloadIntegratorStatusL3 { get; init; }
|
||||||
|
public Power AcSignedPowerValue { get; init; }
|
||||||
|
public Voltage ActualDcLinkVoltageUpperHalf { get; init; }
|
||||||
|
public Voltage ActualDcLinkVoltageLowerHalf { get; init; }
|
||||||
|
public Voltage ActualDcLinkVoltageUpperHalfExt { get; init; }
|
||||||
|
public Voltage ActualDcLinkVoltageLowerHalfExt { get; init; }
|
||||||
|
public Voltage VoltageIntNtoPe { get; init; }
|
||||||
|
public Voltage VoltageExtNtoPe { get; init; }
|
||||||
|
public Temperature InletAirTemperature { get; init; }
|
||||||
|
}
|
||||||
|
|
|
@ -8,17 +8,17 @@ namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||||
|
|
||||||
public enum WarningMessage
|
public enum WarningMessage
|
||||||
{
|
{
|
||||||
ERR_WARN_FAN =10500, //AC-DC module warning
|
ERR_WARN_FAN = 10500, //AC-DC module warning
|
||||||
ERR_WARN_I_OFFSET =10503, //AC-DC module warning
|
ERR_WARN_I_OFFSET = 10503, //AC-DC module warning
|
||||||
ERR_WARN_VG_OFFSET =10504, //AC-DC module warning
|
ERR_WARN_VG_OFFSET = 10504, //AC-DC module warning
|
||||||
ERR_WARN_VC_OFFSET =10505, //AC-DC module warning
|
ERR_WARN_VC_OFFSET = 10505, //AC-DC module warning
|
||||||
ERR_WARN_DC_OFFSET =10506, //AC-DC module warning
|
ERR_WARN_DC_OFFSET = 10506, //AC-DC module warning
|
||||||
ERR_WARN_NTC_PROTECT =10507, //DC-link circuit need more time for cool down
|
ERR_WARN_NTC_PROTECT = 10507, //DC-link circuit need more time for cool down
|
||||||
ERR_WARN_AIR_TEMP =10508, //Overtemperature inlet air: power is derated
|
ERR_WARN_AIR_TEMP = 10508, //Overtemperature inlet air: power is derated
|
||||||
SurgeDetected =10509, //Temporary overvoltage in grid measurement detected (surge)
|
SurgeDetected = 10509, //Temporary overvoltage in grid measurement detected (surge)
|
||||||
ERR_WARN_TEMP_DERATING =11021, //Temperature derating active
|
ERR_WARN_TEMP_DERATING = 11021, //Temperature derating active
|
||||||
ERR_WARN_OVERLOAD =11022, //Overload handling is active
|
ERR_WARN_OVERLOAD = 11022, //Overload handling is active
|
||||||
ERR_WARN_RUNTIME_EEPROM =11023, //AC-DC module warning
|
ERR_WARN_RUNTIME_EEPROM = 11023, //AC-DC module warning
|
||||||
ERR_WARN_OVERCURRENT =11024 //Overcurrent handling is active
|
ERR_WARN_OVERCURRENT = 11024 //Overcurrent handling is active
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
using static InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.DcControlRegisters;
|
using static InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.DcControlRegisters;
|
||||||
|
|
||||||
|
@ -138,27 +138,31 @@ public class TruConvertDcDevice
|
||||||
var dcCurrent = dcLinkVoltage != 0m ? dcPower / dcLinkVoltage : 0m;
|
var dcCurrent = dcLinkVoltage != 0m ? dcPower / dcLinkVoltage : 0m;
|
||||||
|
|
||||||
return new TruConvertDcStatus
|
return new TruConvertDcStatus
|
||||||
(
|
{
|
||||||
|
Left = new DcBus()
|
||||||
|
{
|
||||||
|
Current = dcCurrent,
|
||||||
|
Voltage = dcLinkVoltage
|
||||||
|
},
|
||||||
|
|
||||||
|
Right = new DcBus()
|
||||||
|
{
|
||||||
|
Current = dcBatteryValue2.GetInt16(5111),
|
||||||
|
Voltage =dcBatteryValue.GetUInt16(5101) * 0.1m,
|
||||||
|
},
|
||||||
|
|
||||||
Dc: new DcConnection
|
MainState = (MainState)dcPrValMain.GetInt16(5001),
|
||||||
(
|
NumberOfConnectedSlaves = dcPrValMain.GetUInt16(5002),
|
||||||
dcLinkVoltage,
|
NumberOfConnectedSubSlaves = dcPrValMain.GetUInt16(5003),
|
||||||
dcCurrent
|
TotalDcPower = dcBatteryValue3.GetInt32(5114) * 1m, // Resolution is 0.001 (kW) in Tru convert DC doc, but we want it in W
|
||||||
),
|
StatusOfCurrentLimiting = dcCurrentLimitState,
|
||||||
|
OverloadCapacity = dcPrValDcDc2.GetUInt16(5127) * 0.1m,
|
||||||
MainState : (MainState)dcPrValMain.GetInt16(5001),
|
DcDcInletTemperature = dcTempValue.GetInt16(5511),
|
||||||
NumberOfConnectedSlaves : dcPrValMain.GetUInt16(5002),
|
Warnings = warnings,
|
||||||
NumberOfConnectedSubSlaves : dcPrValMain.GetUInt16(5003),
|
Alarms = alarms,
|
||||||
BatteryVoltage : dcBatteryValue.GetUInt16(5101) * 0.1m,
|
PowerOperation = dcSetValues.GetBoolean(4001),
|
||||||
BatteryCurrent : dcBatteryValue2.GetInt16(5111),
|
|
||||||
TotalDcPower : dcBatteryValue3.GetInt32(5114) * 1m, // Resolution is 0.001 (kW) in Tru convert DC doc, but we want it in W
|
};
|
||||||
StatusOfCurrentLimiting : dcCurrentLimitState,
|
|
||||||
OverloadCapacity : dcPrValDcDc2.GetUInt16(5127) * 0.1m,
|
|
||||||
DcDcInletTemperature : dcTempValue.GetInt16(5511),
|
|
||||||
Warnings : warnings,
|
|
||||||
Alarms : alarms,
|
|
||||||
PowerOperation : dcSetValues.GetBoolean(4001)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
using InnovEnergy.Lib.StatusApi;
|
using InnovEnergy.Lib.StatusApi;
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
@ -9,24 +10,20 @@ using AlarmMessages = IReadOnlyList<AlarmMessage>;
|
||||||
using WarningMessages = IReadOnlyList<WarningMessage>;
|
using WarningMessages = IReadOnlyList<WarningMessage>;
|
||||||
using DcCurrentLimitStates = IReadOnlyList<DcCurrentLimitState>;
|
using DcCurrentLimitStates = IReadOnlyList<DcCurrentLimitState>;
|
||||||
|
|
||||||
public record TruConvertDcStatus
|
public record TruConvertDcStatus : DcDcConverterStatus
|
||||||
(
|
|
||||||
DcBus DcLeft,
|
|
||||||
DcBus DcRight,
|
|
||||||
State MainState,
|
|
||||||
Power TotalDcPower, // TODO: necessary?
|
|
||||||
State StatusOfCurrentLimiting,
|
|
||||||
Decimal OverloadCapacity,
|
|
||||||
Temperature DcDcInletTemperature,
|
|
||||||
State Alarms,
|
|
||||||
State Warnings,
|
|
||||||
State PowerOperation
|
|
||||||
|
|
||||||
// UInt16 NumberOfConnectedSlaves, // TODO: necessary?
|
|
||||||
// UInt16 NumberOfConnectedSubSlaves, // TODO: necessary?
|
|
||||||
) :
|
|
||||||
DcDcConverterStatus(DcLeft, DcRight)
|
|
||||||
{
|
{
|
||||||
public static TruConvertDcStatus operator |(TruConvertDcStatus left, TruConvertDcStatus right) => OpParallel(left, right);
|
public MainState MainState { get; init; }
|
||||||
private static readonly Func<TruConvertDcStatus, TruConvertDcStatus, TruConvertDcStatus> OpParallel = Operators.Op<TruConvertDcStatus>("|");
|
public Power TotalDcPower { get; init; } // TODO: necessary?
|
||||||
}
|
public DcCurrentLimitStates StatusOfCurrentLimiting { get; init; }
|
||||||
|
public Decimal OverloadCapacity { get; init; }
|
||||||
|
public Temperature DcDcInletTemperature { get; init; }
|
||||||
|
public AlarmMessages Alarms { get; init; } = Array.Empty<AlarmMessage>();
|
||||||
|
public WarningMessages Warnings { get; init; } = Array.Empty<WarningMessage>();
|
||||||
|
public Boolean PowerOperation { get; init; }
|
||||||
|
public Decimal NumberOfConnectedSlaves { get; init; } // TODO: necessary?
|
||||||
|
public Decimal NumberOfConnectedSubSlaves { get; init; } // TODO: necessary?
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
// public static TruConvertDcStatus operator |(TruConvertDcStatus left, TruConvertDcStatus right) => OpParallel(left, right);
|
||||||
|
// private static readonly Func<TruConvertDcStatus, TruConvertDcStatus, TruConvertDcStatus> OpParallel = Operators.Op<TruConvertDcStatus>("|");
|
||||||
|
// }
|
|
@ -1,8 +1,6 @@
|
||||||
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 InnovEnergy.Lib.Protocols.Modbus.Protocol;
|
using InnovEnergy.Lib.Protocols.Modbus.Protocol;
|
||||||
using static InnovEnergy.Lib.Protocols.Modbus.Protocol.MultiRegisterEndianness;
|
|
||||||
using static InnovEnergy.Lib.Protocols.Modbus.Protocol.RegisterIndexing;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
|
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
|
||||||
|
@ -15,9 +13,7 @@ public abstract class ModbusClient
|
||||||
{
|
{
|
||||||
protected ModbusConnection Connection { get; }
|
protected ModbusConnection Connection { get; }
|
||||||
protected Byte SlaveId { get; }
|
protected Byte SlaveId { get; }
|
||||||
protected RegisterIndexing RegisterIndexing { get; }
|
|
||||||
protected MultiRegisterEndianness Endianness { get; }
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: add additional functions: coils...
|
// TODO: add additional functions: coils...
|
||||||
|
|
||||||
|
@ -45,19 +41,14 @@ public abstract class ModbusClient
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ModbusClient(ModbusConnection connection,
|
protected ModbusClient(ModbusConnection connection,
|
||||||
Byte slaveId,
|
Byte slaveId)
|
||||||
RegisterIndexing registerIndexing = OneBased,
|
|
||||||
MultiRegisterEndianness endianness = LittleEndian)
|
|
||||||
{
|
{
|
||||||
Connection = connection;
|
Connection = connection;
|
||||||
SlaveId = slaveId;
|
SlaveId = slaveId;
|
||||||
RegisterIndexing = registerIndexing;
|
|
||||||
Endianness = endianness;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseConnection() => Connection.Close();
|
public void CloseConnection() => Connection.Close();
|
||||||
|
|
||||||
protected UInt16 LogicToWire(UInt16 address) => RegisterIndexing.LogicToSerialized(address);
|
|
||||||
protected UInt16 SerializedToLogic(UInt16 address) => RegisterIndexing.SerializedToLogic(address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,7 @@ public class ModbusRtuClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
|
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
var cmd = new ReadInputRegistersCommandFrame(SlaveId, readAddress, nValues);
|
||||||
|
|
||||||
var cmd = new ReadInputRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
|
|
||||||
var crc = CalcCrc(cmd);
|
var crc = CalcCrc(cmd);
|
||||||
|
|
||||||
// TX
|
// TX
|
||||||
|
@ -56,9 +54,7 @@ public class ModbusRtuClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
|
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, readAddress, nValues);
|
||||||
|
|
||||||
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
|
|
||||||
var crc = CalcCrc(cmd.Data);
|
var crc = CalcCrc(cmd.Data);
|
||||||
|
|
||||||
// TX
|
// TX
|
||||||
|
@ -86,9 +82,7 @@ public class ModbusRtuClient : ModbusClient
|
||||||
|
|
||||||
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
|
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
|
||||||
{
|
{
|
||||||
var wireWriteAddress = LogicToWire(writeAddress);
|
var cmd = new WriteRegistersCommandFrame(SlaveId, writeAddress, values);
|
||||||
|
|
||||||
var cmd = new WriteRegistersCommandFrame(SlaveId, wireWriteAddress, values);
|
|
||||||
var crc = CalcCrc(cmd);
|
var crc = CalcCrc(cmd);
|
||||||
var nToRead = cmd.ExpectedResponseSize + CrcSize;
|
var nToRead = cmd.ExpectedResponseSize + CrcSize;
|
||||||
|
|
||||||
|
@ -111,13 +105,10 @@ public class ModbusRtuClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
|
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
|
||||||
var wireWriteAddress = LogicToWire(writeAddress);
|
|
||||||
|
|
||||||
var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
|
var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
|
||||||
wireReadAddress,
|
readAddress,
|
||||||
nbToRead,
|
nbToRead,
|
||||||
wireWriteAddress,
|
writeAddress,
|
||||||
registersToWrite);
|
registersToWrite);
|
||||||
var crc = CalcCrc(cmd);
|
var crc = CalcCrc(cmd);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
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 InnovEnergy.Lib.Protocols.Modbus.Protocol;
|
|
||||||
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.Protocol.MultiRegisterEndianness;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
|
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
|
||||||
|
@ -21,21 +20,16 @@ public class ModbusTcpClient : ModbusClient
|
||||||
private UInt16 NextId() => unchecked(++_Id);
|
private UInt16 NextId() => unchecked(++_Id);
|
||||||
|
|
||||||
|
|
||||||
public ModbusTcpClient(ModbusConnection connection,
|
public ModbusTcpClient(ModbusConnection connection, Byte slaveId) : base(connection, slaveId)
|
||||||
Byte slaveId,
|
|
||||||
RegisterIndexing registerIndexing = RegisterIndexing.OneBased,
|
|
||||||
MultiRegisterEndianness endianness = LittleEndian) : base(connection, slaveId, registerIndexing, endianness)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override IReadOnlyList<Boolean> ReadDiscreteInputs(UInt16 readAddress, UInt16 nValues)
|
public override IReadOnlyList<Boolean> ReadDiscreteInputs(UInt16 readAddress, UInt16 nValues)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
|
||||||
|
|
||||||
var id = NextId(); // TODO: check response id
|
var id = NextId(); // TODO: check response id
|
||||||
|
|
||||||
var cmd = new ReadDiscreteInputsCommandFrame(SlaveId, wireReadAddress, nValues);
|
var cmd = new ReadDiscreteInputsCommandFrame(SlaveId, readAddress, nValues);
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
var frm = new ModbusTcpFrame(hdr, cmd);
|
var frm = new ModbusTcpFrame(hdr, cmd);
|
||||||
|
|
||||||
|
@ -52,10 +46,9 @@ public class ModbusTcpClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
|
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
|
||||||
var id = NextId(); // TODO: check response id
|
var id = NextId(); // TODO: check response id
|
||||||
|
|
||||||
var cmd = new ReadInputRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
|
var cmd = new ReadInputRegistersCommandFrame(SlaveId, readAddress, nValues);
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
var frm = new ModbusTcpFrame(hdr, cmd);
|
var frm = new ModbusTcpFrame(hdr, cmd);
|
||||||
|
|
||||||
|
@ -77,10 +70,8 @@ public class ModbusTcpClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
|
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
|
||||||
|
|
||||||
var id = NextId(); // TODO: check response id
|
var id = NextId(); // TODO: check response id
|
||||||
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
|
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, readAddress, nValues);
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
var frm = new ModbusTcpFrame(hdr, cmd);
|
var frm = new ModbusTcpFrame(hdr, cmd);
|
||||||
|
|
||||||
|
@ -99,10 +90,8 @@ public class ModbusTcpClient : ModbusClient
|
||||||
|
|
||||||
public override UInt16 WriteMultipleCoils(UInt16 writeAddress, Coils coils)
|
public override UInt16 WriteMultipleCoils(UInt16 writeAddress, Coils coils)
|
||||||
{
|
{
|
||||||
var wireWriteAddress = LogicToWire(writeAddress);
|
var id = NextId(); // TODO: check response id
|
||||||
|
var cmd = new WriteCoilsCommandFrame(SlaveId, writeAddress, coils);
|
||||||
var id = NextId(); // TODO: check response id
|
|
||||||
var cmd = new WriteCoilsCommandFrame(SlaveId, wireWriteAddress, coils);
|
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
var frm = new ModbusTcpFrame(hdr, cmd);
|
var frm = new ModbusTcpFrame(hdr, cmd);
|
||||||
|
|
||||||
|
@ -120,10 +109,8 @@ public class ModbusTcpClient : ModbusClient
|
||||||
|
|
||||||
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
|
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
|
||||||
{
|
{
|
||||||
var wireWriteAddress = LogicToWire(writeAddress);
|
|
||||||
|
|
||||||
var id = NextId(); // TODO: check response id
|
var id = NextId(); // TODO: check response id
|
||||||
var cmd = new WriteRegistersCommandFrame(SlaveId, wireWriteAddress, values);
|
var cmd = new WriteRegistersCommandFrame(SlaveId, writeAddress, values);
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
var frm = new ModbusTcpFrame(hdr, cmd);
|
var frm = new ModbusTcpFrame(hdr, cmd);
|
||||||
|
|
||||||
|
@ -142,15 +129,14 @@ public class ModbusTcpClient : ModbusClient
|
||||||
|
|
||||||
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
|
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
|
||||||
{
|
{
|
||||||
var wireReadAddress = LogicToWire(readAddress);
|
|
||||||
var wireWriteAddress = LogicToWire(writeAddress);
|
|
||||||
|
|
||||||
var id = NextId(); // TODO: check response id
|
var id = NextId(); // TODO: check response id
|
||||||
|
|
||||||
var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
|
var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
|
||||||
wireReadAddress,
|
readAddress,
|
||||||
nbToRead,
|
nbToRead,
|
||||||
wireWriteAddress,
|
writeAddress,
|
||||||
registersToWrite);
|
registersToWrite);
|
||||||
|
|
||||||
var hdr = new MbapHeader(id, cmd.Data.Count);
|
var hdr = new MbapHeader(id, cmd.Data.Count);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
using static InnovEnergy.Lib.Protocols.Modbus.Protocol.MultiRegisterEndianness;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors;
|
namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors;
|
||||||
|
|
||||||
|
@ -10,22 +9,11 @@ public struct MbRegisters : IReadOnlyList<UInt16>
|
||||||
{
|
{
|
||||||
private MbWords Words { get; }
|
private MbWords Words { get; }
|
||||||
private UInt16 StartRegister { get; }
|
private UInt16 StartRegister { get; }
|
||||||
private MultiRegisterEndianness Endianness { get; }
|
|
||||||
|
|
||||||
public MbRegisters(MbWords words,
|
public MbRegisters(MbWords words, UInt16 startRegister)
|
||||||
UInt16 startRegister,
|
|
||||||
MultiRegisterEndianness endianness,
|
|
||||||
RegisterIndexing registerIndexing)
|
|
||||||
{
|
{
|
||||||
Words = words;
|
Words = words;
|
||||||
Endianness = endianness;
|
StartRegister = startRegister;
|
||||||
|
|
||||||
var start = startRegister - (Int16) registerIndexing; // TODO: check
|
|
||||||
|
|
||||||
if (start < 0)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(startRegister));
|
|
||||||
|
|
||||||
StartRegister = (UInt16)start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<UInt16> GetEnumerator() => Words.GetEnumerator();
|
public IEnumerator<UInt16> GetEnumerator() => Words.GetEnumerator();
|
||||||
|
@ -74,9 +62,6 @@ public struct MbRegisters : IReadOnlyList<UInt16>
|
||||||
var hi = (UInt32) GetUInt16(i);
|
var hi = (UInt32) GetUInt16(i);
|
||||||
var lo = (UInt32) GetUInt16(++i);
|
var lo = (UInt32) GetUInt16(++i);
|
||||||
|
|
||||||
if (Endianness == LittleEndian)
|
|
||||||
(lo, hi) = (hi, lo);
|
|
||||||
|
|
||||||
return hi << 16 | lo;
|
return hi << 16 | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
using T = BatteryStatus;
|
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record BatteryStatus : DeviceStatus, IDcConnection
|
|
||||||
|
public record BatteryStatus : IDcConnection
|
||||||
{
|
{
|
||||||
public DcBus Dc { get; init; }
|
public DcBus Dc { get; init; }
|
||||||
public Percent Soc { get; init; }
|
public Percent Soc { get; init; }
|
||||||
public Temperature Temperature { get; init; }
|
public Temperature Temperature { get; init; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = BatteryStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record BatteryStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
|
public record CombinedStatus<T>
|
||||||
|
{
|
||||||
|
public T Combined { get; init; }
|
||||||
|
public IReadOnlyList<T> Children { get; init; }
|
||||||
|
|
||||||
|
public Boolean Available => Children.Any();
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record DcDcConverterStatus : DeviceStatus
|
|
||||||
|
public record DcDcConverterStatus
|
||||||
{
|
{
|
||||||
public DcBus Left { get; init; }
|
public DcBus Left { get; init; }
|
||||||
public DcBus Right { get; init; }
|
public DcBus Right { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = DcDcConverterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record DcDcConverterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
public abstract record DeviceStatus
|
|
||||||
{
|
|
||||||
public String DeviceType => GetType()
|
|
||||||
.Unfold(t => t.BaseType)
|
|
||||||
.First(t => t.IsAbstract)
|
|
||||||
.Name
|
|
||||||
.Replace("Status", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// public static class Program
|
|
||||||
// {
|
|
||||||
// public static void Main(string[] args)
|
|
||||||
// {
|
|
||||||
// var x = new ThreePhasePvInverterStatus
|
|
||||||
// {
|
|
||||||
// Ac = new()
|
|
||||||
// {
|
|
||||||
// Frequency = 50,
|
|
||||||
// L1 = new()
|
|
||||||
// {
|
|
||||||
// Current = 10,
|
|
||||||
// Voltage = 10,
|
|
||||||
// Phi = 0,
|
|
||||||
// },
|
|
||||||
// L2 = new()
|
|
||||||
// {
|
|
||||||
// Current = 52,
|
|
||||||
// Voltage = 220,
|
|
||||||
// Phi = Angle.Pi / 2,
|
|
||||||
// },
|
|
||||||
// L3 = new()
|
|
||||||
// {
|
|
||||||
// Current = 158,
|
|
||||||
// Voltage = 454,
|
|
||||||
// Phi = Angle.Pi / 3,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// Strings = new DcBus[]
|
|
||||||
// {
|
|
||||||
// new() { Current = 10, Voltage = 22 },
|
|
||||||
// new() { Current = 12, Voltage = 33 },
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// var s = x.ToJson();
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -1,5 +0,0 @@
|
||||||
namespace InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
|
||||||
internal class OpParallelAttribute : Attribute
|
|
||||||
{}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = Template;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record Template
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
|
|
||||||
scriptDir=$( dirname -- "$0"; )
|
|
||||||
cd "$scriptDir/.." || exit
|
|
||||||
|
|
||||||
for path in $(grep -e '\[OpParallel\]' -l *.cs)
|
|
||||||
do
|
|
||||||
file=$(basename -- "$path")
|
|
||||||
class="${file%.*}"
|
|
||||||
echo "generating $file"
|
|
||||||
sed "s/Template/$class/g" "./Generator/Template.txt" > "./$class.generated.cs"
|
|
||||||
done
|
|
|
@ -1,11 +1,11 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record MpptStatus : IDcConnection, IPvConnection
|
|
||||||
|
public record MpptStatus : IDcConnection, IPvConnection
|
||||||
{
|
{
|
||||||
public DcBus Dc { get; init; }
|
public DcBus Dc { get; init; }
|
||||||
public IReadOnlyList<DcBus> Strings { get; init; }
|
public IReadOnlyList<DcBus> Strings { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = MpptStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record MpptStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record PowerMeterStatus : DeviceStatus, IAc3Connection
|
|
||||||
|
public record PowerMeterStatus : IAc3Connection
|
||||||
{
|
{
|
||||||
public Ac3Bus Ac { get; init; }
|
public Ac3Bus Ac { get; init; }
|
||||||
}
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = PowerMeterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record PowerMeterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
|
||||||
public partial record SinglePhaseInverterStatus :
|
#pragma warning disable CS8618
|
||||||
DeviceStatus,
|
|
||||||
IAc1Connection,
|
public record SinglePhaseInverterStatus : IAc1Connection, IDcConnection
|
||||||
IDcConnection
|
|
||||||
{
|
{
|
||||||
public Ac1Bus Ac { get; init; }
|
public Ac1Bus Ac { get; init; }
|
||||||
public DcBus Dc { get; init; }
|
public DcBus Dc { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = SinglePhaseInverterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record SinglePhaseInverterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record SinglePhasePvInverterStatus :
|
|
||||||
DeviceStatus,
|
public record SinglePhasePvInverterStatus : IAc1Connection, IPvConnection
|
||||||
IAc1Connection,
|
|
||||||
IPvConnection
|
|
||||||
{
|
{
|
||||||
public Ac1Bus Ac { get; init; }
|
public Ac1Bus Ac { get; init; }
|
||||||
public IReadOnlyList<DcBus> Strings { get; init; }
|
public IReadOnlyList<DcBus> Strings { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = SinglePhasePvInverterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record SinglePhasePvInverterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="../InnovEnergy.Lib.props" />
|
<Import Project="../InnovEnergy.Lib.props" />
|
||||||
<!-- <Import Project="../../App/InnovEnergy.App.props" />-->
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../Protocols/Modbus/Modbus.csproj" />
|
<ProjectReference Include="../Protocols/Modbus/Modbus.csproj" />
|
||||||
<ProjectReference Include="../Units/Units.csproj" />
|
<ProjectReference Include="../Units/Units.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
|
||||||
<Exec Command="./Generator/generate.sh" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record ThreePhaseInverterStatus :
|
|
||||||
DeviceStatus,
|
public record ThreePhaseInverterStatus : IAc3Connection, IDcConnection
|
||||||
IAc3Connection,
|
|
||||||
IDcConnection
|
|
||||||
{
|
{
|
||||||
public Ac3Bus Ac { get; init; }
|
public Ac3Bus Ac { get; init; }
|
||||||
public DcBus Dc { get; init; }
|
public DcBus Dc { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = ThreePhaseInverterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record ThreePhaseInverterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
using InnovEnergy.Lib.StatusApi.Connections;
|
using InnovEnergy.Lib.StatusApi.Connections;
|
||||||
using InnovEnergy.Lib.StatusApi.Generator;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
namespace InnovEnergy.Lib.StatusApi;
|
||||||
|
|
||||||
[OpParallel]
|
#pragma warning disable CS8618
|
||||||
public partial record ThreePhasePvInverterStatus :
|
|
||||||
DeviceStatus,
|
public record ThreePhasePvInverterStatus : IAc3Connection, IPvConnection
|
||||||
IAc3Connection,
|
|
||||||
IPvConnection
|
|
||||||
{
|
{
|
||||||
public Ac3Bus Ac { get; init; }
|
public Ac3Bus Ac { get; init; }
|
||||||
public IReadOnlyList<DcBus> Strings { get; init; }
|
public IReadOnlyList<DcBus> Strings { get; init; }
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
using T = ThreePhasePvInverterStatus;
|
|
||||||
|
|
||||||
[GeneratedCode("generate.sh", "1")]
|
|
||||||
public partial record ThreePhasePvInverterStatus
|
|
||||||
{
|
|
||||||
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
|
|
||||||
public static T operator |(T left, T right) => OpParallel(left, right);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
using static DecimalMath.DecimalEx;
|
using static DecimalMath.DecimalEx;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Units.Composite;
|
namespace InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
public record Ac3Bus
|
public record Ac3Bus
|
||||||
{
|
{
|
||||||
public AcPhase L1 { get; init; }
|
public AcPhase L1 { get; init; }
|
||||||
public AcPhase L2 { get; init; }
|
public AcPhase L2 { get; init; }
|
||||||
public AcPhase L3 { get; init; }
|
public AcPhase L3 { get; init; }
|
||||||
public Frequency Frequency { get; init; }
|
public Frequency Frequency { get; init; }
|
||||||
|
|
||||||
public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower;
|
public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower;
|
||||||
public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower;
|
public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower;
|
||||||
public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower;
|
public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower;
|
||||||
public Angle Phi => ATan2(ReactivePower, ActivePower);
|
public Angle Phi => ATan2(ReactivePower, ActivePower);
|
||||||
|
|
||||||
public static Ac3Bus operator |(Ac3Bus left, Ac3Bus right) => OpParallel(left, right);
|
|
||||||
private static readonly Func<Ac3Bus, Ac3Bus, Ac3Bus> OpParallel = "|".CreateBinaryOpForProps<Ac3Bus>();
|
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ public record AcPhase : IBus
|
||||||
init => _Current = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative");
|
init => _Current = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Angle Phi { get; init; }
|
public Angle Phi { get; init; }
|
||||||
|
|
||||||
public ApparentPower ApparentPower => Voltage.Value * Current.Value ;
|
public ApparentPower ApparentPower => Voltage.Value * Current.Value ;
|
||||||
public Power ActivePower => ApparentPower.Value * PowerFactor;
|
public Power ActivePower => ApparentPower.Value * PowerFactor;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Units.Composite;
|
namespace InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
public record DcBus : IBus
|
public record DcBus : IBus
|
||||||
|
@ -8,7 +6,4 @@ public record DcBus : IBus
|
||||||
public Current Current { get; init; }
|
public Current Current { get; init; }
|
||||||
|
|
||||||
public Power Power => Current * Voltage;
|
public Power Power => Current * Voltage;
|
||||||
|
|
||||||
public static DcBus operator |(DcBus left, DcBus right) => OpParallel(left, right);
|
|
||||||
private static readonly Func<DcBus, DcBus, DcBus> OpParallel = "|".CreateBinaryOpForProps<DcBus>();
|
|
||||||
}
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
||||||
|
#define Generate
|
||||||
|
|
||||||
|
using static System.Math;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Units;
|
||||||
|
|
||||||
|
using T = Percent;
|
||||||
|
|
||||||
|
[GeneratedCode("generate.sh", "1")]
|
||||||
|
[JsonConverter(typeof(PercentConverter))]
|
||||||
|
public readonly partial struct Percent
|
||||||
|
{
|
||||||
|
public Decimal Value { get; }
|
||||||
|
public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit;
|
||||||
|
|
||||||
|
// scalar multiplication
|
||||||
|
|
||||||
|
public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value);
|
||||||
|
public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value);
|
||||||
|
public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar);
|
||||||
|
|
||||||
|
// addition
|
||||||
|
|
||||||
|
public static T operator +(T left, T right) => new T(left.Value + right.Value);
|
||||||
|
public static T operator -(T left, T right) => new T(left.Value - right.Value);
|
||||||
|
public static T operator -(T t) => new T(-t.Value);
|
||||||
|
|
||||||
|
// compare
|
||||||
|
|
||||||
|
public static Boolean operator ==(T left, T right) => left.Value == right.Value;
|
||||||
|
public static Boolean operator !=(T left, T right) => left.Value != right.Value;
|
||||||
|
public static Boolean operator > (T left, T right) => left.Value > right.Value;
|
||||||
|
public static Boolean operator < (T left, T right) => left.Value < right.Value;
|
||||||
|
public static Boolean operator >=(T left, T right) => left.Value >= right.Value;
|
||||||
|
public static Boolean operator <=(T left, T right) => left.Value <= right.Value;
|
||||||
|
|
||||||
|
// conversion
|
||||||
|
|
||||||
|
public static implicit operator T(Decimal d) => new T(d);
|
||||||
|
public static implicit operator T(Double d) => new T((Decimal)d);
|
||||||
|
public static implicit operator T(Int32 i) => new T(i);
|
||||||
|
public static implicit operator Decimal(T t) => t.Value;
|
||||||
|
|
||||||
|
// equality
|
||||||
|
|
||||||
|
public Boolean Equals(T other) => Value == other.Value;
|
||||||
|
public override Boolean Equals(Object? obj) => obj is T other && Equals(other);
|
||||||
|
public override Int32 GetHashCode() => Value.GetHashCode();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class PercentConverter : JsonConverter<Percent>
|
||||||
|
{
|
||||||
|
public override Percent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
return new Percent(reader.GetDecimal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Percent value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits);
|
||||||
|
|
||||||
|
writer.WriteNumberValue(rounded);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +1,7 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Units;
|
namespace InnovEnergy.Lib.Units;
|
||||||
|
|
||||||
public static class Units
|
public static class Units
|
||||||
{
|
{
|
||||||
static Units()
|
|
||||||
{
|
|
||||||
JsonConverters = typeof(Units)
|
|
||||||
.Assembly
|
|
||||||
.GetTypes()
|
|
||||||
.Where(t => t.IsAssignableTo(typeof(JsonConverter)))
|
|
||||||
.Select(Activator.CreateInstance)
|
|
||||||
.Cast<JsonConverter>()
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static IReadOnlyList<JsonConverter> JsonConverters { get; }
|
|
||||||
|
|
||||||
public static Byte DisplaySignificantDigits { get; set; } = 3;
|
public static Byte DisplaySignificantDigits { get; set; } = 3;
|
||||||
public static Byte JsonSignificantDigits { get; set; } = 3;
|
public static Byte JsonSignificantDigits { get; set; } = 3;
|
||||||
|
|
||||||
|
@ -31,4 +15,89 @@ public static class Units
|
||||||
public static Angle Rad (this Decimal value) => value;
|
public static Angle Rad (this Decimal value) => value;
|
||||||
public static Temperature Celsius(this Decimal value) => value;
|
public static Temperature Celsius(this Decimal value) => value;
|
||||||
public static Energy KWh (this Decimal value) => value;
|
public static Energy KWh (this Decimal value) => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Prefixes
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyList<String> Big = new[]
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"k",
|
||||||
|
"M",
|
||||||
|
"G",
|
||||||
|
"T",
|
||||||
|
"P",
|
||||||
|
"E",
|
||||||
|
"Y",
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly IReadOnlyList<String> Small = new[]
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"m",
|
||||||
|
"µ",
|
||||||
|
"n",
|
||||||
|
"p",
|
||||||
|
"f",
|
||||||
|
"a",
|
||||||
|
"z",
|
||||||
|
"y",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static String TestGetPrefix(Double v, String unit)
|
||||||
|
{
|
||||||
|
if (v == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
var log10 = Math.Log10(v / 10);
|
||||||
|
var l = (Int32)Math.Floor(log10 / 3);
|
||||||
|
var lookUp = l > 0 ? Big : Small;
|
||||||
|
var i = Math.Abs(l);
|
||||||
|
|
||||||
|
return $"{v / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String TestGetPrefix(Decimal v, String unit)
|
||||||
|
{
|
||||||
|
if (v == 0m)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
var d = (Double)v;
|
||||||
|
var log10 = Math.Log10(d / 10);
|
||||||
|
var l = (Int32)Math.Floor(log10 / 3);
|
||||||
|
var lookUp = l > 0 ? Big : Small;
|
||||||
|
var i = Math.Abs(l);
|
||||||
|
|
||||||
|
return $"{d / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String TestGetPrefix2(Decimal v, String unit)
|
||||||
|
{
|
||||||
|
if (v == 0m)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
var a = Math.Abs(v);
|
||||||
|
var s = Math.Sign(v);
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
while (a >= 10000m)
|
||||||
|
{
|
||||||
|
a /= 1000;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (a < 10m)
|
||||||
|
{
|
||||||
|
a *= 1000;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lookUp = i >= 0 ? Big : Small;
|
||||||
|
|
||||||
|
var r = Decimal.Floor(a * 10m) / 10m;
|
||||||
|
|
||||||
|
return $"{r*s} {lookUp[Math.Abs(i)]}{unit}";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection;
|
||||||
|
|
||||||
|
public abstract class DataMember : Member
|
||||||
|
{
|
||||||
|
public abstract Object? Get();
|
||||||
|
public abstract void Set(Object value);
|
||||||
|
|
||||||
|
public abstract Boolean IsWriteable { get; }
|
||||||
|
public abstract Boolean IsReadable { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DataMembers
|
||||||
|
{
|
||||||
|
public static IEnumerable<DataMember> OfInstance<T>(T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance.GetDataMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<DataMember> GetDataMembers<T>(this T instance) where T : notnull
|
||||||
|
{
|
||||||
|
var fields = instance.GetFields();
|
||||||
|
var props = instance.GetProperties();
|
||||||
|
|
||||||
|
return fields.Concat<DataMember>(props);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using static System.Reflection.BindingFlags;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection;
|
||||||
|
|
||||||
|
public class Field : DataMember
|
||||||
|
{
|
||||||
|
private readonly Object? _Instance;
|
||||||
|
private readonly FieldInfo _FieldInfo;
|
||||||
|
|
||||||
|
public override String Name => _FieldInfo.Name;
|
||||||
|
public override Type Type => _FieldInfo.FieldType;
|
||||||
|
|
||||||
|
public override Boolean IsPublic => _FieldInfo.IsPublic;
|
||||||
|
public override Boolean IsPrivate => _FieldInfo.IsPrivate;
|
||||||
|
public override Boolean IsStatic => _FieldInfo.IsStatic;
|
||||||
|
|
||||||
|
public override Boolean IsWriteable => true;
|
||||||
|
public override Boolean IsReadable => true;
|
||||||
|
|
||||||
|
public override IEnumerable<Attribute> Attributes => _FieldInfo
|
||||||
|
.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<Attribute>();
|
||||||
|
|
||||||
|
internal Field(Object? instance, FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
_Instance = instance;
|
||||||
|
_FieldInfo = fieldInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Object? Get() => _FieldInfo.GetValue(_Instance) ;
|
||||||
|
public override void Set(Object value) => _FieldInfo.SetValue(_Instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Fields
|
||||||
|
{
|
||||||
|
public static IEnumerable<Field> GetFields<T>(this T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance
|
||||||
|
.GetType()
|
||||||
|
.GetFields(Instance | Static | Public | NonPublic)
|
||||||
|
.Select(fi => new Field(fi.IsStatic ? null : instance, fi));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Field> OfInstance<T>(T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance.GetFields();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection;
|
||||||
|
|
||||||
|
public abstract class Member
|
||||||
|
{
|
||||||
|
public abstract String Name { get; }
|
||||||
|
public abstract Type Type { get; }
|
||||||
|
|
||||||
|
public abstract Boolean IsPublic { get; }
|
||||||
|
public abstract Boolean IsPrivate { get; }
|
||||||
|
public abstract Boolean IsStatic { get; }
|
||||||
|
|
||||||
|
public abstract IEnumerable<Attribute> Attributes { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Members
|
||||||
|
{
|
||||||
|
public static IEnumerable<Member> OfInstance<T>(T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance.GetMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Member> GetMembers<T>(this T instance) where T : notnull
|
||||||
|
{
|
||||||
|
var fields = instance.GetFields();
|
||||||
|
var props = instance.GetProperties();
|
||||||
|
var methods = instance.GetMethods();
|
||||||
|
|
||||||
|
return fields
|
||||||
|
.Concat<Member>(props)
|
||||||
|
.Concat(methods);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using static System.Reflection.BindingFlags;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection;
|
||||||
|
|
||||||
|
public class Method : Member
|
||||||
|
{
|
||||||
|
private readonly MethodInfo _MethodInfo;
|
||||||
|
private readonly Object? _Instance;
|
||||||
|
|
||||||
|
public override Boolean IsPublic => _MethodInfo.IsPublic;
|
||||||
|
public override Boolean IsPrivate => _MethodInfo.IsPrivate;
|
||||||
|
public override Boolean IsStatic => _MethodInfo.IsStatic;
|
||||||
|
|
||||||
|
public override String Name => _MethodInfo.Name;
|
||||||
|
public override Type Type => _MethodInfo.ReturnType;
|
||||||
|
|
||||||
|
public override IEnumerable<Attribute> Attributes => _MethodInfo.GetCustomAttributes();
|
||||||
|
|
||||||
|
public IEnumerable<Parameter> Parameters => _MethodInfo
|
||||||
|
.GetParameters()
|
||||||
|
.Select(i => new Parameter(i));
|
||||||
|
|
||||||
|
internal Method(Object? instance, MethodInfo fieldInfo)
|
||||||
|
{
|
||||||
|
_MethodInfo = fieldInfo;
|
||||||
|
_Instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object? Invoke(params Object[] parameters)
|
||||||
|
{
|
||||||
|
return _MethodInfo.Invoke(_Instance, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Methods
|
||||||
|
{
|
||||||
|
public static IEnumerable<Method> GetMethods<T>(this T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return typeof(T)
|
||||||
|
.GetMethods(Instance | Static | Public | NonPublic)
|
||||||
|
.Select(mi => new Method(mi.IsStatic ? null : instance, mi));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Method> OfInstance<T>(T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance.GetMethods();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection
|
||||||
|
{
|
||||||
|
public class Parameter
|
||||||
|
{
|
||||||
|
private readonly ParameterInfo _ParameterInfo;
|
||||||
|
|
||||||
|
internal Parameter(ParameterInfo parameterInfo) => _ParameterInfo = parameterInfo;
|
||||||
|
|
||||||
|
public Type Type => _ParameterInfo.ParameterType;
|
||||||
|
public String Name => _ParameterInfo.Name ?? "<no name>";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using static System.Reflection.BindingFlags;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Utils.Reflection
|
||||||
|
{
|
||||||
|
public class Property : DataMember
|
||||||
|
{
|
||||||
|
private readonly Object? _Instance;
|
||||||
|
private readonly PropertyInfo _PropertyInfo;
|
||||||
|
|
||||||
|
internal Property(Object? instance, PropertyInfo propertyInfo)
|
||||||
|
{
|
||||||
|
_Instance = instance;
|
||||||
|
_PropertyInfo = propertyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Boolean IsWriteable => _PropertyInfo.CanWrite;
|
||||||
|
public override Boolean IsReadable => _PropertyInfo.CanRead;
|
||||||
|
public override String Name => _PropertyInfo.Name;
|
||||||
|
public override Type Type => _PropertyInfo.PropertyType;
|
||||||
|
|
||||||
|
public override Boolean IsPublic => _PropertyInfo.IsPublic();
|
||||||
|
public override Boolean IsPrivate => _PropertyInfo.IsPrivate();
|
||||||
|
public override Boolean IsStatic => _PropertyInfo.IsStatic();
|
||||||
|
|
||||||
|
public override IEnumerable<Attribute> Attributes => GetAttributes<Attribute>();
|
||||||
|
|
||||||
|
public override Object? Get() => _PropertyInfo.GetValue(_Instance);
|
||||||
|
public override void Set(Object value) => _PropertyInfo.SetValue(_Instance, value);
|
||||||
|
|
||||||
|
public IEnumerable<T> GetAttributes<T> () where T : Attribute => _PropertyInfo
|
||||||
|
.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<T>();
|
||||||
|
|
||||||
|
public Boolean HasAttribute<T> () where T : Attribute => GetAttributes<T>().Any();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Properties
|
||||||
|
{
|
||||||
|
public static IEnumerable<Property> GetProperties<T>(this T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance
|
||||||
|
.GetType()
|
||||||
|
.GetProperties(Instance | Static | Public | NonPublic)
|
||||||
|
.Where(p => p.GetIndexParameters().Length == 0) // no indexers please
|
||||||
|
.Select(pi => new Property(pi.IsStatic() ? null : instance, pi));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Property> OfInstance<T>(T instance) where T : notnull
|
||||||
|
{
|
||||||
|
return instance.GetProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static class PropertyInfoExtensions
|
||||||
|
{
|
||||||
|
public static Boolean IsStatic(this PropertyInfo i)
|
||||||
|
{
|
||||||
|
var getter = i.GetMethod;
|
||||||
|
var setter = i.SetMethod;
|
||||||
|
|
||||||
|
return (getter is not null && getter.IsStatic)
|
||||||
|
|| (setter is not null && setter.IsStatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean IsPublic(this PropertyInfo i)
|
||||||
|
{
|
||||||
|
var getter = i.GetMethod;
|
||||||
|
var setter = i.SetMethod;
|
||||||
|
|
||||||
|
return (getter is not null && getter.IsPublic)
|
||||||
|
|| (setter is not null && setter.IsPublic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean IsPrivate(this PropertyInfo i)
|
||||||
|
{
|
||||||
|
var getter = i.GetMethod;
|
||||||
|
var setter = i.SetMethod;
|
||||||
|
|
||||||
|
return (getter is not null && getter.IsPrivate)
|
||||||
|
|| (setter is not null && setter.IsPrivate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,8 +23,8 @@ public static class WebServer
|
||||||
listener.Start();
|
listener.Start();
|
||||||
|
|
||||||
var handlers404 = handlers
|
var handlers404 = handlers
|
||||||
.Concat(Default.HttpResponse)
|
.Concat(Default.HttpResponse)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -34,9 +34,9 @@ public static class WebServer
|
||||||
var request = context.ConvertRequest();
|
var request = context.ConvertRequest();
|
||||||
|
|
||||||
var response = handlers404
|
var response = handlers404
|
||||||
.Select(f => f(request))
|
.Select(f => f(request))
|
||||||
.SkipWhile(r => r == null)
|
.SkipWhile(r => r == null)
|
||||||
.First()!;
|
.First()!;
|
||||||
|
|
||||||
context.SendResponse(response);
|
context.SendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||||
|
|
||||||
|
public static class DcControlRegisters
|
||||||
|
{
|
||||||
|
public const UInt16 Date = 1001;
|
||||||
|
public const UInt16 Time = 1003;
|
||||||
|
public const UInt16 IpAddress = 1005;
|
||||||
|
public const UInt16 Subnet = 1007;
|
||||||
|
public const UInt16 Gateway = 1009;
|
||||||
|
public const UInt16 ResetParamToDefault = 1011;
|
||||||
|
public const UInt16 TimeoutCommunication = 1017;
|
||||||
|
public const UInt16 RestartFlag = 1018;
|
||||||
|
public const UInt16 ConnectedSystemConfig = 1019;
|
||||||
|
public const UInt16 UpdateSwTrigger = 1027;
|
||||||
|
public const UInt16 AutomaticSwUpdate = 1028;
|
||||||
|
public const UInt16 CustomerValuesSaveReset = 1029;
|
||||||
|
public const UInt16 SerialNumberSystemControl = 2001;
|
||||||
|
public const UInt16 SerialNumberDcDc = 2003;
|
||||||
|
public const UInt16 MaterialNumberDcDc = 2005;
|
||||||
|
public const UInt16 PowerStageOperation = 4001;
|
||||||
|
public const UInt16 ResetsAlarmAndWarning = 4003;
|
||||||
|
public const UInt16 SlaveAddress = 4008;
|
||||||
|
public const UInt16 SlaveAlarmPolicy = 4009;
|
||||||
|
public const UInt16 SubSlaveAddress = 4011;
|
||||||
|
public const UInt16 ModbusSlaveId = 4012;
|
||||||
|
public const UInt16 MaximumBatteryVoltage = 4101;
|
||||||
|
public const UInt16 MinimumBatteryVoltage = 4102;
|
||||||
|
public const UInt16 MaximumBatteryVoltageR = 4103; // same as the two previous ones just Different resolution// not sure
|
||||||
|
public const UInt16 MinimumBatteryVoltageR = 4104; // same as the two previous ones just Different resolution// not sure
|
||||||
|
public const UInt16 MaximumBatteryChargingCurrent = 4107;
|
||||||
|
public const UInt16 MaximumBatteryDischargingCurrent = 4110;
|
||||||
|
public const UInt16 MaximumVoltageOfVcc = 4113;
|
||||||
|
public const UInt16 MaximumCurrentOfVcc = 4116;
|
||||||
|
public const UInt16 StartCurrentOfVcc = 4119;
|
||||||
|
public const UInt16 MaximalPowerAtDc = 4122;
|
||||||
|
public const UInt16 MaximumVoltageAlarmThreshold = 4125;
|
||||||
|
public const UInt16 MinimumVoltageAlarmThreshold = 4128;
|
||||||
|
|
||||||
|
//DcDc operation only
|
||||||
|
public const UInt16 BatteryCurrentSet = 4501;
|
||||||
|
public const UInt16 DynamicCurrentPerMillisecond = 4502;
|
||||||
|
|
||||||
|
public const UInt16 DcLinkControlMode = 4505;
|
||||||
|
public const UInt16 ReferenceVoltage = 4506;
|
||||||
|
public const UInt16 UpperVoltageWindow = 4507;
|
||||||
|
public const UInt16 LowerVoltageWindow = 4508;
|
||||||
|
public const UInt16 VoltageDeadBand = 4509;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||||
|
|
||||||
|
public record TruConvertDcControl
|
||||||
|
{
|
||||||
|
public UInt32 Date { get; init;}
|
||||||
|
public UInt32 Time { get; init;}
|
||||||
|
public UInt32 IpAddress { get; init;} //= 0x C0A80102;
|
||||||
|
public UInt32 Subnet { get; init;} //= 0x FFFFFF00;
|
||||||
|
public UInt32 Gateway { get; init;} //= 0x C0A80102;
|
||||||
|
public Boolean ResetParamToDefault { get; init;} = false ; // Coil
|
||||||
|
public TimeSpan TimeoutForCommunication { get; init;} = DefaultCommunicationTimeOut;
|
||||||
|
public Boolean RestartFlag { get; init;} = false ; // Coil
|
||||||
|
public SystemConfig ConnectedSystemConfig { get; init;} = SystemConfig.NoConfig ;
|
||||||
|
public UInt16 UpdateSwTrigger { get; init;} = 0 ;
|
||||||
|
public UInt16 AutomaticSwUpdate { get; init;} = 0 ;
|
||||||
|
public UInt16 CustomerValuesSaveReset { get; init;} = 0 ;
|
||||||
|
public UInt32 SerialNumberSystemControl { get; init;}
|
||||||
|
public UInt32 SerialNumberDcDc { get; init;}
|
||||||
|
public UInt32 MaterialNumberDcDc { get; init;}
|
||||||
|
public Boolean PowerStageEnable { get; init;} = true; //Coil
|
||||||
|
public Boolean ResetsAlarmAndWarning { get; init;} = false; //Coil
|
||||||
|
public UInt16 SlaveAddress { get; init;} = Slave.Broadcast;
|
||||||
|
public UInt16 SlaveAlarmPolicy { get; init;} = 0; // this is must be a an enum
|
||||||
|
public UInt16 SubSlaveAddress { get; init;} = 0;
|
||||||
|
public Boolean ModbusSlaveId { get; init;} = false; // Coil
|
||||||
|
public Decimal MaximumBatteryVoltage { get; init;} = 0; // resolution 0.01
|
||||||
|
public Decimal MinimumBatteryVoltage { get; init;} = 0; // resolution 0.01
|
||||||
|
public Decimal MaximumBatteryChargingCurrent { get; init;} = 0; // resolution 0.1
|
||||||
|
public Decimal MaximumBatteryDischargingCurrent { get; init;} = 0; // resolution 0.1
|
||||||
|
public Decimal MaximalPowerAtDc { get; init;} = 0;
|
||||||
|
public Decimal MaximumVoltageAlarmThreshold { get; init;} = 55; // resolution 0.1
|
||||||
|
public Decimal MinimumVoltageAlarmThreshold { get; init;} = 0; // resolution 0.1
|
||||||
|
public Decimal BatteryCurrentSet { get; init;} = 0; // resolution 1.0
|
||||||
|
public Decimal DynamicCurrentPerMillisecond { get; init;} = 0; // resolution : 0.01
|
||||||
|
public Decimal DcLinkControlMode { get; init;} = 0; // Parameter aktiviert/deaktiviert "DC link voltage droop mode"
|
||||||
|
public Decimal ReferenceVoltage { get; init;} = 800; // resolution : 0.1
|
||||||
|
public Decimal UpperVoltageWindow { get; init;} = 40; // resolution : 0.1
|
||||||
|
public Decimal LowerVoltageWindow { get; init;} = 40; // resolution : 0.1
|
||||||
|
public Decimal VoltageDeadBand { get; init;} = 0; // resolution : 0.1
|
||||||
|
|
||||||
|
private static readonly TimeSpan DefaultCommunicationTimeOut = TimeSpan.FromMinutes(10);
|
||||||
|
}
|
Loading…
Reference in New Issue