diff --git a/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryViewSodioHome.tsx b/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryViewSodioHome.tsx index 6c5a1eb4b..21de1ca34 100644 --- a/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryViewSodioHome.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryViewSodioHome.tsx @@ -38,20 +38,41 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) { const navigate = useNavigate(); const inverter = (props.values as any)?.InverterRecord; const batteryClusterNumber = props.installation.batteryClusterNumber; + + const hasDevices = !!inverter?.Devices; + const sortedBatteryView = inverter ? Array.from({ length: batteryClusterNumber }, (_, i) => { - const index = i + 1; // Battery1, Battery2, ... + if (hasDevices) { + // Sinexcel: map across devices — 0→D1/B1, 1→D1/B2, 2→D2/B1, 3→D2/B2 + const deviceId = String(Math.floor(i / 2) + 1); + const batteryIndex = (i % 2) + 1; + const device = inverter.Devices[deviceId]; - return { - BatteryId: String(index), - battery: { - Voltage: inverter[`Battery${index}Voltage`], - Current: inverter[`Battery${index}Current`], - Power: inverter[`Battery${index}Power`], - Soc: inverter[`Battery${index}Soc`], - Soh: inverter[`Battery${index}Soh`], - } - }; + return { + BatteryId: String(i + 1), + battery: { + Voltage: device?.[`Battery${batteryIndex}PackTotalVoltage`] ?? 0, + Current: device?.[`Battery${batteryIndex}PackTotalCurrent`] ?? 0, + Power: device?.[`Battery${batteryIndex}Power`] ?? 0, + Soc: device?.[`Battery${batteryIndex}Soc`] ?? device?.[`Battery${batteryIndex}SocSecondvalue`] ?? 0, + Soh: device?.[`Battery${batteryIndex}Soh`] ?? 0, + } + }; + } else { + // Growatt: flat Battery1, Battery2, ... + const index = i + 1; + return { + BatteryId: String(index), + battery: { + Voltage: inverter[`Battery${index}Voltage`] ?? 0, + Current: inverter[`Battery${index}Current`] ?? 0, + Power: inverter[`Battery${index}Power`] ?? 0, + Soc: inverter[`Battery${index}Soc`] ?? 0, + Soh: inverter[`Battery${index}Soh`] ?? 0, + } + }; + } }) : []; diff --git a/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx b/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx index c3990e84b..0f8124d56 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx @@ -437,23 +437,76 @@ export interface JSONRecordData { }; }; - // For SodistoreHome + // For SodistoreHome (Sinexcel multi-inverter structure) InverterRecord: { - GridPower:number; - Battery1Power:number; - Battery1Soc:number; - Battery1Soh:number; - Battery1Voltage:number; - Battery1Current:number; - Battery2Power:number; - Battery2Soc:number; - Battery2Voltage:number; - Battery2Current:number; - Battery2Soh:number; - PvPower:number; - ConsumptionPower:number; - WorkingMode?:string; - OperatingMode?:string; + // Top-level aggregated values + TotalPhotovoltaicPower: number; + TotalBatteryPower: number; + TotalLoadPower: number; + TotalGridPower: number; + AvgBatteryVoltage: number; + TotalBatteryCurrent: number; + AvgBatterySoc: number; + AvgBatterySoh: number; + AvgBatteryTemp: number; + OperatingPriority?: string; + MinSoc: number; + MaxChargeCurrent: number; + MaxDischargingCurrent: number; + GridPower: number; + GridFrequency: number; + InverterPower: number; + EnableGridExport?: string; + GridExportPower: number; + // Legacy flat fields (Growatt compatibility) + Battery1Power?: number; + Battery1Soc?: number; + Battery1Soh?: number; + Battery1Voltage?: number; + Battery1Current?: number; + Battery2Power?: number; + Battery2Soc?: number; + Battery2Voltage?: number; + Battery2Current?: number; + Battery2Soh?: number; + PvPower?: number; + ConsumptionPower?: number; + WorkingMode?: string; + OperatingMode?: string; + PvTotalPower?: number; + Battery1AmbientTemperature?: number; + Battery1Temperature?: number; + // Per-device records (Sinexcel multi-inverter) + Devices?: { + [deviceId: string]: { + Battery1Power: number; + Battery1Soc: number; + Battery1Soh: number; + Battery1Voltage: number; + Battery1Current: number; + Battery1PackTotalVoltage: number; + Battery1PackTotalCurrent: number; + Battery1Temperature: number; + Battery1SocSecondvalue: number; + Battery2Power: number; + Battery2Soc: number; + Battery2Soh: number; + Battery2Voltage: number; + Battery2Current: number; + Battery2PackTotalVoltage: number; + Battery2PackTotalCurrent: number; + Battery2Temperature: number; + Battery2Socsecondvalue: number; + ConsumptionPower: number; + TotalPhotovoltaicPower: number; + TotalBatteryPower: number; + TotalLoadPower: number; + TotalGridPower: number; + GridPower: number; + [key: string]: any; + }; + }; + [key: string]: any; }; AcDcGrowatt: { diff --git a/typescript/frontend-marios2/src/content/dashboards/SodiohomeInstallations/Installation.tsx b/typescript/frontend-marios2/src/content/dashboards/SodiohomeInstallations/Installation.tsx index da82a3c54..82d74d8a1 100644 --- a/typescript/frontend-marios2/src/content/dashboards/SodiohomeInstallations/Installation.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/SodiohomeInstallations/Installation.tsx @@ -376,11 +376,10 @@ function SodioHomeInstallation(props: singleInstallationProps) { fontSize: '14px' }} > - {props.current_installation.device === 4 - ? values.InverterRecord?.WorkingMode - : props.current_installation.device === 3 - ? values.InverterRecord?.OperatingMode - : values.Config.OperatingPriority} + {values.InverterRecord?.OperatingPriority + ?? values.InverterRecord?.WorkingMode + ?? values.InverterRecord?.OperatingMode + ?? values.Config?.OperatingPriority} )} diff --git a/typescript/frontend-marios2/src/content/dashboards/Topology/TopologySodistoreHome.tsx b/typescript/frontend-marios2/src/content/dashboards/Topology/TopologySodistoreHome.tsx index 29a27eb05..622129994 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Topology/TopologySodistoreHome.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Topology/TopologySodistoreHome.tsx @@ -39,29 +39,31 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { const isMobile = window.innerWidth <= 1490; - const totalBatteryPower: number = Number( - props.values && props.values.InverterRecord - ? Array.from({ length: props.batteryClusterNumber }).reduce( - (sum: number, _, index) => { - const i = index + 1; + const inv = props.values?.InverterRecord; + const hasDevices = !!inv?.Devices; - const rawPower = - props.values.InverterRecord[`Battery${i}Power`] as unknown; + const totalBatteryPower: number = hasDevices + ? (inv?.TotalBatteryPower ?? 0) + : Number( + Array.from({ length: props.batteryClusterNumber }).reduce( + (sum: number, _, index) => sum + (Number(inv?.[`Battery${index + 1}Power`]) || 0), + 0 + ) + ); - const power = Number(rawPower) || 0; + const pvPower: number = hasDevices + ? (inv?.TotalPhotovoltaicPower ?? 0) + : (inv?.PvPower ?? + ['PvPower1', 'PvPower2', 'PvPower3', 'PvPower4'] + .map((key) => inv?.[key] ?? 0) + .reduce((sum, val) => sum + val, 0)); - return sum + power; - }, - 0 - ) - : 0 - ); + const totalLoadPower: number = hasDevices + ? (inv?.TotalLoadPower ?? 0) + : (inv?.ConsumptionPower ?? 0); - const pvPower = - props.values?.InverterRecord?.PvPower ?? - ['PvPower1', 'PvPower2', 'PvPower3', 'PvPower4'] - .map((key) => props.values?.InverterRecord?.[key] ?? 0) - .reduce((sum, val) => sum + val, 0); + const totalGridPower: number = + inv?.TotalGridPower ?? inv?.GridPower ?? 0; return ( @@ -142,7 +144,7 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { data: props.values?.InverterRecord ? [ { - value: props.values.InverterRecord.GridPower, + value: totalGridPower, unit: 'W' } ] @@ -154,14 +156,14 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { orientation: 'horizontal', data: props.values?.InverterRecord ? { - value: props.values.InverterRecord.GridPower, + value: totalGridPower, unit: 'W' } : undefined, amount: props.values?.InverterRecord ? getAmount( highestConnectionValue, - props.values.InverterRecord.GridPower + totalGridPower ) : 0, showValues: showValues @@ -225,7 +227,7 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { data: props.values?.InverterRecord ? [ { - value: props.values.InverterRecord.ConsumptionPower, + value: totalLoadPower, unit: 'W' } ] @@ -237,14 +239,14 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { position: 'bottom', data: props.values?.InverterRecord ? { - value: props.values.InverterRecord.ConsumptionPower, + value: totalLoadPower, unit: 'W' } : undefined, amount: props.values?.InverterRecord ? getAmount( highestConnectionValue, - props.values.InverterRecord.ConsumptionPower + totalLoadPower ) : 0, showValues: showValues @@ -254,23 +256,32 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) { /> {/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/} {Array.from({ length: props.batteryClusterNumber }).map((_, index) => { - const i = index + 1; // battery cluster index starting from 1 + let soc: number; + let power: number; + + if (hasDevices) { + // Sinexcel: map across devices — 0→D1/B1, 1→D1/B2, 2→D2/B1, 3→D2/B2 + const deviceId = String(Math.floor(index / 2) + 1); + const batteryIndex = (index % 2) + 1; + const device = inv?.Devices?.[deviceId]; + soc = device?.[`Battery${batteryIndex}Soc`] ?? device?.[`Battery${batteryIndex}SocSecondvalue`] ?? 0; + power = device?.[`Battery${batteryIndex}Power`] ?? 0; + } else { + // Growatt: flat Battery1, Battery2, ... + const i = index + 1; + soc = Number(inv?.[`Battery${i}Soc`]) || 0; + power = Number(inv?.[`Battery${i}Power`]) || 0; + } return ( inv[key] ?? 0) - .reduce((sum, val) => sum + val, 0); + value = inv.TotalPhotovoltaicPower ?? inv.PvPower ?? inv.PvTotalPower; break; case 6: // consumption - value = inv.ConsumptionPower; + value = inv.TotalLoadPower ?? inv.ConsumptionPower; break; } }