inverter testing passed
This commit is contained in:
parent
d498e8624a
commit
80caa1c631
@ -62,8 +62,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="row h-100 align-content-center">
|
<div class="row h-100 align-content-center">
|
||||||
<span class="fs-5 @TemperatureCss()">
|
<span class="fs-6 text-muted">
|
||||||
@(status?.HeatSinkTemperature) C°
|
@(status?.WorkingMode)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -205,16 +205,6 @@
|
|||||||
private static double RoundToOneDecimal(double? val)
|
private static double RoundToOneDecimal(double? val)
|
||||||
=> Math.Round(val ?? 0, 1);
|
=> Math.Round(val ?? 0, 1);
|
||||||
|
|
||||||
private static string TemperatureCss()
|
|
||||||
{
|
|
||||||
return status?.HeatSinkTemperature switch
|
|
||||||
{
|
|
||||||
>= 55 and < 65 => "text-danger",
|
|
||||||
>= 65 => "text-danger fw-bolder blinktext",
|
|
||||||
_ => "text-muted"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task StartStatusStreaming(string basePath)
|
public static async Task StartStatusStreaming(string basePath)
|
||||||
{
|
{
|
||||||
//note: only reason we have a full-time stream download is because there's a bug in
|
//note: only reason we have a full-time stream download is because there's a bug in
|
||||||
|
|||||||
@ -375,11 +375,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetChargeCurrent(Setting settingName, byte value)
|
private async Task SetChargeCurrent(Setting setting, byte value)
|
||||||
{
|
{
|
||||||
isSuccess = false;
|
isSuccess = false;
|
||||||
|
|
||||||
switch (settingName)
|
switch (setting)
|
||||||
{
|
{
|
||||||
case Setting.CombinedChargeCurrent:
|
case Setting.CombinedChargeCurrent:
|
||||||
currentButton = Button.MaxCombinedChargeCurrent;
|
currentButton = Button.MaxCombinedChargeCurrent;
|
||||||
@ -392,10 +392,12 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await Http.GetStringAsync($"api/settings/set-setting/{settingName}/{value}") == "true")
|
var xxx = $"api/settings/set-setting/{setting}/{value}";
|
||||||
|
|
||||||
|
if (await Http.GetStringAsync($"api/settings/set-setting/{setting}/{value}") == "true")
|
||||||
{
|
{
|
||||||
isSuccess = true;
|
isSuccess = true;
|
||||||
UpdateLocalSetting(settingName, value);
|
UpdateLocalSetting(setting, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ namespace InverterMon.Server.Endpoints.GetStatus;
|
|||||||
public class Endpoint : EndpointWithoutRequest<object>
|
public class Endpoint : EndpointWithoutRequest<object>
|
||||||
{
|
{
|
||||||
public FelicitySolarInverter Inverter { get; set; } = null!;
|
public FelicitySolarInverter Inverter { get; set; } = null!;
|
||||||
|
public IHostApplicationLifetime AppLife { get; set; } = null!;
|
||||||
|
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
@ -28,32 +29,32 @@ public class Endpoint : EndpointWithoutRequest<object>
|
|||||||
|
|
||||||
async IAsyncEnumerable<InverterStatus> GetDataStream([EnumeratorCancellation] CancellationToken c)
|
async IAsyncEnumerable<InverterStatus> GetDataStream([EnumeratorCancellation] CancellationToken c)
|
||||||
{
|
{
|
||||||
while (!c.IsCancellationRequested)
|
while (!c.IsCancellationRequested && !AppLife.ApplicationStopping.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (Env.IsDevelopment())
|
// if (Env.IsDevelopment())
|
||||||
{
|
// {
|
||||||
var status = new InverterStatus
|
// var status = new InverterStatus
|
||||||
{
|
// {
|
||||||
OutputVoltage = Random.Shared.Next(240),
|
// OutputVoltage = Random.Shared.Next(240),
|
||||||
LoadWatts = Random.Shared.Next(3500),
|
// LoadWatts = Random.Shared.Next(3500),
|
||||||
LoadPercentage = Random.Shared.Next(100),
|
// LoadPercentage = Random.Shared.Next(100),
|
||||||
BatteryVoltage = Random.Shared.Next(24),
|
// BatteryVoltage = Random.Shared.Next(24),
|
||||||
BatteryChargeCurrent = Random.Shared.Next(20),
|
// BatteryChargeCurrent = Random.Shared.Next(20),
|
||||||
BatteryDischargeCurrent = Random.Shared.Next(300),
|
// BatteryDischargeCurrent = Random.Shared.Next(300),
|
||||||
HeatSinkTemperature = Random.Shared.Next(300),
|
// HeatSinkTemperature = Random.Shared.Next(300),
|
||||||
PVInputCurrent = Random.Shared.Next(300),
|
// PVInputCurrent = Random.Shared.Next(300),
|
||||||
PVInputVoltage = Random.Shared.Next(300),
|
// PVInputVoltage = Random.Shared.Next(300),
|
||||||
PVInputWatt = Random.Shared.Next(1000),
|
// PVInputWatt = Random.Shared.Next(1000),
|
||||||
PV_MaxCapacity = 1000,
|
// PV_MaxCapacity = 1000,
|
||||||
BatteryCapacity = 100
|
// BatteryCapacity = 100
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
|
// yield return status;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
yield return Inverter.Status;
|
||||||
|
|
||||||
yield return status;
|
await Task.Delay(2000, c);
|
||||||
}
|
|
||||||
else
|
|
||||||
yield return Inverter.Status;
|
|
||||||
|
|
||||||
await Task.Delay(1000, c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,25 +17,25 @@ public class Endpoint : EndpointWithoutRequest<CurrentSettings>
|
|||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken c)
|
public override async Task HandleAsync(CancellationToken c)
|
||||||
{
|
{
|
||||||
if (Env.IsDevelopment())
|
// if (Env.IsDevelopment())
|
||||||
{
|
// {
|
||||||
var res = new CurrentSettings
|
// var res = new CurrentSettings
|
||||||
{
|
// {
|
||||||
BackToBatteryVoltage = 48.1,
|
// BackToBatteryVoltage = 48.1,
|
||||||
BackToGridVoltage = 48.2,
|
// BackToGridVoltage = 48.2,
|
||||||
FloatChargeVoltage = 48.3,
|
// FloatChargeVoltage = 48.3,
|
||||||
ChargePriority = ChargePriority.OnlySolar,
|
// ChargePriority = ChargePriority.OnlySolar,
|
||||||
DischargeCuttOffVoltage = 48.4,
|
// DischargeCuttOffVoltage = 48.4,
|
||||||
BulkChargeVoltage = 48.5,
|
// BulkChargeVoltage = 48.5,
|
||||||
MaxACChargeCurrent = 10,
|
// MaxACChargeCurrent = 10,
|
||||||
MaxCombinedChargeCurrent = 20,
|
// MaxCombinedChargeCurrent = 20,
|
||||||
OutputPriority = OutputPriority.SolarFirst,
|
// OutputPriority = OutputPriority.SolarFirst,
|
||||||
SystemSpec = UserSettings.ToSystemSpec()
|
// SystemSpec = UserSettings.ToSystemSpec()
|
||||||
};
|
// };
|
||||||
await SendAsync(res, cancellation: c);
|
// await SendAsync(res, cancellation: c);
|
||||||
|
//
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,16 +14,17 @@ public class Endpoint : Endpoint<Shared.Models.SetSetting, bool>
|
|||||||
|
|
||||||
public override async Task HandleAsync(Shared.Models.SetSetting r, CancellationToken c)
|
public override async Task HandleAsync(Shared.Models.SetSetting r, CancellationToken c)
|
||||||
{
|
{
|
||||||
if (Env.IsDevelopment())
|
// if (Env.IsDevelopment())
|
||||||
{
|
// {
|
||||||
await SendAsync(true, cancellation: c);
|
// await SendAsync(true, cancellation: c);
|
||||||
|
//
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Inverter.SetSetting(r.Setting, r.Value);
|
Inverter.SetSetting(r.Setting, r.Value);
|
||||||
|
await SendAsync(true, cancellation: c);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,19 +57,39 @@ public sealed class FelicitySolarInverter
|
|||||||
{
|
{
|
||||||
var regs = ReadRegisters(StatusStartAddress, StatusRegisterCount);
|
var regs = ReadRegisters(StatusStartAddress, StatusRegisterCount);
|
||||||
|
|
||||||
// WorkingMode = regs[0], // 0x1101: Working mode (offset 0)
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (!_serialPort.IsOpen)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// BatteryChargingStage = regs[1], // 0x1102: Battery charging stage (offset 1)
|
// BatteryChargingStage = regs[1], // 0x1102: Battery charging stage (offset 1)
|
||||||
|
|
||||||
Status.BatteryVoltage = regs[7] / 100.0; // 0x1108: Battery voltage (offset 0x1108 - 0x1101 = 7)
|
Status.WorkingMode = (WorkingMode)regs[0]; // 0x1101: Working mode (offset 0)
|
||||||
Status.BatteryDischargeCurrent = regs[8]; // 0x1109: Battery current (offset 8) -- signed value
|
Status.BatteryVoltage = regs[7] / 100.0; // 0x1108: Battery voltage (offset 0x1108 - 0x1101 = 7)
|
||||||
Status.BatteryChargeCurrent = regs[8]; // 0x1109: Battery current (offset 8) -- signed value
|
|
||||||
Status.BatteryDischargeWatts = regs[9]; // 0x110A: Battery power (offset 9) -- signed value
|
var disCur = ChargeStatus(regs[8]); // 0x1109: Battery current (offset 8) -- signed value
|
||||||
Status.BatteryChargeWatts = regs[9]; // 0x110A: Battery power (offset 9) -- signed value
|
Status.BatteryDischargeCurrent = disCur.IsDischarge ? disCur.PositiveValue : 0;
|
||||||
Status.OutputVoltage = regs[16] / 10.0; // 0x1111: AC output voltage (offset 0x1111 - 0x1101 = 16)
|
Status.BatteryChargeCurrent = disCur.IsDischarge is false ? disCur.PositiveValue : 0;
|
||||||
Status.LoadWatts = regs[29]; // 0x111E: AC output active power (offset 0x111E - 0x1101 = 29)
|
|
||||||
Status.LoadPercentage = regs[31]; // 0x1120: Load percentage (offset 0x1120 - 0x1101 = 31)
|
var disPow = ChargeStatus(regs[9]); // 0x110A: Battery power (offset 9) -- signed value
|
||||||
Status.PVInputVoltage = regs[37] / 10.0; // 0x1126: PV input voltage (offset 0x1126 - 0x1101 = 37)
|
Status.BatteryDischargeWatts = disPow.IsDischarge ? disPow.PositiveValue : 0;
|
||||||
Status.PVInputWatt = regs[41]; // 0x112A: PV input power (offset 0x112A - 0x1101 = 41) -- signed value
|
Status.BatteryChargeWatts = disPow.IsDischarge is false ? disPow.PositiveValue : 0;
|
||||||
|
|
||||||
|
Status.OutputVoltage = regs[16] / 10.0; // 0x1111: AC output voltage (offset 0x1111 - 0x1101 = 16)
|
||||||
|
Status.GridVoltage = regs[22] / 10.0; // 0x1111: AC output voltage (offset 0x1117 - 0x1101 = 22)
|
||||||
|
Status.LoadWatts = regs[29]; // 0x111E: AC output active power (offset 0x111E - 0x1101 = 29)
|
||||||
|
Status.LoadPercentage = regs[31]; // 0x1120: Load percentage (offset 0x1120 - 0x1101 = 31)
|
||||||
|
Status.PVInputVoltage = regs[37] / 10.0; // 0x1126: PV input voltage (offset 0x1126 - 0x1101 = 37)
|
||||||
|
Status.PVInputWatt = regs[41]; // 0x112A: PV input power (offset 0x112A - 0x1101 = 41) -- signed value
|
||||||
|
|
||||||
|
static (bool IsDischarge, short PositiveValue) ChargeStatus(short value)
|
||||||
|
{
|
||||||
|
var isNegative = value < 0;
|
||||||
|
var positiveValue = isNegative ? (short)-value : value;
|
||||||
|
|
||||||
|
return (isNegative, positiveValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The settings registers we need are located between 0x211F and 0x2159.
|
// The settings registers we need are located between 0x211F and 0x2159.
|
||||||
@ -206,6 +226,9 @@ public sealed class FelicitySolarInverter
|
|||||||
|
|
||||||
var response = SendModbusRequest(frame);
|
var response = SendModbusRequest(frame);
|
||||||
|
|
||||||
|
if (response.Length == 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
// Expected response structure:
|
// Expected response structure:
|
||||||
// [Slave Address][Function Code][Byte Count][Data...][CRC Lo][CRC Hi]
|
// [Slave Address][Function Code][Byte Count][Data...][CRC Lo][CRC Hi]
|
||||||
|
|
||||||
@ -228,6 +251,9 @@ public sealed class FelicitySolarInverter
|
|||||||
{
|
{
|
||||||
lock (_lock) //prevent concurrent access
|
lock (_lock) //prevent concurrent access
|
||||||
{
|
{
|
||||||
|
if (!_serialPort.IsOpen)
|
||||||
|
return [];
|
||||||
|
|
||||||
_serialPort.DiscardInBuffer();
|
_serialPort.DiscardInBuffer();
|
||||||
_serialPort.DiscardOutBuffer();
|
_serialPort.DiscardOutBuffer();
|
||||||
|
|
||||||
|
|||||||
@ -22,9 +22,11 @@ class StatusRetriever(
|
|||||||
await Task.Delay(5000);
|
await Task.Delay(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.LogInformation("Connected to inverter at device address: [{port}]", port);
|
||||||
|
|
||||||
appLife.ApplicationStopping.Register(inverter.Close);
|
appLife.ApplicationStopping.Register(inverter.Close);
|
||||||
|
|
||||||
while (!c.IsCancellationRequested)
|
while (!c.IsCancellationRequested && !appLife.ApplicationStopping.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
inverter.Status.BatteryCapacity = userSettings.BatteryCapacity;
|
inverter.Status.BatteryCapacity = userSettings.BatteryCapacity;
|
||||||
inverter.Status.PV_MaxCapacity = userSettings.PV_MaxCapacity;
|
inverter.Status.PV_MaxCapacity = userSettings.PV_MaxCapacity;
|
||||||
@ -41,9 +43,16 @@ class StatusRetriever(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.UpdateTodaysPvGeneration(c);
|
try
|
||||||
|
{
|
||||||
|
db.UpdateTodaysPvGeneration(c);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(2000);
|
await Task.Delay(2000, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,7 +8,7 @@ public class UserSettings
|
|||||||
public int Id { get; set; } = 1;
|
public int Id { get; set; } = 1;
|
||||||
public int PV_MaxCapacity { get; set; } = 1000;
|
public int PV_MaxCapacity { get; set; } = 1000;
|
||||||
public int BatteryCapacity { get; set; } = 100;
|
public int BatteryCapacity { get; set; } = 100;
|
||||||
public float BatteryNominalVoltage { get; set; } = 25.6f;
|
public double BatteryNominalVoltage { get; set; } = 25.6f;
|
||||||
public int SunlightStartHour { get; set; } = 6;
|
public int SunlightStartHour { get; set; } = 6;
|
||||||
public int SunlightEndHour { get; set; } = 18;
|
public int SunlightEndHour { get; set; } = 18;
|
||||||
public int[] PVGraphRange => new[] { 0, (SunlightEndHour - SunlightStartHour) * 60 };
|
public int[] PVGraphRange => new[] { 0, (SunlightEndHour - SunlightStartHour) * 60 };
|
||||||
|
|||||||
@ -23,11 +23,12 @@ bld.Services
|
|||||||
.AddSingleton<FelicitySolarInverter>()
|
.AddSingleton<FelicitySolarInverter>()
|
||||||
.AddSingleton<JkBms>();
|
.AddSingleton<JkBms>();
|
||||||
|
|
||||||
if (!bld.Environment.IsDevelopment())
|
// if (!bld.Environment.IsDevelopment())
|
||||||
{
|
// {
|
||||||
bld.Services
|
bld.Services
|
||||||
.AddHostedService<StatusRetriever>();
|
.AddHostedService<StatusRetriever>();
|
||||||
}
|
|
||||||
|
// }
|
||||||
|
|
||||||
bld.Services.AddFastEndpoints(o => o.SourceGeneratorDiscoveredTypes = DiscoveredTypes.All);
|
bld.Services.AddFastEndpoints(o => o.SourceGeneratorDiscoveredTypes = DiscoveredTypes.All);
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||||
"applicationUrl": "http://localhost:80;https://localhost:443",
|
"applicationUrl": "http://localhost:80",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,15 +1,12 @@
|
|||||||
{
|
{
|
||||||
"LaunchSettings": {
|
"LaunchSettings": {
|
||||||
"DeviceAddress": "/dev/ttyUSB1",
|
"DeviceAddress": "COM3",
|
||||||
"JkBmsAddress": "/dev/ttyUSB0",
|
"JkBmsAddress": "/dev/ttyUSB0",
|
||||||
"WebPort": 80
|
"WebPort": 80
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information"
|
||||||
"Microsoft.AspNetCore": "Debug",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Debug",
|
|
||||||
"FastEndpoints.StartupTimer": "Debug"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ public class BMSStatus
|
|||||||
public double AvgPowerWatts => Math.Round(AvgCurrentAmps * PackVoltage, 0, MidpointRounding.AwayFromZero);
|
public double AvgPowerWatts => Math.Round(AvgCurrentAmps * PackVoltage, 0, MidpointRounding.AwayFromZero);
|
||||||
|
|
||||||
[JsonPropertyName("u")]
|
[JsonPropertyName("u")]
|
||||||
public float PackNominalVoltage { get; set; }
|
public double PackNominalVoltage { get; set; }
|
||||||
|
|
||||||
public string GetTimeString()
|
public string GetTimeString()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -11,4 +11,15 @@ public enum Setting
|
|||||||
DischargeCutOff = 7,
|
DischargeCutOff = 7,
|
||||||
BackToGrid = 8,
|
BackToGrid = 8,
|
||||||
BackToBattery = 9
|
BackToBattery = 9
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum WorkingMode
|
||||||
|
{
|
||||||
|
POWER = 0,
|
||||||
|
STANDBY = 1,
|
||||||
|
BYPASS = 2,
|
||||||
|
BATTERY = 3,
|
||||||
|
FAULT = 4,
|
||||||
|
LINE = 5,
|
||||||
|
CHARGING = 6
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ public class InverterStatus
|
|||||||
public double GridVoltage { get; set; }
|
public double GridVoltage { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("l")]
|
[JsonPropertyName("l")]
|
||||||
public int HeatSinkTemperature { get; set; }
|
public WorkingMode WorkingMode { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("m")]
|
[JsonPropertyName("m")]
|
||||||
public double LoadCurrent => LoadWatts == 0 ? 0 : LoadWatts / OutputVoltage;
|
public double LoadCurrent => LoadWatts == 0 ? 0 : LoadWatts / OutputVoltage;
|
||||||
@ -69,7 +69,7 @@ public class InverterStatus
|
|||||||
|
|
||||||
pvInputWatt = value;
|
pvInputWatt = value;
|
||||||
var interval = (DateTime.Now - pvInputWattHourLastComputed).TotalSeconds;
|
var interval = (DateTime.Now - pvInputWattHourLastComputed).TotalSeconds;
|
||||||
PVInputWattHour += value / (3600 / Convert.ToDouble(interval));
|
PVInputWattHour += value / (3600 / interval);
|
||||||
pvInputWattHourLastComputed = DateTime.Now;
|
pvInputWattHourLastComputed = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ public class InverterStatus
|
|||||||
public int PV_MaxCapacity { get; set; }
|
public int PV_MaxCapacity { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("v")]
|
[JsonPropertyName("v")]
|
||||||
public int PVPotential => PVInputWatt > 0 ? Convert.ToInt32(Convert.ToDouble(PVInputWatt) / PV_MaxCapacity * 100) : 0;
|
public int PVPotential => PVInputWatt > 0 ? Convert.ToInt32(PVInputWatt / PV_MaxCapacity * 100) : 0;
|
||||||
|
|
||||||
int pvInputWatt;
|
int pvInputWatt;
|
||||||
DateTime pvInputWattHourLastComputed;
|
DateTime pvInputWattHourLastComputed;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ public class SystemSpec
|
|||||||
{
|
{
|
||||||
public int PV_MaxCapacity { get; set; } = 1000;
|
public int PV_MaxCapacity { get; set; } = 1000;
|
||||||
public int BatteryCapacity { get; set; } = 100;
|
public int BatteryCapacity { get; set; } = 100;
|
||||||
public float BatteryNominalVoltage { get; set; } = 25.6f;
|
public double BatteryNominalVoltage { get; set; } = 25.6f;
|
||||||
public int SunlightStartHour { get; set; } = 6;
|
public int SunlightStartHour { get; set; } = 6;
|
||||||
public int SunlightEndHour { get; set; } = 18;
|
public int SunlightEndHour { get; set; } = 18;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user