Update Status to inherit from Status Api
This commit is contained in:
parent
5affecda55
commit
175f11fccf
|
@ -26,7 +26,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VenusLogger", "app/VenusLog
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meiringen", "app/Meiringen/Meiringen.csproj", "{4C816420-FD19-47BF-87FE-599210CA8384}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeterDriver", "app\EmuMeterDriver\EmuMeterDriver.csproj", "{F65F33B0-3522-4008-8D1E-47EF8E4C7AC7}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeterDriver", "app/EmuMeterDriver/EmuMeterDriver.csproj", "{F65F33B0-3522-4008-8D1E-47EF8E4C7AC7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BmsTunnel", "app/BmsTunnel/BmsTunnel.csproj", "{40B45363-BE34-420B-8F87-775EE6EE3513}"
|
||||
EndProject
|
||||
|
@ -34,21 +34,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{145597B4-3E3
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "lib\S3\S3.csproj", "{C3639841-13F4-4F24-99C6-7D965593BF89}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "lib/S3/S3.csproj", "{C3639841-13F4-4F24-99C6-7D965593BF89}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{D846B46B-46FF-4EF7-9B9D-DDBEF9533C56}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{46DE03C4-52D1-47AA-8E60-8BB15361D723}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsController", "app\CsController\CsController.csproj", "{72DBBE42-A09F-43C0-9613-331039857056}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsController", "app/CsController/CsController.csproj", "{72DBBE42-A09F-43C0-9613-331039857056}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBatteryDbus", "app\TestBatteryDbus\TestBatteryDbus.csproj", "{CB226D69-DD28-4AAF-8BBE-2488E37A0B8D}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "app/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "app\SaliMax\SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiFeeder", "app/GuiFeeder/GuiFeeder.csproj", "{5B953EC4-51F3-4A0A-ADF5-BAA3D1570CB2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiFeeder", "app\GuiFeeder\GuiFeeder.csproj", "{5B953EC4-51F3-4A0A-ADF5-BAA3D1570CB2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "lib\StatusApi\StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devices", "Devices", "{4931A385-24DC-4E78-BFF4-356F8D6D5183}"
|
||||
EndProject
|
||||
|
@ -58,38 +56,36 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Victron", "Victron", "{BD8C
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Trumpf", "Trumpf", "{DDDBEFD0-5DEA-4C7C-A9F2-FDB4636CF092}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvert", "lib\Devices\Trumpf\TruConvert\TruConvert.csproj", "{EF46CF7B-823E-4CB7-966F-EDDC144C7954}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvert", "lib/Devices/Trumpf/TruConvert/TruConvert.csproj", "{EF46CF7B-823E-4CB7-966F-EDDC144C7954}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertAc", "lib\Devices\Trumpf\TruConvertAc\TruConvertAc.csproj", "{1F4B445E-459E-44CD-813E-6D725EBB81E8}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertAc", "lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj", "{1F4B445E-459E-44CD-813E-6D725EBB81E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertDc", "lib\Devices\Trumpf\TruConvertDc\TruConvertDc.csproj", "{F6F29829-C31A-4994-A698-E441BEA631C6}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertDc", "lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj", "{F6F29829-C31A-4994-A698-E441BEA631C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DBus", "lib\Protocols\DBus\DBus.csproj", "{8C3C620A-087D-4DD6-B493-A47FC643F8DC}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DBus", "lib/Protocols/DBus/DBus.csproj", "{8C3C620A-087D-4DD6-B493-A47FC643F8DC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus", "lib\Protocols\Modbus\Modbus.csproj", "{E4AE6A33-0DEB-48EB-9D57-C0C7C63FC267}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus", "lib/Protocols/Modbus/Modbus.csproj", "{E4AE6A33-0DEB-48EB-9D57-C0C7C63FC267}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VeDBus", "lib\Victron\VeDBus\VeDBus.csproj", "{50B26E29-1B99-4D07-BCA5-359CD550BBAA}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VeDBus", "lib/Victron/VeDBus/VeDBus.csproj", "{50B26E29-1B99-4D07-BCA5-359CD550BBAA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VictronVRM", "lib\Victron\VictronVRM\VictronVRM.csproj", "{FE05DF69-B5C7-4C2E-8FB9-7776441A7622}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VictronVRM", "lib/Victron/VictronVRM/VictronVRM.csproj", "{FE05DF69-B5C7-4C2E-8FB9-7776441A7622}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ampt", "lib\Devices\AMPT\Ampt.csproj", "{77AF3A64-2878-4150-BCD0-F16530783165}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ampt", "lib/Devices/AMPT/Ampt.csproj", "{77AF3A64-2878-4150-BCD0-F16530783165}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Battery48TL", "lib\Devices\Battery48TL\Battery48TL.csproj", "{1C3F443A-B339-4B08-80E6-8A84817FFEC9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{89A3E29C-4E57-47FE-A800-12AC68418264} = {89A3E29C-4E57-47FE-A800-12AC68418264}
|
||||
EndProjectSection
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Battery48TL", "lib/Devices/Battery48TL/Battery48TL.csproj", "{1C3F443A-B339-4B08-80E6-8A84817FFEC9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeter", "lib\Devices\EmuMeter\EmuMeter.csproj", "{152A4168-F612-493C-BBEA-8EB26E6E2D34}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeter", "lib/Devices/EmuMeter/EmuMeter.csproj", "{152A4168-F612-493C-BBEA-8EB26E6E2D34}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "lib\Utils\Utils.csproj", "{89A3E29C-4E57-47FE-A800-12AC68418264}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "lib/Utils/Utils.csproj", "{89A3E29C-4E57-47FE-A800-12AC68418264}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adam6060", "lib\Devices\Adam6060\Adam6060.csproj", "{4AFDB799-E6A4-4DCA-8B6D-8C0F98398461}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adam6060", "lib/Devices/Adam6060/Adam6060.csproj", "{4AFDB799-E6A4-4DCA-8B6D-8C0F98398461}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "lib\Channels\Channels.csproj", "{AF7E8DCA-8D48-498E-AB3D-208061B244DC}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "lib/Channels/Channels.csproj", "{AF7E8DCA-8D48-498E-AB3D-208061B244DC}"
|
||||
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
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FossilTui", "app/FossilTui/FossilTui.csproj", "{C40264BB-C834-4C48-9B3F-6BEF8F37C0ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FossilTui", "app\FossilTui\FossilTui.csproj", "{C40264BB-C834-4C48-9B3F-6BEF8F37C0ED}"
|
||||
EndProject
|
||||
|
||||
Global
|
||||
|
|
|
@ -6,19 +6,15 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\lib\DBus\DBus.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Devices\EmuMeter\EmuMeter.csproj" />
|
||||
<ProjectReference Include="..\..\lib\EmuMeter\EmuMeter.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Modbus\Modbus.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Protocols\DBus\DBus.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Protocols\Modbus\Modbus.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Utils\Utils.csproj" />
|
||||
<ProjectReference Include="..\..\lib\VeDBus\VeDBus.csproj" />
|
||||
<ProjectReference Include="..\..\lib\Victron\VeDBus\VeDBus.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliWrap" Version="3.5.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -15,12 +15,16 @@
|
|||
<ProjectReference Include="../../lib/Devices/Trumpf/TruConvert/TruConvert.csproj" />
|
||||
<ProjectReference Include="../../lib/StatusApi/StatusApi.csproj" />
|
||||
<ProjectReference Include="../../lib/Utils/Utils.csproj" />
|
||||
<PackageReference Include="CliWrap" Version="3.5.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||
<ProjectReference Include="..\..\lib\Time\Time.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="src\StatusLog" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
dotnet_version='net6.0'
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
echo -e "\n============================ Build ============================\n"
|
||||
|
@ -11,21 +10,28 @@ echo -e "\n============================ Build ============================\n"
|
|||
dotnet publish \
|
||||
./SaliMax.csproj \
|
||||
-c Release \
|
||||
-r linux-arm
|
||||
-r linux-x64
|
||||
|
||||
echo -e "\n============================ Deploy ============================\n"
|
||||
|
||||
rsync -v \
|
||||
./bin/Release/$dotnet_version/linux-arm/publish/* \
|
||||
debian@10.2.1.87:~/salimax
|
||||
./bin/Release/$dotnet_version/linux-x64/publish/* \
|
||||
ie-entwicklung@10.2.3.49:~/salimax
|
||||
|
||||
echo -e "\n============================ Run ============================\n"
|
||||
|
||||
# debian@10.2.1.87:~/salimax
|
||||
|
||||
echo -e "\n============================ Restart Salimax sevice ============================\n"
|
||||
|
||||
ssh -tt \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=2 \
|
||||
debian@10.2.1.87 \
|
||||
'~/salimax/SaliMax' \
|
||||
2>/dev/null
|
||||
ie-entwicklung@10.2.3.49 \
|
||||
sudo systemctl restart salimax.service
|
||||
|
||||
|
||||
echo -e "\n============================ Print service output ============================\n"
|
||||
|
||||
ssh -tt \
|
||||
ie-entwicklung@10.2.3.49 \
|
||||
journalctl -f -u salimax.service
|
||||
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ public static class Control
|
|||
public static Decimal ControlInverterPower(this StatusRecord status, Decimal targetInverterPower)
|
||||
{
|
||||
var s = status.InverterStatus!;
|
||||
var totalInverterAcPower = s.PowerAcL1 + s.PowerAcL2 + s.PowerAcL3;
|
||||
var totalInverterAcPower = s.Ac.ActivePower;
|
||||
|
||||
return ControlPower(totalInverterAcPower, targetInverterPower,status.SalimaxConfig!.PConstant);
|
||||
}
|
||||
|
||||
public static Decimal ControlBatteryPower(this StatusRecord status, Decimal targetBatteryPower)
|
||||
public static Decimal ControlBatteryPower(this StatusRecord status, Decimal targetBatteryPower, UInt16 i = 0) //this will use the avg batteries
|
||||
{
|
||||
return ControlPower(status.BatteryStatus!.Power, targetBatteryPower, status.SalimaxConfig!.PConstant);
|
||||
return ControlPower(status.BatteriesStatus![i].Dc.Power, targetBatteryPower, status.SalimaxConfig!.PConstant);
|
||||
}
|
||||
|
||||
public static Decimal ControlLowBatterySoc(this StatusRecord status)
|
||||
|
@ -31,14 +31,14 @@ public static class Control
|
|||
public static Decimal LowerLimit(params Decimal[] deltas) => deltas.Max();
|
||||
public static Decimal UpperLimit(params Decimal[] deltas) => deltas.Min();
|
||||
|
||||
private static Decimal HoldMinSocCurve(StatusRecord s)
|
||||
private static Decimal HoldMinSocCurve(StatusRecord s, UInt16 i = 0)
|
||||
{
|
||||
// TODO: explain LowSOC curve
|
||||
|
||||
var a = -2 * s.SalimaxConfig!.SelfDischargePower / s.SalimaxConfig.HoldSocZone;
|
||||
var b = -a * (s.SalimaxConfig.MinSoc + s.SalimaxConfig.HoldSocZone);
|
||||
|
||||
return s.BatteryStatus!.Soc * a + b;
|
||||
return s.BatteriesStatus![i].Soc * a + b; //this will use the avg batteries
|
||||
}
|
||||
|
||||
private static Decimal ControlPower(Decimal measurement, Decimal target, Decimal p)
|
||||
|
|
|
@ -18,7 +18,7 @@ public static class Controller
|
|||
|
||||
private static readonly TimeSpan CommunicationTimeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
private static readonly Int16 MaxmimumAllowedBatteryTemp = 315;
|
||||
public static readonly Int16 MaxmimumAllowedBatteryTemp = 315;
|
||||
|
||||
private static UInt16 _numberOfInverters;
|
||||
|
||||
|
@ -71,7 +71,7 @@ public static class Controller
|
|||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 9,
|
||||
{
|
||||
SaliMaxRelayStatus.K1: Open, SaliMaxRelayStatus.K2: Open, SaliMaxRelayStatus.K3: Closed,
|
||||
SaliMaxRelayStatus.K1: Closed, SaliMaxRelayStatus.K2: Open, SaliMaxRelayStatus.K3: Open,
|
||||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 10,
|
||||
{
|
||||
|
@ -79,11 +79,11 @@ public static class Controller
|
|||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 11,
|
||||
{
|
||||
SaliMaxRelayStatus.K1: Open, SaliMaxRelayStatus.K2: Closed, SaliMaxRelayStatus.K3: Closed,
|
||||
SaliMaxRelayStatus.K1: Closed, SaliMaxRelayStatus.K2: Closed, SaliMaxRelayStatus.K3: Open,
|
||||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 12,
|
||||
{
|
||||
SaliMaxRelayStatus.K1: Closed, SaliMaxRelayStatus.K2: Open, SaliMaxRelayStatus.K3: Open,
|
||||
SaliMaxRelayStatus.K1: Open, SaliMaxRelayStatus.K2: Open, SaliMaxRelayStatus.K3: Closed,
|
||||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 13,
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ public static class Controller
|
|||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 14,
|
||||
{
|
||||
SaliMaxRelayStatus.K1: Closed, SaliMaxRelayStatus.K2: Closed, SaliMaxRelayStatus.K3: Open,
|
||||
SaliMaxRelayStatus.K1: Open, SaliMaxRelayStatus.K2: Closed, SaliMaxRelayStatus.K3: Closed,
|
||||
InverterStatus.AcDcActiveGridType: AcDcGridType.GridTied400V50Hz
|
||||
} => 15,
|
||||
{
|
||||
|
@ -140,7 +140,10 @@ public static class Controller
|
|||
|
||||
public static ControlRecord SaliMaxControl(StatusRecord statusRecord)
|
||||
{
|
||||
var resetInverterAlarm = CheckInverterAlarms(statusRecord);
|
||||
var currentSaliMaxState = GetSaliMaxState(statusRecord);
|
||||
|
||||
UInt16 acSlaveId = 1;
|
||||
var resetInverterAlarm = CheckInverterAlarms(statusRecord, currentSaliMaxState).WriteLine(" reset Alarm");
|
||||
var resetDcAlarm = CheckDcDcAlarms(statusRecord);
|
||||
|
||||
var lastEocTime = GetLastEocTime(statusRecord);
|
||||
|
@ -152,32 +155,48 @@ public static class Controller
|
|||
var noGridMeter = statusRecord.GridMeterStatus == null;
|
||||
var saliMaxConfig = statusRecord.SalimaxConfig with { LastEoc = lastEocTime };
|
||||
|
||||
var currentSaliMaxState = GetSaliMaxState(statusRecord);
|
||||
ExplainState(currentSaliMaxState);
|
||||
|
||||
const RelayState k2Relay = Closed;
|
||||
|
||||
var acPowerStageEnable = StateConfig.AcPowerStageEnableStates.Contains(currentSaliMaxState) || currentSaliMaxState == 8;
|
||||
var acPowerStageEnable = StateConfig.AcPowerStageEnableStates.Contains(currentSaliMaxState); //this is logical incorrect, find better way
|
||||
|
||||
var dcPowerStageEnable = statusRecord.BatteryStatus is not null; // this is to check
|
||||
var dcPowerStageEnable = statusRecord.BatteriesStatus is not null; // TODO this is to check, Can be the batteries Status be null?
|
||||
|
||||
var salimaxRelay = statusRecord.SaliMaxRelayStatus! with { K2 = k2Relay }; // to check
|
||||
var salimaxRelay = statusRecord.SaliMaxRelayStatus! with { K2 = k2Relay }; // to check // this is must be control
|
||||
|
||||
|
||||
if (statusRecord.BatteryStatus == null)
|
||||
if (resetInverterAlarm)
|
||||
{
|
||||
acPowerStageEnable = !resetInverterAlarm ;
|
||||
acSlaveId = 0;
|
||||
}
|
||||
|
||||
if (resetDcAlarm)
|
||||
{
|
||||
dcPowerStageEnable = !resetDcAlarm ;
|
||||
}
|
||||
|
||||
acSlaveId.WriteLine(" AcSlave @");
|
||||
|
||||
if (statusRecord.BatteriesStatus == null)
|
||||
{
|
||||
Console.WriteLine(" No batteries");
|
||||
return new ControlRecord
|
||||
{
|
||||
AcControlRecord = Defaults.TruConvertAcControl with
|
||||
{
|
||||
SignedPowerNominalValue = 0,
|
||||
PowerStageEnable = acPowerStageEnable,
|
||||
CommunicationTimeout = CommunicationTimeout,
|
||||
SlaveAddress = acSlaveId,
|
||||
ResetsAlarmAndWarning = resetInverterAlarm
|
||||
},
|
||||
DcControlRecord = Defaults.TruConvertDcControl with
|
||||
{
|
||||
PowerStageEnable = dcPowerStageEnable,
|
||||
ResetsAlarmAndWarning = resetDcAlarm
|
||||
ResetsAlarmAndWarning = resetDcAlarm,
|
||||
TimeoutForCommunication = CommunicationTimeout
|
||||
|
||||
},
|
||||
SalimaxConfig = saliMaxConfig, // must create a control of each
|
||||
SalimaxRelays = salimaxRelay, // must create a control of each
|
||||
|
@ -201,6 +220,38 @@ public static class Controller
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var newPowerSetPoint = CalculateNewPowerSetPoint(statusRecord);
|
||||
|
||||
////////////////////////// Control Record //////////////////////////
|
||||
|
||||
var acControlRecord = Defaults.TruConvertAcControl with
|
||||
{
|
||||
PowerStageEnable = acPowerStageEnable,
|
||||
CommunicationTimeout = CommunicationTimeout,
|
||||
SignedPowerNominalValue = newPowerSetPoint,
|
||||
SlaveAddress = acSlaveId,
|
||||
ResetsAlarmAndWarning = resetInverterAlarm
|
||||
};
|
||||
|
||||
var dcControlRecord = Defaults.TruConvertDcControl with
|
||||
{
|
||||
PowerStageEnable = dcPowerStageEnable,
|
||||
ResetsAlarmAndWarning = resetDcAlarm,
|
||||
TimeoutForCommunication = CommunicationTimeout
|
||||
};
|
||||
|
||||
|
||||
return new ControlRecord
|
||||
{
|
||||
AcControlRecord = acControlRecord,
|
||||
DcControlRecord = dcControlRecord,
|
||||
SalimaxConfig = saliMaxConfig,
|
||||
SalimaxRelays = salimaxRelay
|
||||
};
|
||||
}
|
||||
|
||||
private static Decimal CalculateNewPowerSetPoint(StatusRecord statusRecord)
|
||||
{
|
||||
var currentPowerSetPoint = statusRecord.InverterStatus!.AcSignedPowerValue;
|
||||
|
||||
var limitReason = "no limit";
|
||||
|
@ -212,7 +263,7 @@ public static class Controller
|
|||
goal = "Calibration Charge";
|
||||
delta = statusRecord.ControlInverterPower(statusRecord.SalimaxConfig.MaxInverterPower);
|
||||
}
|
||||
else if (statusRecord.BatteryStatus!.Soc < statusRecord.SalimaxConfig.MinSoc)
|
||||
else if (statusRecord.AvgBatteriesStatus!.Soc < statusRecord.SalimaxConfig.MinSoc) // TODO
|
||||
{
|
||||
goal = $"reach min SOC (Min soc: {statusRecord.SalimaxConfig.MinSoc})";
|
||||
delta = statusRecord.ControlInverterPower(statusRecord.SalimaxConfig
|
||||
|
@ -234,7 +285,7 @@ public static class Controller
|
|||
delta = inverterAc2DcLimitPower;
|
||||
}
|
||||
|
||||
var batteryChargingLimitPower = statusRecord.ControlBatteryPower(statusRecord.BatteryStatus!.MaxChargingPower);
|
||||
var batteryChargingLimitPower = statusRecord.ControlBatteryPower(statusRecord.BatteriesStatus[0]!.MaxChargingPower);
|
||||
|
||||
if (delta > batteryChargingLimitPower)
|
||||
{
|
||||
|
@ -253,12 +304,12 @@ public static class Controller
|
|||
}
|
||||
|
||||
var batteryDischargingLimitPower =
|
||||
statusRecord.ControlBatteryPower(statusRecord.BatteryStatus!.MaxDischargingPower);
|
||||
statusRecord.ControlBatteryPower(statusRecord.BatteriesStatus[0]!.MaxDischargingPower); // TODO change to avg battery
|
||||
|
||||
if (delta < batteryDischargingLimitPower)
|
||||
{
|
||||
limitReason =
|
||||
$"limited by max battery discharging power: {statusRecord.BatteryStatus!.MaxDischargingPower}";
|
||||
$"limited by max battery discharging power: {statusRecord.BatteriesStatus[0]!.MaxDischargingPower}";// TODO change to avg battery
|
||||
|
||||
delta = batteryDischargingLimitPower;
|
||||
}
|
||||
|
@ -271,13 +322,13 @@ public static class Controller
|
|||
delta = keepMinSocLimitDelta;
|
||||
}
|
||||
|
||||
/* if (statusRecord.BatteryStatus.BatteryTemperature >= 300) must not reduce the delta
|
||||
{
|
||||
var softLandingFactor = (MaxmimumAllowedBatteryTemp - statusRecord.BatteryStatus.BatteryTemperature) / 15; //starting softlanding from 300 degree
|
||||
limitReason =
|
||||
$"limiting discharging power in order to stay keep the battery temp below 315°: {statusRecord.BatteryStatus.BatteryTemperature}°" + " Softlanding factor: " + softLandingFactor;
|
||||
delta *= softLandingFactor;
|
||||
}*/
|
||||
// if (statusRecord.BatteriesStatus[0]!.Temperature >= 300) //must not reduce the delta
|
||||
// {
|
||||
// var softLandingFactor = (MaxmimumAllowedBatteryTemp - statusRecord.BatteriesStatus[0]!.Temperature) / 15; //starting softlanding from 300 degree
|
||||
// limitReason =
|
||||
// $"limiting discharging power in order to stay keep the battery temp below 315°: {statusRecord.BatteriesStatus[0]!.Temperature}°" + " Softlanding factor: " + softLandingFactor;
|
||||
// delta *= softLandingFactor;
|
||||
// }
|
||||
|
||||
var newPowerSetPoint =
|
||||
DistributePower(currentPowerSetPoint + delta, statusRecord.SalimaxConfig.MaxInverterPower);
|
||||
|
@ -289,32 +340,7 @@ public static class Controller
|
|||
limitReason.WriteLine(" Limit reason");
|
||||
delta.WriteLine(" Delta");
|
||||
// "============".WriteLine();
|
||||
|
||||
////////////////////////// Control Record //////////////////////////
|
||||
|
||||
var acControlRecord = Defaults.TruConvertAcControl with
|
||||
{
|
||||
PowerStageEnable = acPowerStageEnable,
|
||||
CommunicationTimeout = CommunicationTimeout,
|
||||
SignedPowerNominalValue = newPowerSetPoint,
|
||||
ResetsAlarmAndWarning = resetInverterAlarm
|
||||
};
|
||||
|
||||
var dcControlRecord = Defaults.TruConvertDcControl with
|
||||
{
|
||||
PowerStageEnable = dcPowerStageEnable,
|
||||
ResetsAlarmAndWarning = resetDcAlarm,
|
||||
TimeoutForCommunication = CommunicationTimeout
|
||||
};
|
||||
|
||||
|
||||
return new ControlRecord
|
||||
{
|
||||
AcControlRecord = acControlRecord,
|
||||
DcControlRecord = dcControlRecord,
|
||||
SalimaxConfig = saliMaxConfig,
|
||||
SalimaxRelays = salimaxRelay
|
||||
};
|
||||
return newPowerSetPoint;
|
||||
}
|
||||
|
||||
private static State TargetState(State currentState)
|
||||
|
@ -423,7 +449,7 @@ public static class Controller
|
|||
|
||||
private static UnixTime GetLastEocTime(StatusRecord statusRecord)
|
||||
{
|
||||
if (statusRecord.BatteryStatus?.Soc >= 100)
|
||||
if (statusRecord.BatteriesStatus[0]!.Soc >= 100 && statusRecord.BatteriesStatus[1]!.Soc >= 100 )
|
||||
{
|
||||
Console.WriteLine("battery has reached EOC");
|
||||
File.AppendAllTextAsync(Config.LogSalimaxLog, String.Join(Environment.NewLine, UnixTime.Now + "battery has reached EOC"));
|
||||
|
@ -442,6 +468,7 @@ public static class Controller
|
|||
|
||||
private static Boolean CheckDcDcAlarms(StatusRecord s)
|
||||
{
|
||||
s.DcDcStatus?.Alarms.Count.WriteLine(" Dc Alarm count");
|
||||
if ( s.DcDcStatus?.Alarms.Count > 0 &&
|
||||
s.DcDcStatus?.PowerOperation == false)
|
||||
{
|
||||
|
@ -452,14 +479,15 @@ public static class Controller
|
|||
return false;
|
||||
}
|
||||
|
||||
private static Boolean CheckInverterAlarms(StatusRecord s)
|
||||
private static Boolean CheckInverterAlarms(StatusRecord s, UInt16 state)
|
||||
{
|
||||
if ( s.InverterStatus?.Alarms.Count > 0 &&
|
||||
s.InverterStatus?.PowerOperation == false)
|
||||
s.InverterStatus?.Alarms.Count.WriteLine(" Ac Alarm count");
|
||||
if ( s.InverterStatus?.Alarms.Count > 0 )
|
||||
{
|
||||
File.AppendAllTextAsync(Config.LogSalimaxLog, UnixTime.Now + " " + s.InverterStatus.Alarms);
|
||||
File.AppendAllTextAsync(Config.LogSalimaxLog, UnixTime.Now + " " + s.InverterStatus.Alarms[0]); // Todo write every alarm in he alarm list
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,26 @@ public enum State : Int16
|
|||
{
|
||||
State1 = 1,
|
||||
State2 = 2,
|
||||
State3 = 3,
|
||||
State4 = 4,
|
||||
State5 = 5,
|
||||
State6 = 6,
|
||||
State7 = 7,
|
||||
State8 = 8,
|
||||
State9 = 9,
|
||||
State10 = 10,
|
||||
State11 = 11,
|
||||
State12 = 12,
|
||||
State13 = 13,
|
||||
State14 = 14,
|
||||
State15 = 15,
|
||||
State16 = 16,
|
||||
State17 = 17,
|
||||
State18 = 18,
|
||||
State19 = 19,
|
||||
State20 = 20,
|
||||
State21 = 21,
|
||||
State22 = 22,
|
||||
State23 = 23,
|
||||
State24 = 24
|
||||
}
|
|
@ -3,5 +3,5 @@ namespace InnovEnergy.SaliMax.Controller;
|
|||
|
||||
public static class StateConfig
|
||||
{
|
||||
public static readonly IReadOnlyList<Int32> AcPowerStageEnableStates = new[] { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
|
||||
public static readonly IReadOnlyList<Int32> AcPowerStageEnableStates = new[] {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
|
||||
}
|
|
@ -12,11 +12,11 @@ public record StatusRecord
|
|||
{
|
||||
public TruConvertAcStatus? InverterStatus { get; init; }
|
||||
public TruConvertDcStatus? DcDcStatus { get; init; }
|
||||
public Battery48TLStatus? BatteryStatus { get; init; }
|
||||
public Battery48TLStatus[]? BatteriesStatus { get; set; } = Array.Empty<Battery48TLStatus>(); // TODO remove static
|
||||
public AvgBatteriesStatus? AvgBatteriesStatus { get; init; }
|
||||
public EmuMeterStatus? GridMeterStatus { get; init; }
|
||||
public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
|
||||
public AmptStatus? AmptStatus { get; init; }
|
||||
public EmuMeterStatus? AcInToAcOutMeterStatus { get; init; }
|
||||
public SalimaxConfig SalimaxConfig { get; init; } = null!;
|
||||
}
|
||||
|
|
@ -11,15 +11,16 @@ public static class Ampt
|
|||
if (s is null)
|
||||
return null;
|
||||
|
||||
// TODO return one AMPT device to sum all the other
|
||||
|
||||
return DeviceType
|
||||
.PvOnDc
|
||||
.CreateDevice("AMPT")
|
||||
.AddProp("Current 1", s.Current1)
|
||||
.AddProp("Current 2", s.Current2)
|
||||
.AddProp("Voltage 1", s.Voltage1)
|
||||
.AddProp("Voltage 2", s.Voltage2)
|
||||
.AddProp("Power 1", s.Current1 * s.Voltage1)
|
||||
.AddProp("Power 2", s.Current2 * s.Voltage2);
|
||||
// .AddDcConnection(s.AvgCurrent.Round3(), s.AvgVolatge.Round3());
|
||||
.AddProp("Current 1", s.Devices[0].Dc.Current)
|
||||
.AddProp("Current 2", s.Devices[1].Dc.Current)
|
||||
.AddProp("Voltage 1", s.Devices[0].Dc.Voltage)
|
||||
.AddProp("Voltage 2", s.Devices[1].Dc.Voltage)
|
||||
.AddProp("Power 1", s.Devices[0].Dc.Current * s.Devices[0].Dc.Voltage)
|
||||
.AddProp("Power 2", s.Devices[1].Dc.Current * s.Devices[1].Dc.Voltage);
|
||||
}
|
||||
}
|
|
@ -14,13 +14,13 @@ public static class Battery48Tl
|
|||
return DeviceType
|
||||
.Battery
|
||||
.CreateDevice("48TL Battery")
|
||||
.AddDc48Connection(s.Current.Round3(),s.Voltage.Round3())
|
||||
.AddDc48Connection(s.Dc.Current.Round3(),s.Dc.Voltage.Round3())
|
||||
.AddAlarms(s.Alarms)
|
||||
.AddWarnings(s.Warnings)
|
||||
.AddProp("Soc", s.Soc.Round3())
|
||||
.AddProp("HeaterOn", s.HeaterOn)
|
||||
.AddProp("EocReached", s.EocReached)
|
||||
.AddProp("BatteryCold", s.BatteryCold)
|
||||
.AddProp("Temperature", s.BatteryTemperature);
|
||||
.AddProp("Temperature", s.Temperature);
|
||||
}
|
||||
}
|
|
@ -17,16 +17,16 @@ public static class EmuMeter
|
|||
|
||||
//
|
||||
|
||||
var l1 = CreateAcPhase(s.CurrentL1, s.VoltageL1N, ACos(s.PowerFactorL1));
|
||||
var l2 = CreateAcPhase(s.CurrentL2, s.VoltageL2N, ACos(s.PowerFactorL2));
|
||||
var l3 = CreateAcPhase(s.CurrentL3, s.VoltageL3N, ACos(s.PowerFactorL3));
|
||||
var l1 = CreateAcPhase(s.Ac.L1.Current, s.Ac.L1.Voltage, ACos(s.Ac.L1.PowerFactor));
|
||||
var l2 = CreateAcPhase(s.Ac.L2.Current, s.Ac.L2.Voltage, ACos(s.Ac.L2.PowerFactor));
|
||||
var l3 = CreateAcPhase(s.Ac.L3.Current, s.Ac.L3.Voltage, ACos(s.Ac.L3.PowerFactor));
|
||||
|
||||
var ac = new JsonObject
|
||||
{
|
||||
["L1"] = l1,
|
||||
["L2"] = l2,
|
||||
["L3"] = l3,
|
||||
["Frequency"] = s.Frequency
|
||||
["Frequency"] = s.Ac.Frequency
|
||||
};
|
||||
|
||||
var status = new JsonObject
|
||||
|
@ -39,8 +39,8 @@ public static class EmuMeter
|
|||
|
||||
private static IEnumerable<JsonObject> GetAcPhases(this EmuMeterStatus s)
|
||||
{
|
||||
yield return CreateAcPhase(s.CurrentL1.Round3(),s.VoltageL1N.Round3(),s.PowerFactorL1.Apply(ACos).Round3());
|
||||
yield return CreateAcPhase(s.CurrentL2.Round3(),s.VoltageL2N.Round3(),s.PowerFactorL2.Apply(ACos).Round3());
|
||||
yield return CreateAcPhase(s.CurrentL3.Round3(),s.VoltageL3N.Round3(),s.PowerFactorL3.Apply(ACos).Round3());
|
||||
yield return CreateAcPhase(s.Ac.L1.Current.Round3(),s.Ac.L1.Voltage.Round3(),s.Ac.L1.PowerFactor.Apply(ACos).Round3());
|
||||
yield return CreateAcPhase(s.Ac.L2.Current.Round3(),s.Ac.L2.Voltage.Round3(),s.Ac.L2.PowerFactor.Apply(ACos).Round3());
|
||||
yield return CreateAcPhase(s.Ac.L3.Current.Round3(),s.Ac.L3.Voltage.Round3(),s.Ac.L3.PowerFactor.Apply(ACos).Round3());
|
||||
}
|
||||
}
|
|
@ -24,15 +24,16 @@ public static class Salimax
|
|||
|
||||
private static IEnumerable<JsonNode?> GetDevices(StatusRecord s)
|
||||
{
|
||||
yield return s.InverterStatus.Log("1234");
|
||||
yield return s.InverterStatus.Log();
|
||||
yield return s.DcDcStatus.Log("3214");
|
||||
yield return s.GridMeterStatus.Log(DeviceType.Grid);
|
||||
yield return s.AcInToAcOutMeterStatus.Log(DeviceType.AcInToAcOut);
|
||||
yield return s.GridMeterStatus.Log(DeviceType.Grid , "123");
|
||||
yield return s.AcInToAcOutMeterStatus.Log(DeviceType.AcInToAcOut, "123");
|
||||
yield return s.AmptStatus.Log();
|
||||
yield return s.BatteryStatus.Log();
|
||||
yield return s.BatteriesStatus![0].Log();
|
||||
yield return s.BatteriesStatus[1].Log();
|
||||
}
|
||||
|
||||
public static JsonArray CreateTopology()
|
||||
private static JsonArray CreateTopology()
|
||||
{
|
||||
var acInBusJson = JsonUtil.CreateBus
|
||||
(
|
||||
|
|
|
@ -9,13 +9,12 @@ namespace InnovEnergy.SaliMax.Log;
|
|||
public static class TruConvertAc
|
||||
{
|
||||
|
||||
// TODO: remove serialNb arg, embed TruConvertDcStatus
|
||||
public static JsonObject? Log(this TruConvertAcStatus? s, String serialNb)
|
||||
public static JsonObject? Log(this TruConvertAcStatus? s)
|
||||
{
|
||||
if (s is null)
|
||||
return null;
|
||||
|
||||
var dcPower = s.PowerAcL1 + s.PowerAcL2 + s.PowerAcL3;
|
||||
var dcPower = s.Ac.ActivePower;
|
||||
var dcVoltage = s.ActualDcLinkVoltageLowerHalfExt + s.ActualDcLinkVoltageUpperHalfExt;
|
||||
var dcCurrent = dcVoltage != 0m
|
||||
? dcPower / dcVoltage
|
||||
|
@ -25,16 +24,16 @@ public static class TruConvertAc
|
|||
// TODO: acos quadrant
|
||||
// TODO: total AC power
|
||||
|
||||
var l1 = CreateAcPhase(s.PhaseCurrentL1, s.GridVoltageL1, ACos(s.CosPhiL1));
|
||||
var l2 = CreateAcPhase(s.PhaseCurrentL2, s.GridVoltageL2, ACos(s.CosPhiL2));
|
||||
var l3 = CreateAcPhase(s.PhaseCurrentL3, s.GridVoltageL3, ACos(s.CosPhiL3));
|
||||
var l1 = CreateAcPhase(s.Ac.L1.Current.Round3(), s.Ac.L1.Voltage.Round3(), s.Ac.L1.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
var l2 = CreateAcPhase(s.Ac.L2.Current.Round3(), s.Ac.L2.Voltage.Round3(), s.Ac.L1.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
var l3 = CreateAcPhase(s.Ac.L3.Current.Round3(), s.Ac.L3.Voltage.Round3(), s.Ac.L1.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
|
||||
var ac = new JsonObject
|
||||
{
|
||||
["L1"] = l1,
|
||||
["L2"] = l2,
|
||||
["L3"] = l3,
|
||||
["Frequency"] = s.GridFrequency
|
||||
["Frequency"] = s.Ac.Frequency
|
||||
};
|
||||
|
||||
var dc = CreateDcPhase(dcCurrent, dcVoltage);
|
||||
|
@ -47,20 +46,20 @@ public static class TruConvertAc
|
|||
["Alarms"] = s.Alarms.ToJsonArray() ,
|
||||
};
|
||||
|
||||
return new JsonObject { [$"TruConvertAc {serialNb}"] = status };
|
||||
return new JsonObject { [$"TruConvertAc {s.SerialNumber}"] = status };
|
||||
}
|
||||
|
||||
private static IEnumerable<JsonObject> GetAcPhases(this TruConvertAcStatus s)
|
||||
{
|
||||
// Math.Acos return "NaN" if the cos phi < -1 or > 1
|
||||
// Decimal.Acos throw an exception
|
||||
yield return JsonUtil.CreateAcPhase(s.PhaseCurrentL1.Round3(), s.GridVoltageL1.Round3(),
|
||||
s.CosPhiL1.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
yield return JsonUtil.CreateAcPhase(s.Ac.L1.Current.Round3(), s.Ac.L1.Voltage.Round3(),
|
||||
s.Ac.L1.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
|
||||
yield return JsonUtil.CreateAcPhase(s.PhaseCurrentL2.Round3(), s.GridVoltageL2.Round3(),
|
||||
s.CosPhiL2.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
yield return JsonUtil.CreateAcPhase(s.Ac.L2.Current.Round3(), s.Ac.L2.Voltage.Round3(),
|
||||
s.Ac.L2.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
|
||||
yield return JsonUtil.CreateAcPhase(s.PhaseCurrentL3.Round3(), s.GridVoltageL3.Round3(),
|
||||
s.CosPhiL3.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
yield return JsonUtil.CreateAcPhase(s.Ac.L3.Current.Round3(), s.Ac.L3.Voltage.Round3(),
|
||||
s.Ac.L3.PowerFactor.Clamp(-1m, 1m).Apply(ACos).Round3());
|
||||
}
|
||||
}
|
|
@ -14,30 +14,19 @@ public static class TruConvertDc
|
|||
if (s is null)
|
||||
return null;
|
||||
|
||||
var dcCurrent = s.DcLinkVoltage != 0m
|
||||
? s.DcPower / s.DcLinkVoltage
|
||||
: 0m;
|
||||
var dcCurrent = s.Dc.Current;
|
||||
|
||||
return new JO
|
||||
{
|
||||
{
|
||||
$"TruConvertDc {serialNb}", new JO
|
||||
{
|
||||
{ "Dc" , CreateDcPhase(dcCurrent, s.DcLinkVoltage) },
|
||||
{ "Dc" , CreateDcPhase(dcCurrent, s.Dc.Voltage) },
|
||||
{ "Dc48" , CreateDcPhase(s.BatteryCurrent, s.BatteryVoltage) },
|
||||
{ "Warnings", s.Warnings.ToJsonArray() },
|
||||
{ "Alarms" , s.Alarms.ToJsonArray() },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// return DeviceType
|
||||
// .DcDc
|
||||
// .CreateDevice("TruConvertDc")
|
||||
// //.AddDcConnection(Decimal.Round(current, 3), s.DcLinkVoltage)
|
||||
// .AddDc48Connection(Decimal.Round(s.BatteryCurrent, 3), Decimal.Round(s.BatteryVoltage, 3))
|
||||
// .AddWarnings(s.Warnings)
|
||||
// .AddAlarms(s.Alarms)
|
||||
// .AddProp("DC Power", s.DcPower);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
#undef BatteriesAllowed
|
||||
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
@ -14,9 +17,12 @@ using InnovEnergy.SaliMax.Log;
|
|||
using InnovEnergy.SaliMax.SaliMaxRelays;
|
||||
using InnovEnergy.SaliMax.SystemConfig;
|
||||
using InnovEnergy.Time.Unix;
|
||||
using Utils = InnovEnergy.Lib.StatusApi.Utils;
|
||||
|
||||
|
||||
#pragma warning disable IL2026
|
||||
|
||||
|
||||
namespace InnovEnergy.SaliMax;
|
||||
|
||||
internal static class Program
|
||||
|
@ -31,7 +37,8 @@ internal static class Program
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await File.AppendAllTextAsync(Config.LogSalimaxLog, String.Join(Environment.NewLine, UnixTime.Now + " \n" + e));
|
||||
await File.AppendAllTextAsync(Config.LogSalimaxLog,
|
||||
String.Join(Environment.NewLine, UnixTime.Now + " \n" + e));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -57,10 +64,14 @@ internal static class Program
|
|||
var saliMaxRelaysDevice = new SaliMaxRelaysDevice("127.0.0.1", 5004);
|
||||
var amptDevice = new AmptCommunicationUnit("127.0.0.1", 5005);
|
||||
var acInToAcOutMeterDevice = new EmuMeterDevice("127.0.0.1", 5003); // TODO: use real device
|
||||
var battery48TlDevice = Battery48TlDevice.Fake();
|
||||
var secondBattery48TlDevice = Battery48TlDevice.Fake();
|
||||
var firstBattery48TlDevice =Battery48TlDevice.Fake();;
|
||||
var salimaxConfig = new SalimaxConfig();
|
||||
#else
|
||||
var battery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 3);
|
||||
#if BatteriesAllowed
|
||||
var firstBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 2);
|
||||
var secondBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 3);
|
||||
#endif
|
||||
var inverterDevice = new TruConvertAcDevice("192.168.1.2");
|
||||
var dcDcDevice = new TruConvertDcDevice("192.168.1.3");
|
||||
var gridMeterDevice = new EmuMeterDevice("192.168.1.241");
|
||||
|
@ -69,15 +80,36 @@ internal static class Program
|
|||
var saliMaxRelaysDevice = new SaliMaxRelaysDevice("192.168.1.242");
|
||||
var salimaxConfig = new SalimaxConfig();
|
||||
#endif
|
||||
// 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()
|
||||
{
|
||||
#if BatteriesAllowed
|
||||
|
||||
var battery48TlStatusArray = battery48TlDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
#endif
|
||||
// var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
// var inverterStatusArray = inverterDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
|
||||
return new StatusRecord
|
||||
{
|
||||
InverterStatus = inverterDevice.ReadStatus(),
|
||||
DcDcStatus = dcDcDevice.ReadStatus(),
|
||||
BatteryStatus = battery48TlDevice.ReadStatus(),
|
||||
#if BatteriesAllowed
|
||||
|
||||
BatteriesStatus = battery48TlStatusArray,
|
||||
AvgBatteriesStatus = AvgBatteriesStatus.ReadBatteriesStatus(battery48TlStatusArray),
|
||||
#else
|
||||
BatteriesStatus = null,
|
||||
AvgBatteriesStatus = null,
|
||||
#endif
|
||||
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
||||
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
||||
SaliMaxRelayStatus = saliMaxRelaysDevice.ReadStatus(),
|
||||
|
@ -90,7 +122,8 @@ internal static class Program
|
|||
var startTime = UnixTime.Now;
|
||||
const Int32 delayTime = 10;
|
||||
|
||||
ReleaseWriteTopology(startTime);
|
||||
|
||||
await UploadTopology(s3Config, Salimax.TopologyToLog(startTime), startTime);
|
||||
DebugWriteTopology(startTime);
|
||||
|
||||
Console.WriteLine("press ctrl-C to stop");
|
||||
|
@ -104,16 +137,17 @@ internal static class Program
|
|||
await Task.Delay(delayTime);
|
||||
t = UnixTime.Now;
|
||||
}
|
||||
var status = ReadStatus();
|
||||
//var jsonLog = status.ToLog(t);
|
||||
|
||||
//await UploadTimeSeries(s3Config, jsonLog, t);
|
||||
var status = ReadStatus();
|
||||
#if BatteriesAllowed
|
||||
|
||||
var jsonLog = status.ToLog(t);
|
||||
await UploadTimeSeries(s3Config, jsonLog, t);
|
||||
var controlRecord = Controller.Controller.SaliMaxControl(status);
|
||||
Controller.Controller.WriteControlRecord(controlRecord, inverterDevice, dcDcDevice, saliMaxRelaysDevice);
|
||||
|
||||
// JsonSerializer.Serialize(jsonLog, JsonOptions).WriteLine(ConsoleColor.DarkBlue);
|
||||
|
||||
//ReleaseWriteLog(jsonLog, t);
|
||||
//JsonSerializer.Serialize(jsonLog, JsonOptions).WriteLine(ConsoleColor.DarkBlue);
|
||||
#endif
|
||||
PrintTopology(status);
|
||||
|
||||
while (UnixTime.Now == t)
|
||||
|
@ -130,39 +164,38 @@ internal static class Program
|
|||
const Int32 height = 25;
|
||||
|
||||
|
||||
var boxSize = chargingSeparator.Length / 2;
|
||||
|
||||
|
||||
var pwr = s.InverterStatus!.PowerAcL1 + s.InverterStatus.PowerAcL2 + s.InverterStatus.PowerAcL3;
|
||||
var pvPower = (s.AmptStatus!.Voltage1 * s.AmptStatus.Current1 + s.AmptStatus!.Voltage2 * s.AmptStatus.Current2).Round0();
|
||||
var loadPower = (s.GridMeterStatus!.ActivePowerL123 + pwr).Round3(); // it's a + because the pwr is inverted
|
||||
var pwr = s.InverterStatus!.Ac.ActivePower;
|
||||
var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt
|
||||
var loadPower = Utils.Round3((s.GridMeterStatus!.ActivePowerL123 + pwr)); // it's a + because the pwr is inverted
|
||||
|
||||
var gridSeparator = s.GridMeterStatus!.ActivePowerL123 > 0 ? chargingSeparator : dischargingSeparator;
|
||||
var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator;
|
||||
var dcSeparator = -s.DcDcStatus!.DcPower > 0 ? chargingSeparator : dischargingSeparator;
|
||||
var batterySeparator = s.BatteryStatus!.Power > 0 ? chargingSeparator : dischargingSeparator;
|
||||
|
||||
var dcSeparator = -s.DcDcStatus!.Dc.Power > 0 ? chargingSeparator : dischargingSeparator;
|
||||
#if BatteriesAllowed
|
||||
var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator;
|
||||
var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator;
|
||||
#endif
|
||||
|
||||
////////////////// Grid //////////////////////
|
||||
var boxGrid = AsciiArt.CreateBox
|
||||
(
|
||||
"Grid",
|
||||
s.GridMeterStatus.VoltageL1N.V(),
|
||||
s.GridMeterStatus.VoltageL2N.V(),
|
||||
s.GridMeterStatus.VoltageL3N.V()
|
||||
s.GridMeterStatus.Ac.L1.Voltage.V(),
|
||||
s.GridMeterStatus.Ac.L2.Voltage.V(),
|
||||
s.GridMeterStatus.Ac.L3.Voltage.V()
|
||||
).AlignCenterVertical(height);
|
||||
|
||||
//var gridBox = CreateRect(0, boxGrid).AlignBottom(height);
|
||||
var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator).AlignCenterVertical(height);
|
||||
var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator)
|
||||
.AlignCenterVertical(height);
|
||||
|
||||
|
||||
////////////////// Ac Bus //////////////////////
|
||||
var boxAcBus = AsciiArt.CreateBox
|
||||
(
|
||||
"AC Bus",
|
||||
s.InverterStatus.GridVoltageL1.V(),
|
||||
s.InverterStatus.GridVoltageL2.V(),
|
||||
s.InverterStatus.GridVoltageL3.V()
|
||||
s.InverterStatus.Ac.L1.Voltage.V(),
|
||||
s.InverterStatus.Ac.L2.Voltage.V(),
|
||||
s.InverterStatus.Ac.L3.Voltage.V()
|
||||
);
|
||||
|
||||
var boxLoad = AsciiArt.CreateBox
|
||||
|
@ -172,9 +205,10 @@ internal static class Program
|
|||
""
|
||||
);
|
||||
|
||||
var loadRect = CreateRect(loadPower, boxAcBus, boxLoad).AlignBottom(height);
|
||||
var loadRect = CreateRect(boxAcBus, boxLoad, loadPower).AlignBottom(height);
|
||||
|
||||
var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator).AlignCenterVertical(height);
|
||||
var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator)
|
||||
.AlignCenterVertical(height);
|
||||
|
||||
//////////////////// Inverter /////////////////////////
|
||||
var inverterBox = AsciiArt.CreateBox
|
||||
|
@ -184,7 +218,8 @@ internal static class Program
|
|||
""
|
||||
).AlignCenterVertical(height);
|
||||
|
||||
var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator).AlignCenterVertical(height);
|
||||
var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator)
|
||||
.AlignCenterVertical(height);
|
||||
|
||||
|
||||
//////////////////// DC Bus /////////////////////////
|
||||
|
@ -197,82 +232,120 @@ internal static class Program
|
|||
|
||||
var pvBox = AsciiArt.CreateBox
|
||||
(
|
||||
"",
|
||||
"MPPT",
|
||||
((s.AmptStatus!.Devices[0].Dc.Voltage + s.AmptStatus!.Devices[1].Dc.Voltage) / 2).Round0().V(),
|
||||
""
|
||||
);
|
||||
|
||||
var pvRect = CreateRect(pvPower, pvBox, dcBusBox).AlignTop(height);
|
||||
var pvRect = CreateRect(pvBox, dcBusBox, pvPower).AlignTop(height);
|
||||
|
||||
var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.DcPower.Round0(), dcSeparator).AlignCenterVertical(height);
|
||||
var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator)
|
||||
.AlignCenterVertical(height);
|
||||
|
||||
//////////////////// Dc/Dc /////////////////////////
|
||||
var dcBox = AsciiArt.CreateBox
|
||||
(
|
||||
"",
|
||||
"Dc/Dc",
|
||||
s.DcDcStatus.BatteryVoltage.V(),
|
||||
""
|
||||
).AlignCenterVertical(height);
|
||||
#if BatteriesAllowed
|
||||
var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power.Round0(), battery1Separator);
|
||||
var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power.Round0(), battery2Separator);
|
||||
#else
|
||||
var dcArrow1 ="";
|
||||
var dcArrow2 = "";
|
||||
var dcArrowRect = CreateRect(dcArrow1, dcArrow2).AlignCenterVertical(height);
|
||||
#endif
|
||||
|
||||
var dcArrow = AsciiArt.CreateHorizontalArrow(s.BatteryStatus!.Power.Round0(), batterySeparator).AlignCenterVertical(height);
|
||||
|
||||
//////////////////// Battery /////////////////////////
|
||||
var batteryBox = AsciiArt.CreateBox
|
||||
#if BatteriesAllowed
|
||||
|
||||
//////////////////// Batteries /////////////////////////
|
||||
var battery1Box = AsciiArt.CreateBox
|
||||
(
|
||||
"Battery",
|
||||
s.BatteryStatus!.Voltage.V(),
|
||||
""
|
||||
"Battery 1",
|
||||
s.BatteriesStatus[0].Voltage.V(),
|
||||
s.BatteriesStatus[0].Soc.Percent(),
|
||||
s.BatteriesStatus[0].Temperature.Celsius()
|
||||
);
|
||||
|
||||
var battery2Box = AsciiArt.CreateBox
|
||||
(
|
||||
"Battery 2",
|
||||
s.BatteriesStatus[1].Voltage.V(),
|
||||
s.BatteriesStatus[1].Soc.Percent(),
|
||||
s.BatteriesStatus[1].Temperature.Celsius()
|
||||
);
|
||||
|
||||
var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height);
|
||||
|
||||
var avgBatteryBox = AsciiArt.CreateBox
|
||||
(
|
||||
"Batteries",
|
||||
s.AvgBatteriesStatus!.Voltage.V(),
|
||||
s.AvgBatteriesStatus.Soc.Percent(),
|
||||
s.AvgBatteriesStatus.Temperature.Celsius()
|
||||
).AlignCenterVertical(height);
|
||||
|
||||
var batteryDegree = AsciiArt.CreateTransitionPadLeft(s.BatteryStatus!.Soc.Percent(), s.BatteryStatus!.BatteryTemperature.Celsius()).AlignCenterVertical(height);
|
||||
|
||||
// var loadLength = boxSize * 6;
|
||||
// var mpptLength = boxSize * 14;
|
||||
//
|
||||
// var mpptBox = AsciiArt.CreateVerticalPad(pvPower.W(),(Int16)mpptLength, true, "MPPT") + "\n";
|
||||
// var loadBox = AsciiArt.CreateVerticalPad(loadPower.W(), (Int16)loadLength, false, "Load");
|
||||
|
||||
|
||||
var topology = boxGrid.SideBySideWith(gridAcBusArrow,"")
|
||||
.SideBySideWith(loadRect,"")
|
||||
.SideBySideWith(acBusInvertArrow,"")
|
||||
.SideBySideWith(inverterBox,"")
|
||||
.SideBySideWith(inverterArrow,"")
|
||||
.SideBySideWith(pvRect,"")
|
||||
.SideBySideWith(dcBusArrow,"")
|
||||
.SideBySideWith(dcBox,"")
|
||||
.SideBySideWith(dcArrow,"")
|
||||
.SideBySideWith(batteryBox,"")
|
||||
.SideBySideWith(batteryDegree, "") + "\n";
|
||||
|
||||
// var topology = mpptBox + boxSide11 + loadBox;
|
||||
|
||||
var topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
||||
.SideBySideWith(loadRect, "")
|
||||
.SideBySideWith(acBusInvertArrow, "")
|
||||
.SideBySideWith(inverterBox, "")
|
||||
.SideBySideWith(inverterArrow, "")
|
||||
.SideBySideWith(pvRect, "")
|
||||
.SideBySideWith(dcBusArrow, "")
|
||||
.SideBySideWith(dcBox, "")
|
||||
.SideBySideWith(dcArrowRect, "")
|
||||
.SideBySideWith(batteryRect, "")
|
||||
.SideBySideWith(avgBatteryBox, "")+ "\n";
|
||||
#else
|
||||
var topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
||||
.SideBySideWith(loadRect, "")
|
||||
.SideBySideWith(acBusInvertArrow, "")
|
||||
.SideBySideWith(inverterBox, "")
|
||||
.SideBySideWith(inverterArrow, "")
|
||||
.SideBySideWith(pvRect, "")
|
||||
.SideBySideWith(dcBusArrow, "")
|
||||
.SideBySideWith(dcBox, "")+ "\n";
|
||||
#endif
|
||||
Console.WriteLine(topology);
|
||||
// Console.WriteLine(loadRect);
|
||||
// Console.WriteLine(pvRect);
|
||||
}
|
||||
|
||||
private static String CreateRect(Decimal loadPower, String boxAcBus, String boxLoad = "")
|
||||
private static String CreateRect(String boxTop, String boxBottom, Decimal power)
|
||||
{
|
||||
var loadAcBusArrow = AsciiArt.CreateVerticalArrow(loadPower);
|
||||
var boxes = new[] { boxAcBus, loadAcBusArrow, boxLoad };
|
||||
var powerArrow = AsciiArt.CreateVerticalArrow(power);
|
||||
var boxes = new[] { boxTop, powerArrow, boxBottom };
|
||||
var maxWidth = boxes.Max(l => l.Width());
|
||||
|
||||
var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines();
|
||||
return rect;
|
||||
}
|
||||
|
||||
private static String CreateRect(String boxTop, String boxBottom)
|
||||
{
|
||||
var boxes = new[] { boxTop, boxBottom };
|
||||
var maxWidth = boxes.Max(l => l.Width());
|
||||
|
||||
var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines();
|
||||
return rect;
|
||||
}
|
||||
|
||||
// to delete not used anymore
|
||||
[Conditional("RELEASE")]
|
||||
private static void ReleaseWriteLog(JsonObject jsonLog, UnixTime timestamp)
|
||||
{
|
||||
WriteToFile(jsonLog, "/home/debian/DataSaliMax/" + timestamp);
|
||||
// WriteToFile(jsonLog, "/home/debian/DataSaliMax/" + timestamp); // this is was for beaglebone TODO
|
||||
}
|
||||
|
||||
[Conditional("RELEASE")]
|
||||
private static void ReleaseWriteTopology(UnixTime timestamp)
|
||||
// [Conditional("RELEASE")]
|
||||
private static JsonObject ReleaseWriteTopology(UnixTime timestamp)
|
||||
{
|
||||
var topologyJson = Salimax.TopologyToLog(timestamp);
|
||||
WriteToFile(topologyJson, "/home/debian/DataSaliMax/topology" + timestamp);
|
||||
|
||||
// WriteToFile(topologyJson, "/home/debian/DataSaliMax/topology" + timestamp); // this is was for beaglebone
|
||||
return topologyJson;
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
|
@ -318,4 +391,19 @@ internal static class Program
|
|||
Console.WriteLine(error);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task UploadTopology(S3Config config, JsonObject json, UnixTime unixTime)
|
||||
{
|
||||
var payload = JsonSerializer.Serialize(json, JsonOptions);
|
||||
var s3Path = "topology" + unixTime.Ticks + ".json";
|
||||
var request = config.CreatePutRequest(s3Path);
|
||||
var response = await request.PutAsync(new StringContent(payload));
|
||||
|
||||
if (response.StatusCode != 200)
|
||||
{
|
||||
Console.WriteLine("ERROR: PUT");
|
||||
var error = response.GetStringAsync();
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,6 @@ namespace InnovEnergy.SaliMax.SaliMaxRelays;
|
|||
|
||||
public record SaliMaxRelayStatus
|
||||
{
|
||||
internal const UInt16 DigitalInputsStartRegister = 1;
|
||||
internal const UInt16 NbDigitalInputs = 6;
|
||||
|
||||
public RelayState K1 { get; init; } = RelayState.Closed; // Address on Adam(0X) 00002
|
||||
public RelayState K2 { get; init; } = RelayState.Closed; // Address on Adam(0X) 00003
|
||||
public RelayState K3 { get; init; } = RelayState.Closed; // Address on Adam(0X) 00004
|
||||
|
|
|
@ -2,5 +2,5 @@ namespace InnovEnergy.SaliMax.SystemConfig;
|
|||
|
||||
public static class Config
|
||||
{
|
||||
public const String LogSalimaxLog = "/home/debian/Salimax.log";
|
||||
public const String LogSalimaxLog = "/home/ie-entwicklung/Salimax.log"; // todo remove ie-entwicklung
|
||||
}
|
|
@ -13,7 +13,7 @@ public static class Defaults
|
|||
Subnet = default, //= 0x FFFFFF00;
|
||||
Gateway = default, //= 0x C0A80102;
|
||||
ResetParamToDefault = false, // Coil
|
||||
CommunicationTimeout = default,
|
||||
CommunicationTimeout = TimeSpan.FromSeconds(10),
|
||||
FactoryResetParameters = false,
|
||||
ConnectedSystemConfig = Lib.Devices.Trumpf.TruConvert.SystemConfig.AcDcAndDcDc,
|
||||
UpdateSwTrigger = 0,
|
||||
|
@ -25,7 +25,7 @@ public static class Defaults
|
|||
// IlBuildnumber = 0,
|
||||
PowerStageEnable = true,
|
||||
SetValueConfig = SymmetricAcOperationMode.Symmetric, // Asymmetric = 0, // this is can not be seen in UI
|
||||
ResetsAlarmAndWarning = false,
|
||||
ResetsAlarmAndWarning = true,
|
||||
PreChargeDcLinkConfig = PreChargeDcLinkConfig.Internal, // 1 = internal
|
||||
PowerFactorConvention = PowerFactorConvention.Producer, // 0 = producer
|
||||
SlaveAddress = 1,
|
||||
|
@ -66,9 +66,9 @@ public static class Defaults
|
|||
GridFormingMode = 0, // 0 = not grid-forming (grid-tied) ,1 = grid-forming TODO enum
|
||||
|
||||
//remove DC stuff from AC
|
||||
DcLinkRefVoltage = 850,
|
||||
DcLinkMinVoltage = 830,
|
||||
DcLinkMaxVoltage = 870,
|
||||
DcLinkRefVoltage = 800,
|
||||
DcLinkMinVoltage = 780,
|
||||
DcLinkMaxVoltage = 820,
|
||||
DcVoltageRefUs = 900,
|
||||
DcMinVoltageUs = 880,
|
||||
DcMaxVoltageUs = 920,
|
||||
|
@ -88,7 +88,7 @@ public static class Defaults
|
|||
Subnet = default,
|
||||
Gateway = default,
|
||||
ResetParamToDefault = false ,
|
||||
TimeoutForCommunication = default ,
|
||||
TimeoutForCommunication = TimeSpan.FromSeconds(10) ,
|
||||
RestartFlag = false ,
|
||||
ConnectedSystemConfig = Lib.Devices.Trumpf.TruConvert.SystemConfig.DcDcOnly,
|
||||
UpdateSwTrigger = 0,
|
||||
|
@ -112,7 +112,7 @@ public static class Defaults
|
|||
BatteryCurrentSet = 0,
|
||||
DynamicCurrentPerMillisecond = 2,
|
||||
DcLinkControlMode = 1,
|
||||
ReferenceVoltage = 850,
|
||||
ReferenceVoltage = 800,
|
||||
UpperVoltageWindow = 40,
|
||||
LowerVoltageWindow = 40,
|
||||
VoltageDeadBand = 0,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using DecimalMath;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Ampt;
|
||||
|
||||
|
@ -48,25 +49,22 @@ public class AmptCommunicationUnit
|
|||
.ToList();
|
||||
|
||||
var amptSt = new AmptStatus
|
||||
{
|
||||
Sid = r.GetUInt32(1),
|
||||
IdSunSpec = r.GetUInt16(3),
|
||||
Manufacturer = r.GetString(5, 16),
|
||||
Model = r.GetString(21, 16),
|
||||
Version = r.GetString(45, 8),
|
||||
SerialNumber = r.GetString(53, 16),
|
||||
DeviceAddress = r.GetInt16(69),
|
||||
IdVendor = r.GetUInt16(71),
|
||||
Devices = devices,
|
||||
Current1 = r.GetInt16(90) * currentFactor,
|
||||
Current2 = r.GetInt16(106) * currentFactor,
|
||||
Voltage1 = r.GetUInt32(91) * voltageFactor,
|
||||
Voltage2 = r.GetUInt32(107) * voltageFactor,
|
||||
(
|
||||
Sid : r.GetUInt32(1),
|
||||
IdSunSpec : r.GetUInt16(3),
|
||||
Manufacturer : r.GetString(5, 16),
|
||||
Model : r.GetString(21, 16),
|
||||
Version : r.GetString(45, 8),
|
||||
SerialNumber : r.GetString(53, 16),
|
||||
DeviceAddress : r.GetInt16(69),
|
||||
IdVendor : r.GetUInt16(71),
|
||||
Devices : devices
|
||||
// devices.d Current1 = r.GetInt16(90) * currentFactor,
|
||||
// Current2 = r.GetInt16(106) * currentFactor,
|
||||
// Voltage1 = r.GetUInt32(91) * voltageFactor,
|
||||
// Voltage2 = r.GetUInt32(107) * voltageFactor
|
||||
|
||||
//AvgVolatge = ReadDevicesVoltage(nbrOfDevices),
|
||||
//AvgCurrent = ReadDevicesCurrent(nbrOfDevices)
|
||||
|
||||
};
|
||||
);
|
||||
|
||||
|
||||
return amptSt;
|
||||
|
@ -104,26 +102,30 @@ public class AmptCommunicationUnit
|
|||
var b = (UInt16)(FirstDeviceOffset + deviceNumber * RegistersPerDevice); // base address
|
||||
|
||||
return new AmptDeviceStatus
|
||||
(
|
||||
Dc : new DcConnection
|
||||
(
|
||||
Voltage:r.GetUInt32((UInt16)(b + 6)) * voltageFactor,
|
||||
Current:r.GetUInt16((UInt16)(b + 5)) * currentFactor
|
||||
),
|
||||
DeviceId : r.GetInt16 (b) ,
|
||||
Timestamp : r.GetUInt32((UInt16)(b + 3)),
|
||||
ProductionToday : r.GetUInt32((UInt16)(b + 12))* energyFactor,
|
||||
|
||||
Strings : new []
|
||||
{
|
||||
DeviceId = r.GetInt16 (b) ,
|
||||
Timestamp = r.GetUInt32((UInt16)(b + 3)),
|
||||
Current = r.GetUInt16((UInt16)(b + 5)) * currentFactor,
|
||||
Voltage = r.GetUInt32((UInt16)(b + 6)) * voltageFactor,
|
||||
ProductionToday = r.GetUInt32((UInt16)(b + 12))* energyFactor,
|
||||
Strings = new AmptStringStatus[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Voltage = r.GetUInt32((UInt16)(b + 8)) * voltageFactor,
|
||||
Current = r.GetUInt16((UInt16)(b + 14)) * currentFactor,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Voltage = r.GetUInt32((UInt16)(b + 9)) * voltageFactor,
|
||||
Current = r.GetUInt16((UInt16)(b + 15)) * currentFactor,
|
||||
new DcConnection
|
||||
(
|
||||
Voltage : r.GetUInt32((UInt16)(b + 8)) * voltageFactor,
|
||||
Current : r.GetUInt16((UInt16)(b + 14)) * currentFactor
|
||||
),
|
||||
new DcConnection
|
||||
(
|
||||
Voltage : r.GetUInt32((UInt16)(b + 9)) * voltageFactor,
|
||||
Current : r.GetUInt16((UInt16)(b + 15)) * currentFactor
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Devices;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Ampt;
|
||||
|
||||
public record AmptDeviceStatus
|
||||
{
|
||||
internal const UInt16 NbrOfStrings = 2;
|
||||
public Int16 DeviceId { get; init; } // The string number
|
||||
public UInt32 Timestamp { get; init; } // The UTC timestamp of the measurements
|
||||
|
||||
public Decimal Current { get; init; } // String output current in mA
|
||||
public Decimal Voltage { get; init; } // String output voltage in mV
|
||||
|
||||
public Decimal ProductionToday { get; init; } // converted to kW in AmptCU class
|
||||
public IReadOnlyList<AmptStringStatus> Strings { get; init; } = null!;
|
||||
}
|
||||
(
|
||||
DcConnection Dc,
|
||||
// UInt16 NbrOfStrings,
|
||||
Int16 DeviceId, // The string number
|
||||
UInt32 Timestamp, // The UTC timestamp of the measurements
|
||||
Decimal ProductionToday, // converted to kW in AmptCU class
|
||||
IReadOnlyList<DcConnection> Strings
|
||||
): Mppt(Dc, Strings)
|
||||
{}
|
|
@ -1,25 +1,27 @@
|
|||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Devices;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Ampt;
|
||||
|
||||
public record AmptStatus
|
||||
(
|
||||
UInt32 Sid, // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map
|
||||
UInt16 IdSunSpec, // A well-known value 1, uniquely identifies this as a SunSpec Common Model
|
||||
// UInt16 L, // Well-known # of 16-bit registers to follow : 66
|
||||
String? Manufacturer, // A well-known value registered with SunSpec for compliance: "Ampt"
|
||||
String? Model, // Manufacturer specific value "Communication Unit"
|
||||
String? Version, // Software Version
|
||||
String? SerialNumber, // Manufacturer specific value
|
||||
Int16 DeviceAddress, // Modbus Device ID
|
||||
UInt16 IdVendor, // Ampt SunSpec Vendor Code 64050
|
||||
// Decimal Current1,
|
||||
// Decimal Current2,
|
||||
// Decimal Voltage1,
|
||||
// Decimal Voltage2,
|
||||
IReadOnlyList<AmptDeviceStatus> Devices
|
||||
//internal const UInt16 StartRegister = 1;
|
||||
//internal const UInt16 TotalNbOfRegister = 116;
|
||||
)
|
||||
{
|
||||
internal const UInt16 StartRegister = 1;
|
||||
internal const UInt16 TotalNbOfRegister = 116;
|
||||
|
||||
public UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map
|
||||
public UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model
|
||||
//public UInt16 L { get; init; } // Well-known # of 16-bit registers to follow : 66
|
||||
public String? Manufacturer { get; init; } // A well-known value registered with SunSpec for compliance: "Ampt"
|
||||
public String? Model { get; init; } // Manufacturer specific value "Communication Unit"
|
||||
public String? Version { get; init; } // Software Version
|
||||
public String? SerialNumber { get; init; } // Manufacturer specific value
|
||||
public Int16 DeviceAddress { get; init; } // Modbus Device ID
|
||||
public UInt16 IdVendor { get; init; } // Ampt SunSpec Vendor Code 64050
|
||||
public Decimal AvgVolatge { get; init; }
|
||||
public Decimal AvgCurrent { get; init; }
|
||||
public Decimal Current1 { get; init; }
|
||||
public Decimal Current2 { get; init; }
|
||||
public Decimal Voltage1 { get; init; }
|
||||
public Decimal Voltage2 { get; init; }
|
||||
|
||||
public IReadOnlyList<AmptDeviceStatus> Devices { get; init; } = null!;
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="../../Utils/Utils.csproj" />
|
||||
<ProjectReference Include="../../Protocols/Modbus/Modbus.csproj" />
|
||||
<ProjectReference Include="../../StatusApi/StatusApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||
|
||||
|
@ -33,6 +35,7 @@ public class Battery48TlDevice
|
|||
{
|
||||
if (Modbus is null) // TODO : remove fake
|
||||
{
|
||||
Console.WriteLine("Battery is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -41,13 +44,101 @@ public class Battery48TlDevice
|
|||
try
|
||||
{
|
||||
var registers = Modbus.ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters);
|
||||
return new Battery48TLStatus(registers);
|
||||
return TryReadStatus(registers);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
Console.WriteLine(e.Message + " Battery ");
|
||||
Modbus.CloseConnection();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Battery48TLStatus? TryReadStatus(ModbusRegisters data)
|
||||
{
|
||||
var soc = data.ParseDecimal(register: 1054, scaleFactor: 0.1m);
|
||||
var eocReached = data.ParseEocReached();
|
||||
|
||||
var warnings = new List<String>();
|
||||
|
||||
if (data.ParseBool(1006, 1)) warnings.Add("TaM1: BMS temperature high");
|
||||
if (data.ParseBool(1006, 4)) warnings.Add("TbM1: Battery temperature high");
|
||||
if (data.ParseBool(1006, 6)) warnings.Add("VBm1: Bus voltage low");
|
||||
if (data.ParseBool(1006, 8)) warnings.Add("VBM1: Bus voltage high");
|
||||
if (data.ParseBool(1006, 10)) warnings.Add("IDM1: Discharge current high");
|
||||
if (data.ParseBool(1006, 24)) warnings.Add("vsM1: String voltage high");
|
||||
if (data.ParseBool(1006, 26)) warnings.Add("iCM1: Charge current high");
|
||||
if (data.ParseBool(1006, 28)) warnings.Add("iDM1: Discharge current high");
|
||||
if (data.ParseBool(1006, 30)) warnings.Add("MID1: String voltages unbalanced");
|
||||
if (data.ParseBool(1006, 32)) warnings.Add("BLPW: Not enough charging power on bus");
|
||||
if (data.ParseBool(1006, 35)) warnings.Add("Ah_W: String SOC low");
|
||||
if (data.ParseBool(1006, 38)) warnings.Add("MPMM: Midpoint wiring problem");
|
||||
if (data.ParseBool(1006, 39)) warnings.Add("TCMM:");
|
||||
if (data.ParseBool(1006, 40)) warnings.Add("TCdi: Temperature difference between strings high");
|
||||
if (data.ParseBool(1006, 41)) warnings.Add("WMTO:");
|
||||
if (data.ParseBool(1006, 44)) warnings.Add("bit44:");
|
||||
if (data.ParseBool(1006, 46)) warnings.Add("CELL1:");
|
||||
|
||||
var alarms = new List<String>();
|
||||
|
||||
if (data.ParseBool(1010, 0)) alarms.Add("Tam : BMS temperature too low");
|
||||
if (data.ParseBool(1010, 2)) alarms.Add("TaM2 : BMS temperature too high");
|
||||
if (data.ParseBool(1010, 3)) alarms.Add("Tbm : Battery temperature too low");
|
||||
if (data.ParseBool(1010, 5)) alarms.Add("TbM2 : Battery temperature too high");
|
||||
if (data.ParseBool(1010, 7)) alarms.Add("VBm2 : Bus voltage too low");
|
||||
if (data.ParseBool(1010, 9)) alarms.Add("VBM2 : Bus voltage too high");
|
||||
if (data.ParseBool(1010, 11)) alarms.Add("IDM2 : Discharge current too high");
|
||||
if (data.ParseBool(1010, 12)) alarms.Add("ISOB : Electrical insulation failure");
|
||||
if (data.ParseBool(1010, 13)) alarms.Add("MSWE : Main switch failure");
|
||||
if (data.ParseBool(1010, 14)) alarms.Add("FUSE : Main fuse blown");
|
||||
if (data.ParseBool(1010, 15)) alarms.Add("HTRE : Battery failed to warm up");
|
||||
if (data.ParseBool(1010, 16)) alarms.Add("TCPE : Temperature sensor failure");
|
||||
if (data.ParseBool(1010, 17)) alarms.Add("STRE :");
|
||||
if (data.ParseBool(1010, 18)) alarms.Add("CME : Current sensor failure");
|
||||
if (data.ParseBool(1010, 19)) alarms.Add("HWFL : BMS hardware failure");
|
||||
if (data.ParseBool(1010, 20)) alarms.Add("HWEM : Hardware protection tripped");
|
||||
if (data.ParseBool(1010, 21)) alarms.Add("ThM : Heatsink temperature too high");
|
||||
if (data.ParseBool(1010, 22)) alarms.Add("vsm1 : String voltage too low");
|
||||
if (data.ParseBool(1010, 23)) alarms.Add("vsm2 : Low string voltage failure");
|
||||
if (data.ParseBool(1010, 25)) alarms.Add("vsM2 : String voltage too high");
|
||||
if (data.ParseBool(1010, 27)) alarms.Add("iCM2 : Charge current too high");
|
||||
if (data.ParseBool(1010, 29)) alarms.Add("iDM2 : Discharge current too high");
|
||||
if (data.ParseBool(1010, 31)) alarms.Add("MID2 : String voltage unbalance too high");
|
||||
if (data.ParseBool(1010, 33)) alarms.Add("CCBF : Internal charger hardware failure");
|
||||
if (data.ParseBool(1010, 34)) alarms.Add("AhFL :");
|
||||
if (data.ParseBool(1010, 36)) alarms.Add("TbCM :");
|
||||
if (data.ParseBool(1010, 37)) alarms.Add("BRNF :");
|
||||
if (data.ParseBool(1010, 42)) alarms.Add("HTFS : If Heaters Fuse Blown");
|
||||
if (data.ParseBool(1010, 43)) alarms.Add("DATA : Parameters out of range");
|
||||
if (data.ParseBool(1010, 45)) alarms.Add("CELL2:");
|
||||
|
||||
|
||||
return new Battery48TLStatus(
|
||||
Dc: new DcConnection
|
||||
(
|
||||
Voltage : data.ReadVoltage(),
|
||||
Current : data.ReadCurrent()),
|
||||
|
||||
Soc : !eocReached && soc >= 100m ? 99.9m : soc,
|
||||
Temperature : data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400),
|
||||
BusVoltage : data.ParseDecimal(register: 1002, scaleFactor: 0.01m),
|
||||
GreenLed : data.ParseLedState(register: 1005, led: LedColor.Green),
|
||||
AmberLed : data.ParseLedState(register: 1006, led: LedColor.Amber),
|
||||
BlueLed : data.ParseLedState(register: 1005, led: LedColor.Blue),
|
||||
RedLed : data.ParseLedState(register: 1005, led: LedColor.Red),
|
||||
Warnings : warnings,
|
||||
Alarms : alarms,
|
||||
MainSwitchClosed : data.ParseBool(baseRegister: 1014, bit: 0),
|
||||
AlarmOutActive : data.ParseBool(baseRegister: 1014, bit: 1),
|
||||
InternalFanActive : data.ParseBool(baseRegister: 1014, bit: 2),
|
||||
VoltMeasurementAllowed: data.ParseBool(baseRegister: 1014, bit: 3),
|
||||
AuxRelay : data.ParseBool(baseRegister: 1014, bit: 4),
|
||||
RemoteState : data.ParseBool(baseRegister: 1014, bit: 5),
|
||||
HeaterOn : data.ParseBool(baseRegister: 1014, bit: 6),
|
||||
EocReached : eocReached,
|
||||
BatteryCold : data.ParseBatteryCold(),
|
||||
MaxChargingPower : data.CalcMaxChargePower(),
|
||||
MaxDischargingPower : data.CalcMaxDischargePower()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,118 +1,39 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Devices;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class Battery48TLStatus
|
||||
public record Battery48TLStatus
|
||||
(
|
||||
DcConnection Dc,
|
||||
Decimal Soc,
|
||||
Decimal Temperature,
|
||||
//Decimal Current,
|
||||
//Decimal Voltage,
|
||||
Decimal BusVoltage,
|
||||
LedState GreenLed,
|
||||
LedState AmberLed,
|
||||
LedState BlueLed,
|
||||
LedState RedLed,
|
||||
IReadOnlyList<String> Warnings,
|
||||
IReadOnlyList<String> Alarms,
|
||||
Boolean MainSwitchClosed,
|
||||
Boolean AlarmOutActive,
|
||||
Boolean InternalFanActive,
|
||||
Boolean VoltMeasurementAllowed,
|
||||
Boolean AuxRelay,
|
||||
Boolean RemoteState,
|
||||
Boolean HeaterOn,
|
||||
Boolean EocReached,
|
||||
Boolean BatteryCold,
|
||||
Decimal MaxChargingPower,
|
||||
Decimal MaxDischargingPower
|
||||
)
|
||||
: Battery(Dc, Soc, Temperature)
|
||||
{
|
||||
public Decimal Soc { get; }
|
||||
public Decimal Current { get; }
|
||||
public Decimal Voltage { get; }
|
||||
public Decimal Power => Current * Voltage; // TODO do we have to invert the sign here?
|
||||
public Decimal BusVoltage { get; }
|
||||
public Decimal BatteryTemperature { get; }
|
||||
public LedState GreenLed { get; }
|
||||
public LedState AmberLed { get; }
|
||||
public LedState BlueLed { get; }
|
||||
public LedState RedLed { get; }
|
||||
public IReadOnlyList<String> Warnings { get; }
|
||||
public IReadOnlyList<String> Alarms { get; }
|
||||
public Boolean MainSwitchClosed { get; }
|
||||
public Boolean AlarmOutActive { get; }
|
||||
public Boolean InternalFanActive { get; }
|
||||
public Boolean VoltMeasurementAllowed { get; }
|
||||
public Boolean AuxRelay { get; }
|
||||
public Boolean RemoteState { get; }
|
||||
public Boolean HeaterOn { get; }
|
||||
public Boolean EocReached { get; }
|
||||
public Boolean BatteryCold { get; }
|
||||
public Decimal MaxChargingPower { get; }
|
||||
public Decimal MaxDischargingPower { get; }
|
||||
|
||||
|
||||
public Battery48TLStatus(ModbusRegisters data)
|
||||
{
|
||||
|
||||
var soc = data.ParseDecimal(register: 1054, scaleFactor: 0.1m);
|
||||
var eocReached = data.ParseEocReached();
|
||||
|
||||
var warnings = new List<String>();
|
||||
|
||||
if (data.ParseBool(1006, 1)) warnings.Add("TaM1: BMS temperature high");
|
||||
if (data.ParseBool(1006, 4)) warnings.Add("TbM1: Battery temperature high");
|
||||
if (data.ParseBool(1006, 6)) warnings.Add("VBm1: Bus voltage low");
|
||||
if (data.ParseBool(1006, 8)) warnings.Add("VBM1: Bus voltage high");
|
||||
if (data.ParseBool(1006, 10)) warnings.Add("IDM1: Discharge current high");
|
||||
if (data.ParseBool(1006, 24)) warnings.Add("vsM1: String voltage high");
|
||||
if (data.ParseBool(1006, 26)) warnings.Add("iCM1: Charge current high");
|
||||
if (data.ParseBool(1006, 28)) warnings.Add("iDM1: Discharge current high");
|
||||
if (data.ParseBool(1006, 30)) warnings.Add("MID1: String voltages unbalanced");
|
||||
if (data.ParseBool(1006, 32)) warnings.Add("BLPW: Not enough charging power on bus");
|
||||
if (data.ParseBool(1006, 35)) warnings.Add("Ah_W: String SOC low");
|
||||
if (data.ParseBool(1006, 38)) warnings.Add("MPMM: Midpoint wiring problem");
|
||||
if (data.ParseBool(1006, 39)) warnings.Add("TCMM:");
|
||||
if (data.ParseBool(1006, 40)) warnings.Add("TCdi: Temperature difference between strings high");
|
||||
if (data.ParseBool(1006, 41)) warnings.Add("WMTO:");
|
||||
if (data.ParseBool(1006, 44)) warnings.Add("bit44:");
|
||||
if (data.ParseBool(1006, 46)) warnings.Add("CELL1:");
|
||||
|
||||
var alarms = new List<String>();
|
||||
|
||||
if (data.ParseBool(1010, 0)) alarms.Add("Tam : BMS temperature too low");
|
||||
if (data.ParseBool(1010, 2)) alarms.Add("TaM2 : BMS temperature too high");
|
||||
if (data.ParseBool(1010, 3)) alarms.Add("Tbm : Battery temperature too low");
|
||||
if (data.ParseBool(1010, 5)) alarms.Add("TbM2 : Battery temperature too high");
|
||||
if (data.ParseBool(1010, 7)) alarms.Add("VBm2 : Bus voltage too low");
|
||||
if (data.ParseBool(1010, 9)) alarms.Add("VBM2 : Bus voltage too high");
|
||||
if (data.ParseBool(1010, 11)) alarms.Add("IDM2 : Discharge current too high");
|
||||
if (data.ParseBool(1010, 12)) alarms.Add("ISOB : Electrical insulation failure");
|
||||
if (data.ParseBool(1010, 13)) alarms.Add("MSWE : Main switch failure");
|
||||
if (data.ParseBool(1010, 14)) alarms.Add("FUSE : Main fuse blown");
|
||||
if (data.ParseBool(1010, 15)) alarms.Add("HTRE : Battery failed to warm up");
|
||||
if (data.ParseBool(1010, 16)) alarms.Add("TCPE : Temperature sensor failure");
|
||||
if (data.ParseBool(1010, 17)) alarms.Add("STRE :");
|
||||
if (data.ParseBool(1010, 18)) alarms.Add("CME : Current sensor failure");
|
||||
if (data.ParseBool(1010, 19)) alarms.Add("HWFL : BMS hardware failure");
|
||||
if (data.ParseBool(1010, 20)) alarms.Add("HWEM : Hardware protection tripped");
|
||||
if (data.ParseBool(1010, 21)) alarms.Add("ThM : Heatsink temperature too high");
|
||||
if (data.ParseBool(1010, 22)) alarms.Add("vsm1 : String voltage too low");
|
||||
if (data.ParseBool(1010, 23)) alarms.Add("vsm2 : Low string voltage failure");
|
||||
if (data.ParseBool(1010, 25)) alarms.Add("vsM2 : String voltage too high");
|
||||
if (data.ParseBool(1010, 27)) alarms.Add("iCM2 : Charge current too high");
|
||||
if (data.ParseBool(1010, 29)) alarms.Add("iDM2 : Discharge current too high");
|
||||
if (data.ParseBool(1010, 31)) alarms.Add("MID2 : String voltage unbalance too high");
|
||||
if (data.ParseBool(1010, 33)) alarms.Add("CCBF : Internal charger hardware failure");
|
||||
if (data.ParseBool(1010, 34)) alarms.Add("AhFL :");
|
||||
if (data.ParseBool(1010, 36)) alarms.Add("TbCM :");
|
||||
if (data.ParseBool(1010, 37)) alarms.Add("BRNF :");
|
||||
if (data.ParseBool(1010, 42)) alarms.Add("HTFS : If Heaters Fuse Blown");
|
||||
if (data.ParseBool(1010, 43)) alarms.Add("DATA : Parameters out of range");
|
||||
if (data.ParseBool(1010, 45)) alarms.Add("CELL2:");
|
||||
|
||||
Voltage = data.ReadVoltage();
|
||||
Current = data.ReadCurrent();
|
||||
Soc = !eocReached && soc >= 100m ? 99.9m : soc;
|
||||
BusVoltage = data.ParseDecimal(register: 1002, scaleFactor: 0.01m);
|
||||
BatteryTemperature = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400);
|
||||
GreenLed = data.ParseLedState(register: 1005, led: LedColor.Green);
|
||||
AmberLed = data.ParseLedState(register: 1006, led: LedColor.Amber);
|
||||
BlueLed = data.ParseLedState(register: 1005, led: LedColor.Blue);
|
||||
RedLed = data.ParseLedState(register: 1005, led: LedColor.Red);
|
||||
Warnings = warnings;
|
||||
Alarms = alarms;
|
||||
MainSwitchClosed = data.ParseBool(baseRegister: 1014, bit: 0);
|
||||
AlarmOutActive = data.ParseBool(baseRegister: 1014, bit: 1);
|
||||
InternalFanActive = data.ParseBool(baseRegister: 1014, bit: 2);
|
||||
VoltMeasurementAllowed = data.ParseBool(baseRegister: 1014, bit: 3);
|
||||
AuxRelay = data.ParseBool(baseRegister: 1014, bit: 4);
|
||||
RemoteState = data.ParseBool(baseRegister: 1014, bit: 5);
|
||||
HeaterOn = data.ParseBool(baseRegister: 1014, bit: 6);
|
||||
EocReached = eocReached;
|
||||
BatteryCold = data.ParseBatteryCold();
|
||||
MaxChargingPower = data.CalcMaxChargePower();
|
||||
MaxDischargingPower = data.CalcMaxDischargePower();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -111,6 +111,22 @@ public static class BatteryDataParser
|
|||
return pLimit;
|
||||
}
|
||||
|
||||
|
||||
private static Decimal CalcPowerLimitImposedByTempLimit(Decimal t, Decimal maxAllowedTemp, Decimal power , Decimal setpoint)
|
||||
{
|
||||
// const Int32 holdZone = 300;
|
||||
// const Int32 maxAllowedTemp = 315;
|
||||
|
||||
var kp = 0.05m;
|
||||
var error = setpoint - power;
|
||||
var controlOutput = (kp * error) *(1 - Math.Abs((t-307.5m)/7.5m));
|
||||
|
||||
return controlOutput;
|
||||
|
||||
// var a = holdZone - maxAllowedTemp;
|
||||
// var b = -a * maxAllowedTemp;
|
||||
}
|
||||
|
||||
internal static Decimal CalcMaxChargePower(this ModbusRegisters data)
|
||||
{
|
||||
var v = ReadVoltage(data);
|
||||
|
@ -133,13 +149,15 @@ public static class BatteryDataParser
|
|||
{
|
||||
var v = ReadVoltage(data);
|
||||
var i = ReadCurrent(data);
|
||||
var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400);
|
||||
|
||||
var pLimits = new[]
|
||||
{
|
||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin),
|
||||
CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax),
|
||||
CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin),
|
||||
CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax)
|
||||
CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax),
|
||||
// CalcPowerLimitImposedByTempLimit(t,315,300)
|
||||
};
|
||||
|
||||
var pLimit = pLimits.Max();
|
||||
|
|
|
@ -29,7 +29,4 @@ public static class Constants
|
|||
public const Decimal RIntMin = RStringMin / NumberOfStrings;
|
||||
public const Decimal RIntMax = RStringMax / NumberOfStrings;
|
||||
public const Decimal IMax = NumberOfStrings * IMaxPerString;
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="../../Utils/Utils.csproj" />
|
||||
<ProjectReference Include="../../Protocols/Modbus/Modbus.csproj" />
|
||||
<ProjectReference Include="../../StatusApi/StatusApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../Protocols/Modbus/Modbus.csproj" />
|
||||
<ProjectReference Include="../../../StatusApi/StatusApi.csproj" />
|
||||
<ProjectReference Include="../TruConvert/TruConvert.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ public record TruConvertAcControl
|
|||
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;} = 850;
|
||||
public UInt16 DcLinkMinVoltage { get; init;} = 830;
|
||||
public UInt16 DcLinkMaxVoltage { get; init;} = 870;
|
||||
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;
|
||||
|
|
|
@ -2,7 +2,10 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Phases;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using static DecimalMath.DecimalEx;
|
||||
using static InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.AcControlRegisters;
|
||||
|
||||
|
||||
|
@ -39,6 +42,8 @@ public class TruConvertAcDevice
|
|||
WriteRegs(CommunicationTimeout, c.CommunicationTimeout.TotalSeconds.ConvertTo<UInt16>());
|
||||
|
||||
WriteRegs(ConnectedSystemConfig, c.ConnectedSystemConfig);
|
||||
|
||||
|
||||
WriteCoils(PowerStageConfig, c.PowerStageEnable,
|
||||
c.SetValueConfig.ConvertTo<Boolean>(),
|
||||
c.ResetsAlarmAndWarning);
|
||||
|
@ -92,6 +97,8 @@ public class TruConvertAcDevice
|
|||
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 TruConvertAcStatus? ReadStatus()
|
||||
{
|
||||
try
|
||||
|
@ -112,6 +119,7 @@ public class TruConvertAcDevice
|
|||
{
|
||||
// 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);
|
||||
|
@ -143,84 +151,139 @@ public class TruConvertAcDevice
|
|||
.ToArray();
|
||||
|
||||
|
||||
return new TruConvertAcStatus
|
||||
{
|
||||
// acActualMainValues
|
||||
MainState = acActualMain.GetInt16(5001).ConvertTo<MainState>(),
|
||||
NumberOfConnectedSlaves = acActualMain.GetUInt16(5002),
|
||||
NumberOfConnectedSubSlaves = acActualMain.GetUInt16(5003),
|
||||
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;
|
||||
|
||||
//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
|
||||
|
||||
ApparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m, // in VA
|
||||
ApparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m, // in VA
|
||||
ApparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m, // in VA
|
||||
|
||||
AcDcOverloadIntegratorStatusL1 = acActualAcDc3.GetUInt16(5134) * 0.1m,
|
||||
AcDcOverloadIntegratorStatusL2 = acActualAcDc3.GetUInt16(5135) * 0.1m,
|
||||
AcDcOverloadIntegratorStatusL3 = acActualAcDc3.GetUInt16(5136) * 0.1m,
|
||||
|
||||
//acActualMeasurement
|
||||
PowerAcL1 = acActualMeasurement.GetInt16(5141) * 1m, // in Watt
|
||||
PowerAcL2 = acActualMeasurement.GetInt16(5142) * 1m, // in Watt
|
||||
PowerAcL3 = acActualMeasurement.GetInt16(5143) * 1m, // in Watt
|
||||
|
||||
// //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,
|
||||
// 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,
|
||||
// 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,
|
||||
// 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,
|
||||
|
||||
//acActualMeasurement10
|
||||
ActualDcLinkVoltageUpperHalf = acActualMeasurement8.GetUInt16(5211),
|
||||
ActualDcLinkVoltageLowerHalf = acActualMeasurement8.GetUInt16(5212),
|
||||
ActualDcLinkVoltageUpperHalfExt = acActualMeasurement8.GetUInt16(5213),
|
||||
ActualDcLinkVoltageLowerHalfExt = acActualMeasurement8.GetUInt16(5214),
|
||||
// //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,
|
||||
// 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 TruConvertAcStatus
|
||||
(
|
||||
Ac: new ThreePhaseAcConnection
|
||||
(
|
||||
AcPhase.FromActiveReactive(
|
||||
activePower: powerAcL1,
|
||||
apparentPower: apparentPowerAcL1,
|
||||
voltage: gridVoltageL1,
|
||||
current: phaseCurrentL1),
|
||||
|
||||
AcPhase.FromActiveReactive(
|
||||
activePower: powerAcL2,
|
||||
apparentPower: apparentPowerAcL2,
|
||||
voltage: gridVoltageL2,
|
||||
current: phaseCurrentL2),
|
||||
|
||||
AcPhase.FromActiveReactive(
|
||||
activePower: powerAcL3,
|
||||
apparentPower: apparentPowerAcL3,
|
||||
voltage: gridVoltageL3,
|
||||
current: phaseCurrentL3),
|
||||
|
||||
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,
|
||||
InletAirTemperature : acActualTemp.GetInt16(5501) * 0.1m,
|
||||
|
||||
Warnings = warnings,
|
||||
Alarms = alarms,
|
||||
|
||||
// acSetValues
|
||||
AcSignedPowerValue = acSetValues.GetInt16(4196) * -1.0m, // this is also used for control
|
||||
};
|
||||
Warnings : warnings,
|
||||
Alarms : alarms
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,60 +1,43 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Devices;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||
|
||||
using AlarmMessages = IReadOnlyList<AlarmMessage>;
|
||||
using WarningMessages = IReadOnlyList<WarningMessage>;
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public record TruConvertAcStatus
|
||||
(
|
||||
ThreePhaseAcConnection Ac,
|
||||
DcConnection Dc,
|
||||
String SerialNumber,
|
||||
MainState MainState,
|
||||
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; } // 5000
|
||||
public UInt16 NumberOfConnectedSlaves { get; init; } // 5001
|
||||
public UInt16 NumberOfConnectedSubSlaves { get; init; }
|
||||
public Decimal AcDcNominalGridFrequency { get; init; }
|
||||
public Decimal AcDcNominalGridVoltage { get; init; }
|
||||
public Decimal AcDcActNominalPower { get; init; }
|
||||
public AcDcGridType AcDcActiveGridType { get; init; }
|
||||
public Decimal AcDcPowerLimitingStatusAct { get; init; }
|
||||
public Decimal AcDcDcVoltageReference { get; init; }
|
||||
public Decimal AcDcDcLinkVoltageMinAct { get; init; }
|
||||
public Decimal AcDcDcLinkVoltageMaxAct { get; init; }
|
||||
public Decimal AcDcDcLinkChargedMinVoltage { get; init; }
|
||||
public Decimal AcDcStmActCustomer { get; init; }
|
||||
public Decimal ApparentPowerAcL1 { get; init; }
|
||||
public Decimal ApparentPowerAcL2 { get; init; }
|
||||
public Decimal ApparentPowerAcL3 { get; init; }
|
||||
public Decimal AcDcOverloadIntegratorStatusL1 { get; init; }
|
||||
public Decimal AcDcOverloadIntegratorStatusL2 { get; init; }
|
||||
public Decimal AcDcOverloadIntegratorStatusL3 { get; init; }
|
||||
public Decimal PowerAcL1 { get; init; }
|
||||
public Decimal PowerAcL2 { get; init; }
|
||||
public Decimal PowerAcL3 { get; init; }
|
||||
public Decimal PhaseCurrentL1 { get; init; }
|
||||
public Decimal PhaseCurrentL2 { get; init; }
|
||||
public Decimal PhaseCurrentL3 { get; init; }
|
||||
public Decimal GridVoltageL1 { get; init; }
|
||||
public Decimal GridVoltageL2 { get; init; }
|
||||
public Decimal GridVoltageL3 { get; init; }
|
||||
public Decimal CosPhiL1 { get; init; }
|
||||
public Decimal CosPhiL2 { get; init; }
|
||||
public Decimal CosPhiL3 { get; init; }
|
||||
public Decimal SumPowerL1 { get; init; }
|
||||
public Decimal SumPowerL2 { get; init; }
|
||||
public Decimal SumPowerL3 { get; init; }
|
||||
public Decimal GridFrequency { get; init; }
|
||||
public Decimal ActualDcLinkVoltageUpperHalf { get; init; }
|
||||
public Decimal ActualDcLinkVoltageLowerHalf { get; init; }
|
||||
public Decimal ActualDcLinkVoltageUpperHalfExt { get; init; }
|
||||
public Decimal ActualDcLinkVoltageLowerHalfExt { get; init; }
|
||||
public Decimal VoltageIntNtoPE { get; init; }
|
||||
public Decimal VoltageExtNtoPE { get; init; }
|
||||
public Decimal InletAirTemperature { get; init; }
|
||||
public WarningMessages Warnings { get; init; } = Array.Empty<WarningMessage>();
|
||||
public AlarmMessages Alarms { get; init; } = Array.Empty<AlarmMessage>();
|
||||
public Boolean PowerOperation { get; init; }
|
||||
public Decimal AcSignedPowerValue { get; init; }// this is in control but we also need to read data
|
||||
//public Int16 AcSignedPowerValue2 { get; init; } = 0; // For Test
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="../../../Protocols/Modbus/Modbus.csproj" />
|
||||
<ProjectReference Include="../TruConvert/TruConvert.csproj" />
|
||||
<ProjectReference Include="../../../StatusApi/StatusApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ public record TruConvertDcControl
|
|||
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 ;
|
||||
|
@ -36,9 +35,9 @@ public record TruConvertDcControl
|
|||
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;} = 0; // resolution : 0.1
|
||||
public Decimal UpperVoltageWindow { get; init;} = 0; // resolution : 0.1
|
||||
public Decimal LowerVoltageWindow { get; init;} = 0; // resolution : 0.1
|
||||
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);
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using static InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.DcControlRegisters;
|
||||
|
||||
|
@ -42,6 +43,7 @@ public class TruConvertDcDevice
|
|||
*/
|
||||
// TODO starting from 4000, evaluate what/if needs updating below 4000
|
||||
|
||||
WriteRegs(TimeoutCommunication, c.TimeoutForCommunication.TotalSeconds.ConvertTo<UInt16>());
|
||||
|
||||
WriteCoils(PowerStageOperation, c.PowerStageEnable);
|
||||
WriteCoils(ResetsAlarmAndWarning, c.ResetsAlarmAndWarning);
|
||||
|
@ -103,18 +105,14 @@ public class TruConvertDcDevice
|
|||
private TruConvertDcStatus TryReadStatus()
|
||||
{
|
||||
// Console.WriteLine("Reading DC Device");
|
||||
|
||||
var dcPrValMain = ModbusTcpClient.ReadInputRegisters(5001, 3);
|
||||
var dcBatteryValue = ModbusTcpClient.ReadInputRegisters(5101, 1);
|
||||
var dcBatteryValue2 = ModbusTcpClient.ReadInputRegisters(5111, 1);
|
||||
var dcBatteryValue3 = ModbusTcpClient.ReadInputRegisters(5114, 2);
|
||||
var dcBatteryValue4 = ModbusTcpClient.ReadInputRegisters(5121, 1);
|
||||
|
||||
var dcPrValDcDc = ModbusTcpClient.ReadInputRegisters(5124, 1);
|
||||
var dcPrValDcDc2 = ModbusTcpClient.ReadInputRegisters(5127, 2);
|
||||
|
||||
var dcTempValue = ModbusTcpClient.ReadInputRegisters(5511, 1);
|
||||
|
||||
var dcWarningValues = ModbusTcpClient.ReadInputRegisters(2404, 20);
|
||||
var dcAlarmValues = ModbusTcpClient.ReadInputRegisters(2811, 20);
|
||||
var dcSetValues = ModbusTcpClient.ReadInputRegisters(4001, 1);
|
||||
|
@ -133,37 +131,34 @@ public class TruConvertDcDevice
|
|||
|
||||
var dcCurrentLimitState = GetFlags(dcPrValDcDc.GetUInt16(5124)).ToArray();
|
||||
|
||||
var dcLinkVoltage = dcPrValDcDc2.GetUInt16(5128);
|
||||
|
||||
var dcPower = dcBatteryValue4.GetInt16(5121) * 1m;
|
||||
|
||||
var dcCurrent = dcLinkVoltage != 0m ? dcPower / dcLinkVoltage : 0m;
|
||||
|
||||
return new TruConvertDcStatus
|
||||
{
|
||||
// dcPrValMain
|
||||
MainState = (MainState) dcPrValMain.GetInt16(5001),
|
||||
NumberOfConnectedSlaves = dcPrValMain.GetUInt16(5002),
|
||||
NumberOfConnectedSubSlaves = dcPrValMain.GetUInt16(5003),
|
||||
(
|
||||
|
||||
// dcBatteryValue
|
||||
BatteryVoltage = dcBatteryValue.GetUInt16(5101) * 0.1m,
|
||||
BatteryCurrent = dcBatteryValue2.GetInt16(5111),
|
||||
Dc: new DcConnection
|
||||
(
|
||||
dcLinkVoltage,
|
||||
dcCurrent
|
||||
),
|
||||
|
||||
TotalDcPower = dcBatteryValue3.GetInt32(5114) * 1m, // Resolution is 0.001 (kW) in Tru convert DC doc, but we want it in W
|
||||
|
||||
DcPower = dcBatteryValue4.GetInt16(5121) * 1m, // Resolution is 0.001 (kW) in Tru convert DC doc, but we want it in W
|
||||
|
||||
// dcPrValDcDc
|
||||
StatusOfCurrentLimiting = dcCurrentLimitState,
|
||||
|
||||
// dcPrValDcDc2
|
||||
OverloadCapacity = dcPrValDcDc2.GetUInt16(5127) * 0.1m,
|
||||
DcLinkVoltage = dcPrValDcDc2.GetUInt16(5128),
|
||||
|
||||
//dcTempValue
|
||||
DcDcInletTemperature = dcTempValue.GetInt16(5511),
|
||||
|
||||
Warnings = warnings,
|
||||
Alarms = alarms,
|
||||
|
||||
// dcSetValues
|
||||
PowerOperation = dcSetValues.GetBoolean(4001)
|
||||
};
|
||||
MainState : (MainState)dcPrValMain.GetInt16(5001),
|
||||
NumberOfConnectedSlaves : dcPrValMain.GetUInt16(5002),
|
||||
NumberOfConnectedSubSlaves : dcPrValMain.GetUInt16(5003),
|
||||
BatteryVoltage : dcBatteryValue.GetUInt16(5101) * 0.1m,
|
||||
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,4 +1,6 @@
|
|||
using InnovEnergy.Lib.Devices.Trumpf.TruConvert;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Devices;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||
|
||||
|
@ -7,21 +9,19 @@ using WarningMessages = IReadOnlyList<WarningMessage>;
|
|||
using DcCurrentLimitStates = IReadOnlyList<DcCurrentLimitState>;
|
||||
|
||||
public record TruConvertDcStatus
|
||||
{
|
||||
public MainState MainState { get; init; }
|
||||
public UInt16 NumberOfConnectedSlaves { get; init; }
|
||||
public UInt16 NumberOfConnectedSubSlaves { get; init; }
|
||||
public Decimal BatteryVoltage { get; init; }
|
||||
public Decimal BatteryCurrent { get; init; }
|
||||
public Decimal TotalDcPower { get; init; }
|
||||
public Decimal DcPower { get; init; }
|
||||
public DcCurrentLimitStates StatusOfCurrentLimiting { get; init; } = Array.Empty<DcCurrentLimitState>();
|
||||
public Decimal OverloadCapacity { get; init; }
|
||||
public Decimal DcLinkVoltage { get; init; }
|
||||
public Decimal DcDcInletTemperature { get; init; }
|
||||
public AlarmMessages Alarms { get; init; } = Array.Empty<AlarmMessage>();
|
||||
public WarningMessages Warnings { get; init; } = Array.Empty<WarningMessage>();
|
||||
|
||||
public Boolean PowerOperation { get; init; }
|
||||
|
||||
}
|
||||
(
|
||||
DcConnection Dc,
|
||||
MainState MainState,
|
||||
UInt16 NumberOfConnectedSlaves,
|
||||
UInt16 NumberOfConnectedSubSlaves,
|
||||
Decimal BatteryVoltage,
|
||||
Decimal BatteryCurrent,
|
||||
Decimal TotalDcPower,
|
||||
DcCurrentLimitStates StatusOfCurrentLimiting,
|
||||
Decimal OverloadCapacity,
|
||||
Decimal DcDcInletTemperature,
|
||||
AlarmMessages Alarms,
|
||||
WarningMessages Warnings,
|
||||
Boolean PowerOperation
|
||||
):DcDevice(Dc)
|
||||
{}
|
|
@ -1,9 +1,8 @@
|
|||
using InnovEnergy.Lib.StatusApi.Phases;
|
||||
|
||||
namespace InnovEnergy.Lib.StatusApi.Connections;
|
||||
|
||||
|
||||
public record DcConnection(Decimal Voltage, Decimal Current) : Phase(Voltage, Current)
|
||||
{
|
||||
public Decimal Power => Current * Voltage;
|
||||
public Decimal Power => (Current * Voltage).Round3();
|
||||
}
|
|
@ -3,10 +3,10 @@ using InnovEnergy.Lib.StatusApi.Phases;
|
|||
namespace InnovEnergy.Lib.StatusApi.Connections;
|
||||
|
||||
public record SinglePhaseAcConnection
|
||||
(
|
||||
(
|
||||
Decimal Voltage,
|
||||
Decimal Current,
|
||||
Decimal Phi,
|
||||
Decimal Frequency
|
||||
)
|
||||
: AcPhase(Voltage, Current, Phi);
|
||||
);
|
||||
//: AcPhase(Voltage, Current, Phi);
|
|
@ -21,12 +21,12 @@ public record AcPhase
|
|||
public static AcPhase FromActiveReactive
|
||||
(
|
||||
Decimal activePower,
|
||||
Decimal reactivePower,
|
||||
Decimal apparentPower,
|
||||
Decimal voltage,
|
||||
Decimal current
|
||||
)
|
||||
{
|
||||
var apparentPower = Sqrt(activePower * activePower + reactivePower * reactivePower);
|
||||
var reactivePower = Sqrt(Math.Abs(apparentPower * apparentPower - activePower * activePower ));
|
||||
var phi = ATan2(reactivePower, activePower);
|
||||
|
||||
return new AcPhase
|
||||
|
@ -39,11 +39,10 @@ public record AcPhase
|
|||
ReactivePower: reactivePower,
|
||||
PowerFactor: Cos(phi)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static AcPhase FromVoltageCurrentPhi(Decimal voltage, Decimal current, Decimal phi)
|
||||
public static AcPhase CreateInstance(Decimal voltage, Decimal current, Decimal phi)
|
||||
{
|
||||
|
||||
var powerFactor = Cos(phi);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
namespace InnovEnergy.Lib.StatusApi;
|
||||
|
||||
public static class Utils
|
||||
{
|
||||
public static Decimal Round3(this Decimal d)
|
||||
{
|
||||
return d.RoundToSignificantFigures(3);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliWrap" Version="3.3.1" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue