show sum battery power and avg soc on Live View for Sodistore Home, Pro, Grid

This commit is contained in:
Yinyin Liu 2026-04-14 16:18:57 +02:00
parent 5bced9374b
commit dde3b9794c
3 changed files with 32 additions and 56 deletions

View File

@ -25,6 +25,7 @@ import Information from '../Information/Information';
import { UserType } from '../../../interfaces/UserTypes'; import { UserType } from '../../../interfaces/UserTypes';
import HistoryOfActions from '../History/History'; import HistoryOfActions from '../History/History';
import Topology from '../Topology/Topology'; import Topology from '../Topology/Topology';
import TopologySodistoreHome from '../Topology/TopologySodistoreHome';
import BatteryView from '../BatteryView/BatteryView'; import BatteryView from '../BatteryView/BatteryView';
import Configuration from '../Configuration/Configuration'; import Configuration from '../Configuration/Configuration';
import PvView from '../PvView/PvView'; import PvView from '../PvView/PvView';
@ -465,20 +466,12 @@ function Installation(props: singleInstallationProps) {
path={routes.live} path={routes.live}
element={ element={
props.current_installation.product === 4 ? ( props.current_installation.product === 4 ? (
// TODO: SodistoreGrid — implement actual topology layout <TopologySodistoreHome
<Container values={values}
maxWidth="xl" connected={connected}
sx={{ loading={loading}
display: 'flex', batteryClusterNumber={props.current_installation.batteryClusterNumber}
justifyContent: 'center', ></TopologySodistoreHome>
alignItems: 'center',
height: '40vh'
}}
>
<Typography variant="body1" color="text.secondary">
Live view coming soon
</Typography>
</Container>
) : ( ) : (
<Topology <Topology
values={values} values={values}

View File

@ -65,6 +65,14 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
const totalGridPower: number = const totalGridPower: number =
inv?.TotalGridPower ?? inv?.GridPower ?? 0; inv?.TotalGridPower ?? inv?.GridPower ?? 0;
const avgBatterySoc: number = hasDevices
? (inv?.AvgBatterySoc ?? 0)
: (() => {
const socs = Array.from({ length: props.batteryClusterNumber })
.map((_, i) => Number(inv?.[`Battery${i + 1}Soc`]) || 0);
return socs.length ? socs.reduce((s, v) => s + v, 0) / socs.length : 0;
})();
return ( return (
<Container maxWidth="xl" style={{ backgroundColor: 'white' }}> <Container maxWidth="xl" style={{ backgroundColor: 'white' }}>
<Grid container> <Grid container>
@ -255,42 +263,20 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
isFirst={false} isFirst={false}
/> />
{/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/} {/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/}
{Array.from({ length: props.batteryClusterNumber }).map((_, index) => { <TopologyColumn
let soc: number; centerBox={{
let power: number; title: 'Battery',
data: inv
if (hasDevices) { ? [
// Sinexcel: map across devices — 0→D1/B1, 1→D1/B2, 2→D2/B1, 3→D2/B2 { value: avgBatterySoc, unit: '%' },
const deviceId = String(Math.floor(index / 2) + 1); { value: totalBatteryPower, unit: 'W' }
const batteryIndex = (index % 2) + 1; ]
const device = inv?.Devices?.[deviceId]; : undefined,
soc = device?.[`Battery${batteryIndex}Soc`] ?? device?.[`Battery${batteryIndex}SocSecondvalue`] ?? 0; connected: true
power = device?.[`Battery${batteryIndex}Power`] ?? 0; }}
} else { isFirst={false}
// Growatt: flat Battery1, Battery2, ... isLast={true}
const i = index + 1; />
soc = Number(inv?.[`Battery${i}Soc`]) || 0;
power = Number(inv?.[`Battery${i}Power`]) || 0;
}
return (
<TopologyColumn
key={index + 1}
centerBox={{
title: `Battery C${index + 1}`,
data: inv
? [
{ value: soc, unit: '%' },
{ value: power, unit: 'W' }
]
: undefined,
connected: true
}}
isFirst={false}
isLast={true}
/>
);
})}
</Grid> </Grid>
</> </>
)} )}

View File

@ -257,14 +257,11 @@ function TopologyBox(props: TopologyBoxProps) {
}} }}
> >
{props.data.map((boxData, index) => { {props.data.map((boxData, index) => {
const formatted = formatPower(boxData.value, boxData.unit);
return ( return (
<Typography key={index}> <Typography key={index}>
{formatPower(boxData.value, boxData.unit) === 0 {formatted === 0 ? '0 ' : formatted}
? null {boxData.unit}
: formatPower(boxData.value, boxData.unit)}
{formatPower(boxData.value, boxData.unit) === 0
? null
: boxData.unit}
</Typography> </Typography>
); );
})} })}