updated multi-inverter sinexcel data path

This commit is contained in:
Yinyin Liu 2026-03-09 12:27:02 +01:00
parent 401d82ea7a
commit c102ab3335
5 changed files with 159 additions and 84 deletions

View File

@ -38,20 +38,41 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
const navigate = useNavigate(); const navigate = useNavigate();
const inverter = (props.values as any)?.InverterRecord; const inverter = (props.values as any)?.InverterRecord;
const batteryClusterNumber = props.installation.batteryClusterNumber; const batteryClusterNumber = props.installation.batteryClusterNumber;
const hasDevices = !!inverter?.Devices;
const sortedBatteryView = inverter const sortedBatteryView = inverter
? Array.from({ length: batteryClusterNumber }, (_, i) => { ? 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(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 { return {
BatteryId: String(index), BatteryId: String(index),
battery: { battery: {
Voltage: inverter[`Battery${index}Voltage`], Voltage: inverter[`Battery${index}Voltage`] ?? 0,
Current: inverter[`Battery${index}Current`], Current: inverter[`Battery${index}Current`] ?? 0,
Power: inverter[`Battery${index}Power`], Power: inverter[`Battery${index}Power`] ?? 0,
Soc: inverter[`Battery${index}Soc`], Soc: inverter[`Battery${index}Soc`] ?? 0,
Soh: inverter[`Battery${index}Soh`], Soh: inverter[`Battery${index}Soh`] ?? 0,
} }
}; };
}
}) })
: []; : [];

View File

@ -437,23 +437,76 @@ export interface JSONRecordData {
}; };
}; };
// For SodistoreHome // For SodistoreHome (Sinexcel multi-inverter structure)
InverterRecord: { InverterRecord: {
GridPower:number; // Top-level aggregated values
Battery1Power:number; TotalPhotovoltaicPower: number;
Battery1Soc:number; TotalBatteryPower: number;
Battery1Soh:number; TotalLoadPower: number;
Battery1Voltage:number; TotalGridPower: number;
Battery1Current:number; AvgBatteryVoltage: number;
Battery2Power:number; TotalBatteryCurrent: number;
Battery2Soc:number; AvgBatterySoc: number;
Battery2Voltage:number; AvgBatterySoh: number;
Battery2Current:number; AvgBatteryTemp: number;
Battery2Soh:number; OperatingPriority?: string;
PvPower:number; MinSoc: number;
ConsumptionPower:number; MaxChargeCurrent: number;
WorkingMode?:string; MaxDischargingCurrent: number;
OperatingMode?:string; 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: { AcDcGrowatt: {

View File

@ -376,11 +376,10 @@ function SodioHomeInstallation(props: singleInstallationProps) {
fontSize: '14px' fontSize: '14px'
}} }}
> >
{props.current_installation.device === 4 {values.InverterRecord?.OperatingPriority
? values.InverterRecord?.WorkingMode ?? values.InverterRecord?.WorkingMode
: props.current_installation.device === 3 ?? values.InverterRecord?.OperatingMode
? values.InverterRecord?.OperatingMode ?? values.Config?.OperatingPriority}
: values.Config.OperatingPriority}
</Typography> </Typography>
</div> </div>
)} )}

View File

@ -39,29 +39,31 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
const isMobile = window.innerWidth <= 1490; const isMobile = window.innerWidth <= 1490;
const totalBatteryPower: number = Number( const inv = props.values?.InverterRecord;
props.values && props.values.InverterRecord const hasDevices = !!inv?.Devices;
? Array.from({ length: props.batteryClusterNumber }).reduce(
(sum: number, _, index) => {
const i = index + 1;
const rawPower = const totalBatteryPower: number = hasDevices
props.values.InverterRecord[`Battery${i}Power`] as unknown; ? (inv?.TotalBatteryPower ?? 0)
: Number(
const power = Number(rawPower) || 0; Array.from({ length: props.batteryClusterNumber }).reduce(
(sum: number, _, index) => sum + (Number(inv?.[`Battery${index + 1}Power`]) || 0),
return sum + power;
},
0 0
) )
: 0
); );
const pvPower = const pvPower: number = hasDevices
props.values?.InverterRecord?.PvPower ?? ? (inv?.TotalPhotovoltaicPower ?? 0)
: (inv?.PvPower ??
['PvPower1', 'PvPower2', 'PvPower3', 'PvPower4'] ['PvPower1', 'PvPower2', 'PvPower3', 'PvPower4']
.map((key) => props.values?.InverterRecord?.[key] ?? 0) .map((key) => inv?.[key] ?? 0)
.reduce((sum, val) => sum + val, 0); .reduce((sum, val) => sum + val, 0));
const totalLoadPower: number = hasDevices
? (inv?.TotalLoadPower ?? 0)
: (inv?.ConsumptionPower ?? 0);
const totalGridPower: number =
inv?.TotalGridPower ?? inv?.GridPower ?? 0;
return ( return (
<Container maxWidth="xl" style={{ backgroundColor: 'white' }}> <Container maxWidth="xl" style={{ backgroundColor: 'white' }}>
@ -142,7 +144,7 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
data: props.values?.InverterRecord data: props.values?.InverterRecord
? [ ? [
{ {
value: props.values.InverterRecord.GridPower, value: totalGridPower,
unit: 'W' unit: 'W'
} }
] ]
@ -154,14 +156,14 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
orientation: 'horizontal', orientation: 'horizontal',
data: props.values?.InverterRecord data: props.values?.InverterRecord
? { ? {
value: props.values.InverterRecord.GridPower, value: totalGridPower,
unit: 'W' unit: 'W'
} }
: undefined, : undefined,
amount: props.values?.InverterRecord amount: props.values?.InverterRecord
? getAmount( ? getAmount(
highestConnectionValue, highestConnectionValue,
props.values.InverterRecord.GridPower totalGridPower
) )
: 0, : 0,
showValues: showValues showValues: showValues
@ -225,7 +227,7 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
data: props.values?.InverterRecord data: props.values?.InverterRecord
? [ ? [
{ {
value: props.values.InverterRecord.ConsumptionPower, value: totalLoadPower,
unit: 'W' unit: 'W'
} }
] ]
@ -237,14 +239,14 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
position: 'bottom', position: 'bottom',
data: props.values?.InverterRecord data: props.values?.InverterRecord
? { ? {
value: props.values.InverterRecord.ConsumptionPower, value: totalLoadPower,
unit: 'W' unit: 'W'
} }
: undefined, : undefined,
amount: props.values?.InverterRecord amount: props.values?.InverterRecord
? getAmount( ? getAmount(
highestConnectionValue, highestConnectionValue,
props.values.InverterRecord.ConsumptionPower totalLoadPower
) )
: 0, : 0,
showValues: showValues showValues: showValues
@ -254,23 +256,32 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
/> />
{/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/} {/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/}
{Array.from({ length: props.batteryClusterNumber }).map((_, index) => { {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 ( return (
<TopologyColumn <TopologyColumn
key={i} key={index + 1}
centerBox={{ centerBox={{
title: `Battery C${i}`, title: `Battery C${index + 1}`,
data: props.values.InverterRecord data: inv
? [ ? [
{ { value: soc, unit: '%' },
value: props.values.InverterRecord[`Battery${i}Soc`], { value: power, unit: 'W' }
unit: '%'
},
{
value: props.values.InverterRecord[`Battery${i}Power`],
unit: 'W'
}
] ]
: undefined, : undefined,
connected: true connected: true

View File

@ -516,36 +516,27 @@ export const transformInputToDailyDataJson = async (
let value: number | undefined = undefined; let value: number | undefined = undefined;
if (product === 2) { if (product === 2) {
// SodioHome: custom extraction with fallbacks for Growatt/Sinexcel // SodioHome: use top-level aggregated values (Sinexcel multi-inverter)
const inv = result?.InverterRecord; const inv = result?.InverterRecord;
if (inv) { if (inv) {
switch (category_index) { switch (category_index) {
case 0: // soc case 0: // soc
value = inv.Battery1Soc; value = inv.AvgBatterySoc ?? inv.Battery1Soc;
break; break;
case 1: // temperature case 1: // temperature
// Growatt: Battery1AmbientTemperature, Sinexcel: Battery1Temperature value = inv.AvgBatteryTemp ?? inv.Battery1AmbientTemperature ?? inv.Battery1Temperature;
value = inv.Battery1AmbientTemperature ?? inv.Battery1Temperature;
break; break;
case 2: // battery power case 2: // battery power
value = inv.Battery1Power; value = inv.TotalBatteryPower ?? inv.Battery1Power;
break; break;
case 3: // grid power case 3: // grid power
// Growatt: GridPower (always valid), Sinexcel: GridPower may be 0 when
// electric meter is offline, TotalGridPower is the reliable fallback
value = inv.TotalGridPower ?? inv.GridPower; value = inv.TotalGridPower ?? inv.GridPower;
break; break;
case 4: // pv production case 4: // pv production
// Growatt: PvPower (aggregated), Sinexcel: PvTotalPower or sum PvPower1-4 value = inv.TotalPhotovoltaicPower ?? inv.PvPower ?? inv.PvTotalPower;
value =
inv.PvPower ??
inv.PvTotalPower ??
['PvPower1', 'PvPower2', 'PvPower3', 'PvPower4']
.map((key) => inv[key] ?? 0)
.reduce((sum, val) => sum + val, 0);
break; break;
case 6: // consumption case 6: // consumption
value = inv.ConsumptionPower; value = inv.TotalLoadPower ?? inv.ConsumptionPower;
break; break;
} }
} }