Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(IndexRazor): display power buffer with edit option #1595

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 169 additions & 143 deletions TeslaSolarCharger/Client/Components/PowerFlowComponent.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,164 +5,175 @@

@inject HttpClient HttpClient
@inject IConstants Constants
@inject ISnackbar Snackbar
@implements IDisposable

@if (_pvValues != default)
{
<div class="text-center">
<svg width="420" height="@SvgHeight" viewBox="@($"0 0 420 {SvgHeight}")">
<!-- Lines -->
<!-- Grid to Solar -->
@if (GridLocation != default && InverterLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@InverterLocation.X" y2="@InverterLocation.Y" stroke="black" />
}
<!-- Grid to House -->
@if (GridLocation != default && HomeLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@HomeLocation.X" y2="@HomeLocation.Y" stroke="black" />
}
<!-- Solar to House -->
@if (InverterLocation != default && HomeLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@HomeLocation.X" y2="@HomeLocation.Y" stroke="black" />
}

<svg width="420" height="@SvgHeight" viewBox="@($"0 0 420 {SvgHeight}")">
<!-- Lines -->
<!-- Grid to Solar -->
@if (GridLocation != default && InverterLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@InverterLocation.X" y2="@InverterLocation.Y" stroke="black" />
}
<!-- Grid to House -->
@if (GridLocation != default && HomeLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@HomeLocation.X" y2="@HomeLocation.Y" stroke="black" />
}
<!-- Solar to House -->
@if (InverterLocation != default && HomeLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@HomeLocation.X" y2="@HomeLocation.Y" stroke="black" />
}
<!-- Solar to Home Battery -->
@if (InverterLocation != default && BatteryLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
<!-- Home Battery to House -->
@if (HomeLocation != default && BatteryLocation != default)
{
<line x1="@HomeLocation.X" y1="@HomeLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
<!-- Grid to Home Battery -->
@if (GridLocation != default && BatteryLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}

<!-- Solar to Home Battery -->
@if (InverterLocation != default && BatteryLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
<!-- Home Battery to House -->
@if (HomeLocation != default && BatteryLocation != default)
{
<line x1="@HomeLocation.X" y1="@HomeLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
<!-- Grid to Home Battery -->
@if (GridLocation != default && BatteryLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
<!-- Home to Charger -->
@if (HomeLocation != default && EvChargerLocation != default)
{
<line x1="@HomeLocation.X" y1="@HomeLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
}

<!-- Home to Charger -->
@if (HomeLocation != default && EvChargerLocation != default)
{
<line x1="@HomeLocation.X" y1="@HomeLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
}
@if (HomeLocation == default)
{
<!-- Grid to EvCharger -->
@if (GridLocation != default && EvChargerLocation != default)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
}
<!-- Solar to EVCharger -->
@if (InverterLocation != default && EvChargerLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
}
<!-- Home Battery to EVCharger -->
@if (EvChargerLocation != default && BatteryLocation != default)
{
<line x1="@EvChargerLocation.X" y1="@EvChargerLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
}
}

@if (HomeLocation == default)
{
<!-- Grid to EvCharger -->
@if (GridLocation != default && EvChargerLocation != default)

<!-- Animated balls -->
@foreach (var ball in Balls)
{
<line x1="@GridLocation.X" y1="@GridLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
<circle cx="@ball.X" cy="@ball.Y" r="5" fill="@ball.Color">
<animate attributeName="cx" from="@ball.StartX" to="@ball.EndX" dur="@ball.Duration" repeatCount="indefinite" />
<animate attributeName="cy" from="@ball.StartY" to="@ball.EndY" dur="@ball.Duration" repeatCount="indefinite" />
</circle>
}
<!-- Solar to EVCharger -->
@if (InverterLocation != default && EvChargerLocation != default)

<!-- Circles -->
<!-- Grid -->
@if (GridLocation != default)
{
<line x1="@InverterLocation.X" y1="@InverterLocation.Y" x2="@EvChargerLocation.X" y2="@EvChargerLocation.Y" stroke="black" />
<circle cx="@GridLocation.X" cy="@GridLocation.Y" r="40"
fill="@(_pvValues.GridPower == 0 ? "white" : (_pvValues.GridPower > 0 ? "lightgreen" : "#ff3030"))"
stroke="lightblue" stroke-width="4" />
}
<!-- Home Battery to EVCharger -->
@if (EvChargerLocation != default && BatteryLocation != default)
<!-- Solar -->
@if (InverterLocation != default)
{
<line x1="@EvChargerLocation.X" y1="@EvChargerLocation.Y" x2="@BatteryLocation.X" y2="@BatteryLocation.Y" stroke="black" />
<circle cx="@InverterLocation.X" cy="@InverterLocation.Y" r="40"
fill="@(_pvValues.InverterPower == 0 ? "white" : "orange")"
stroke="orange" stroke-width="4" />
}
<!-- Home Battery -->
@if (BatteryLocation != default)
{
<circle cx="@BatteryLocation.X" cy="@BatteryLocation.Y" r="40"
fill="@(_pvValues.HomeBatteryPower == 0 ? "white" : (_pvValues.HomeBatteryPower > 0 ? "lightgreen" : "#ff3030"))"
stroke="lightsalmon" stroke-width="4" />
}
<!-- House -->
@if (HomeLocation != default)
{
<circle cx="@HomeLocation.X" cy="@HomeLocation.Y" r="40"
fill="@(CalculateHomePower() == 0 ? "white" : "pink")"
stroke="pink" stroke-width="4" />
}
<!-- EVCharger -->
@if (EvChargerLocation != default)
{
<circle cx="@EvChargerLocation.X" cy="@EvChargerLocation.Y" r="40"
fill="@(_pvValues.CarCombinedChargingPowerAtHome == 0 ? "white" : "lightgrey")"
stroke="lightgrey" stroke-width="4" />
}
}


<!-- Animated balls -->
@foreach (var ball in Balls)
{
<circle cx="@ball.X" cy="@ball.Y" r="5" fill="@ball.Color">
<animate attributeName="cx" from="@ball.StartX" to="@ball.EndX" dur="@ball.Duration" repeatCount="indefinite" />
<animate attributeName="cy" from="@ball.StartY" to="@ball.EndY" dur="@ball.Duration" repeatCount="indefinite" />
</circle>
}

<!-- Circles -->
<!-- Grid -->
@if (GridLocation != default)
{
<circle cx="@GridLocation.X" cy="@GridLocation.Y" r="40"
fill="@(_pvValues.GridPower == 0 ? "white" : (_pvValues.GridPower > 0 ? "lightgreen" : "#ff3030"))"
stroke="lightblue" stroke-width="4" />
}
<!-- Solar -->
@if (InverterLocation != default)
{
<circle cx="@InverterLocation.X" cy="@InverterLocation.Y" r="40"
fill="@(_pvValues.InverterPower == 0 ? "white" : "orange")"
stroke="orange" stroke-width="4" />
}
<!-- Home Battery -->
@if (BatteryLocation != default)
{
<circle cx="@BatteryLocation.X" cy="@BatteryLocation.Y" r="40"
fill="@(_pvValues.HomeBatteryPower == 0 ? "white" : (_pvValues.HomeBatteryPower > 0 ? "lightgreen" : "#ff3030"))"
stroke="lightsalmon" stroke-width="4" />
}
<!-- House -->
@if (HomeLocation != default)
{
<circle cx="@HomeLocation.X" cy="@HomeLocation.Y" r="40"
fill="@(CalculateHomePower() == 0 ? "white" : "pink")"
stroke="pink" stroke-width="4" />
}
<!-- EVCharger -->
@if (EvChargerLocation != default)
{
<circle cx="@EvChargerLocation.X" cy="@EvChargerLocation.Y" r="40"
fill="@(_pvValues.CarCombinedChargingPowerAtHome == 0 ? "white" : "lightgrey")"
stroke="lightgrey" stroke-width="4" />
}
<!-- Text -->
@if (GridLocation != default)
{
<foreignObject x="@(GridLocation.X - CircleContentLocationDifference)" y="@(GridLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Constants.GridPoleIcon" Size="Size.Large" />
<div>@(Math.Abs(_pvValues.GridPower ?? 0)) W</div>
</div>
</foreignObject>
}
@if (InverterLocation != default)
{
<foreignObject x="@(InverterLocation.X - CircleContentLocationDifference)" y="@(InverterLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.WbSunny" Size="Size.Large" />
<div>@_pvValues.InverterPower W</div>
</div>
</foreignObject>
}
@if (BatteryLocation != default)
{
<foreignObject x="@(BatteryLocation.X - CircleContentLocationDifference)" y="@(BatteryLocation.Y - CircleContentLocationDifference + 10)" width="70" height="80">
<div style="text-align: center;">
<BatteryIcon StateOfCharge="@_pvValues.HomeBatterySoc" />
<div>@Math.Abs(_pvValues.HomeBatteryPower ?? 0) W</div>
</div>
</foreignObject>
}
@if (HomeLocation != default)
{
<foreignObject x="@(HomeLocation.X - CircleContentLocationDifference)" y="@(HomeLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.Home" Size="Size.Large" />
<div>@CalculateHomePower() W</div>
</div>
</foreignObject>
}
@if (EvChargerLocation != default)
{
<foreignObject x="@(EvChargerLocation.X - CircleContentLocationDifference)" y="@(EvChargerLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.EvStation" Size="Size.Large" />
<div>@_pvValues.CarCombinedChargingPowerAtHome W</div>
</div>
</foreignObject>
}
</svg>

<!-- Text -->
@if (GridLocation != default)
{
<foreignObject x="@(GridLocation.X - CircleContentLocationDifference)" y="@(GridLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Constants.GridPoleIcon" Size="Size.Large" />
<div>@(Math.Abs(_pvValues.GridPower ?? 0)) W</div>
</div>
</foreignObject>
}
@if (InverterLocation != default)
{
<foreignObject x="@(InverterLocation.X - CircleContentLocationDifference)" y="@(InverterLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.WbSunny" Size="Size.Large" />
<div>@_pvValues.InverterPower W</div>
</div>
</foreignObject>
}
@if (BatteryLocation != default)
{
<foreignObject x="@(BatteryLocation.X - CircleContentLocationDifference)" y="@(BatteryLocation.Y - CircleContentLocationDifference + 10)" width="70" height="80">
<div style="text-align: center;">
<BatteryIcon StateOfCharge="@_pvValues.HomeBatterySoc" />
<div>@Math.Abs(_pvValues.HomeBatteryPower ?? 0) W</div>
</div>
</foreignObject>
}
@if (HomeLocation != default)
{
<foreignObject x="@(HomeLocation.X - CircleContentLocationDifference)" y="@(HomeLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.Home" Size="Size.Large" />
<div>@CalculateHomePower() W</div>
</div>
</foreignObject>
}
@if (EvChargerLocation != default)
{
<foreignObject x="@(EvChargerLocation.X - CircleContentLocationDifference)" y="@(EvChargerLocation.Y - CircleContentLocationDifference)" width="70" height="80">
<div style="text-align: center;">
<MudIcon Icon="@Icons.Material.Filled.EvStation" Size="Size.Large" />
<div>@_pvValues.CarCombinedChargingPowerAtHome W</div>
</div>
</foreignObject>
}
</svg>
</div>
if (_pvValues.PowerBuffer != default && _pvValues.PowerBuffer != 0)
{
<div style="max-width: 200px; margin: 0 auto;">
<GenericInput T="int?"
For="() => _pvValues.PowerBuffer"
OnValueChanged="newValue => UpdatePowerBuffer(newValue)"></GenericInput>
</div>
}
}


Expand All @@ -187,7 +198,7 @@
_periodicTaskHelper = new();
_periodicTaskHelper.Start(RefreshPvValues, TimeSpan.FromSeconds(5));
}

private async Task RefreshPvValues()
{
try
Expand Down Expand Up @@ -629,4 +640,19 @@
var homePower = _pvValues.InverterPower - _pvValues.GridPower - homeBatteryPower - chargingPower;
return homePower;
}

private async Task UpdatePowerBuffer(int? newValue)
{
var response = await HttpClient.GetAsync($"api/BaseConfiguration/UpdatePowerBuffer?powerBuffer={newValue ?? 0}").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Snackbar.Add("Power Buffer updated", Severity.Success);
}
else
{
Snackbar.Add("Failed to update Power Buffer", Severity.Error);
}

}

}
2 changes: 1 addition & 1 deletion TeslaSolarCharger/Client/Pages/BaseConfiguration.razor
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ else
<InputComponent ValueId="powerBuffer"
LabelText="Power Buffer"
UnitText="W"
HelpText="Set values higher than 0 to always have some overage (power to grid). Set values lower than 0 to always consume some power from the grid.">
HelpText="Set values higher than 0 to always have some overage (power to grid). Set values lower than 0 to always consume some power from the grid. Note: The power buffer you see on the home page is replaced with this value after a TSC restart. Do only change this value if you want a permanent change. Frequent Base Configuration changes are not recommended. If you can not see a power buffer value on the homepage, set the power buffer here to 1 as on the homepage it is only displayed if different from zero.">
<InputFragment>
<InputNumber id="powerBuffer" @bind-Value="_dtoBaseConfiguration.PowerBuffer" placeholder=" " class="form-control" />
</InputFragment>
Expand Down
4 changes: 1 addition & 3 deletions TeslaSolarCharger/Client/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@
<BackendInformationDisplayComponent></BackendInformationDisplayComponent>
<LoggedErrorsComponent></LoggedErrorsComponent>

<div class="d-flex justify-content-center align-items-center">
<PowerFlowComponent></PowerFlowComponent>
</div>
<PowerFlowComponent></PowerFlowComponent>


@if (_carBaseStates == null || _carBaseSettings == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace TeslaSolarCharger.Shared.Dtos.IndexRazor.PvValues;
using TeslaSolarCharger.Shared.Attributes;

namespace TeslaSolarCharger.Shared.Dtos.IndexRazor.PvValues;

//Attention: this also is implemented in TeslaSolarCharger.SharedBackend.Dtos. Can not be combined as this would result in UI needing all dependecies of SharedBackend project
public class DtoPvValues
Expand All @@ -7,6 +9,7 @@ public class DtoPvValues
public int? GridPower { get; set; }
public int? HomeBatteryPower { get; set; }
public int? HomeBatterySoc { get; set; }
[Postfix("W")]
public int? PowerBuffer { get; set; }
public int? CarCombinedChargingPowerAtHome { get; set; }
public DateTimeOffset? LastUpdated { get; set; }
Expand Down
Loading