fixed batteryview, min_soc error msg, operating priority in configuration tab tailored to sinexcel and growatt; fixed routes warning

This commit is contained in:
Yinyin Liu 2025-11-04 08:31:34 +01:00
parent d91090965d
commit 7b4f4481a3
11 changed files with 139 additions and 55 deletions

View File

@ -168,7 +168,7 @@ function BatteryView(props: BatteryViewProps) {
<Grid container> <Grid container>
<Routes> <Routes>
<Route <Route
path={routes.mainstats + '*'} path={routes.mainstats + '/*'}
element={ element={
<MainStats <MainStats
s3Credentials={props.s3Credentials} s3Credentials={props.s3Credentials}

View File

@ -166,7 +166,7 @@ function BatteryViewSalidomo(props: BatteryViewProps) {
<Grid container> <Grid container>
<Routes> <Routes>
<Route <Route
path={routes.mainstats + '*'} path={routes.mainstats + '/*'}
element={ element={
<MainStatsSalidomo <MainStatsSalidomo
s3Credentials={props.s3Credentials} s3Credentials={props.s3Credentials}

View File

@ -34,14 +34,51 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
const currentLocation = useLocation(); const currentLocation = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
// const sortedBatteryView =
// props.values != null &&
// props.values?.AcDcGrowatt?.BatteriesRecords?.Batteries
// ? Object.entries(props.values.AcDcGrowatt.BatteriesRecords.Batteries)
// .map(([BatteryId, battery]) => {
// return { BatteryId, battery }; // Here we return an object with the id and device
// })
// .sort((a, b) => parseInt(b.BatteryId) - parseInt(a.BatteryId))
// : [];
const inverter = (props.values as any)?.InverterRecord;
const sortedBatteryView = const sortedBatteryView =
props.values != null && inverter
props.values?.AcDcGrowatt?.BatteriesRecords?.Batteries ? [
? Object.entries(props.values.AcDcGrowatt.BatteriesRecords.Batteries) {
.map(([BatteryId, battery]) => { BatteryId: '1',
return { BatteryId, battery }; // Here we return an object with the id and device battery: {
}) Voltage: inverter.Battery1Voltage,
.sort((a, b) => parseInt(b.BatteryId) - parseInt(a.BatteryId)) Current: inverter.Battery1Current,
Power: inverter.Battery1Power,
Soc: inverter.Battery1Soc,
Soh: inverter.Battery1Soh,
// DailyDischargeEnergy: inverter.Battery1DailyDischargeEnergy,
// DailyChargeEnergy: inverter.Battery1DailyChargeEnergy,
}
},
{
BatteryId: '2',
battery: {
Voltage: inverter.Battery2Voltage,
Current: inverter.Battery2Current,
Power: inverter.Battery2Power,
Soc: inverter.Battery2Soc,
Soh: inverter.Battery2Soh,
// DailyDischargeEnergy: inverter.Battery2DailyDischargeEnergy,
// DailyChargeEnergy: inverter.Battery2DailyChargeEnergy,
}
}
]// filter out batteries where all numeric values are 0 or null/undefined
.filter(({ battery }) =>
Object.values(battery).some(
(v) => typeof v === 'number' && v !== 0
)
)
: []; : [];
const [loading, setLoading] = useState(sortedBatteryView.length == 0); const [loading, setLoading] = useState(sortedBatteryView.length == 0);
@ -157,7 +194,7 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
{/*<Grid container>*/} {/*<Grid container>*/}
{/* <Routes>*/} {/* <Routes>*/}
{/* <Route*/} {/* <Route*/}
{/* path={routes.mainstats + '*'}*/} {/* path={routes.mainstats + '/*'}*/}
{/* element={*/} {/* element={*/}
{/* <MainStats*/} {/* <MainStats*/}
{/* s3Credentials={props.s3Credentials}*/} {/* s3Credentials={props.s3Credentials}*/}
@ -224,8 +261,8 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
<TableCell align="center">Current</TableCell> <TableCell align="center">Current</TableCell>
<TableCell align="center">SoC</TableCell> <TableCell align="center">SoC</TableCell>
<TableCell align="center">SoH</TableCell> <TableCell align="center">SoH</TableCell>
<TableCell align="center">Daily Charge Energy</TableCell> {/*<TableCell align="center">Daily Charge Energy</TableCell>*/}
<TableCell align="center">Daily Discharge Energy</TableCell> {/*<TableCell align="center">Daily Discharge Energy</TableCell>*/}
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
@ -298,26 +335,26 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
> >
{battery.Soh + ' %'} {battery.Soh + ' %'}
</TableCell> </TableCell>
<TableCell {/*<TableCell*/}
sx={{ {/* sx={{*/}
width: '15%', {/* width: '15%',*/}
textAlign: 'center', {/* textAlign: 'center',*/}
backgroundColor: '#32CD32', {/* backgroundColor: '#32CD32',*/}
color: 'inherit' {/* color: 'inherit'*/}
}} {/* }}*/}
> {/*>*/}
{battery.DailyChargeEnergy + ' Wh'} {/* {battery.DailyChargeEnergy + ' Wh'}*/}
</TableCell> {/*</TableCell>*/}
<TableCell {/*<TableCell*/}
sx={{ {/* sx={{*/}
width: '15%', {/* width: '15%',*/}
textAlign: 'center', {/* textAlign: 'center',*/}
backgroundColor: '#32CD32', {/* backgroundColor: '#32CD32',*/}
color: 'inherit' {/* color: 'inherit'*/}
}} {/* }}*/}
> {/*>*/}
{battery.DailyDischargeEnergy + ' Wh'} {/* {battery.DailyDischargeEnergy + ' Wh'}*/}
</TableCell> {/*</TableCell>*/}
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>

View File

@ -416,7 +416,7 @@ function Installation(props: singleInstallationProps) {
/> />
<Route <Route
path={routes.batteryview + '*'} path={routes.batteryview + '/*'}
element={ element={
<BatteryView <BatteryView
values={values} values={values}
@ -428,7 +428,7 @@ function Installation(props: singleInstallationProps) {
></Route> ></Route>
<Route <Route
path={routes.pvview + '*'} path={routes.pvview + '/*'}
element={ element={
<PvView values={values} connected={connected}></PvView> <PvView values={values} connected={connected}></PvView>
} }

View File

@ -18,7 +18,7 @@ function InstallationSearch(props: installationSearchProps) {
return ( return (
<Route <Route
key={installation.id} key={installation.id}
path={routes.installation + installation.id + '*'} path={routes.installation + installation.id + '/*'}
element={ element={
<Installation <Installation
key={installation.id} key={installation.id}
@ -92,7 +92,7 @@ function InstallationSearch(props: installationSearchProps) {
// return ( // return (
// <Route // <Route
// key={installation.id} // key={installation.id}
// path={routes.installation + installation.id + '*'} // path={routes.installation + installation.id + '/*'}
// element={ // element={
// <Installation // <Installation
// key={installation.id} // key={installation.id}

View File

@ -361,7 +361,7 @@ function SalidomoInstallation(props: singleInstallationProps) {
/> />
<Route <Route
path={routes.batteryview + '*'} path={routes.batteryview + '/*'}
element={ element={
<BatteryViewSalidomo <BatteryViewSalidomo
values={values} values={values}

View File

@ -18,7 +18,7 @@ function InstallationSearch(props: installationSearchProps) {
return ( return (
<Route <Route
key={installation.id} key={installation.id}
path={routes.installation + installation.id + '*'} path={routes.installation + installation.id + '/*'}
element={ element={
<SalidomoInstallation <SalidomoInstallation
key={installation.id} key={installation.id}

View File

@ -444,7 +444,7 @@ function SodioHomeInstallation(props: singleInstallationProps) {
/> />
<Route <Route
path={routes.batteryview + '*'} path={routes.batteryview + '/*'}
element={ element={
<BatteryViewSodioHome <BatteryViewSodioHome
values={values} values={values}
@ -474,6 +474,7 @@ function SodioHomeInstallation(props: singleInstallationProps) {
<SodistoreHomeConfiguration <SodistoreHomeConfiguration
values={values} values={values}
id={props.current_installation.id} id={props.current_installation.id}
installation={props.current_installation}
></SodistoreHomeConfiguration> ></SodistoreHomeConfiguration>
} }
/> />

View File

@ -83,7 +83,7 @@ function InstallationSearch(props: installationSearchProps) {
return ( return (
<Route <Route
key={installation.id} key={installation.id}
path={routes.installation + installation.id + '*'} path={routes.installation + installation.id + '/*'}
element={ element={
<SodioHomeInstallation <SodioHomeInstallation
key={installation.id} key={installation.id}

View File

@ -24,10 +24,12 @@ import MenuItem from '@mui/material/MenuItem';
import axiosConfig from '../../../Resources/axiosConfig'; import axiosConfig from '../../../Resources/axiosConfig';
import { UserContext } from '../../../contexts/userContext'; import { UserContext } from '../../../contexts/userContext';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
import { I_Installation } from 'src/interfaces/InstallationTypes';
interface SodistoreHomeConfigurationProps { interface SodistoreHomeConfigurationProps {
values: JSONRecordData; values: JSONRecordData;
id: number; id: number;
installation: I_Installation;
} }
function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) { function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
@ -35,11 +37,22 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
return null; return null;
} }
const OperatingPriorityOptions = [ const device = props.installation.device;
'LoadPriority',
'BatteryPriority', const OperatingPriorityOptions =
'GridPriority' device === 3 // Growatt
]; ? ['LoadPriority', 'BatteryPriority', 'GridPriority']
: device === 4 // Sinexcel
? [
'SpontaneousSelfUse',
'TimeChargeDischarge',
'TimeOfUsePowerPrice',
'DisasterStandby',
'ManualControl',
'PvPriorityCharging',
'PrioritySellElectricity'
]
: [];
const [errors, setErrors] = useState({ const [errors, setErrors] = useState({
minimumSoC: false, minimumSoC: false,
@ -114,17 +127,50 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
const { name, value } = e.target; const { name, value } = e.target;
switch (name) { switch (name) {
case 'minimumSoC': // case 'minimumSoC':
if ( // if (
/[^0-9.]/.test(value) || // /[^0-9.]/.test(value) ||
isNaN(parseFloat(value)) || // isNaN(parseFloat(value)) ||
parseFloat(value) > 100 // parseFloat(value) > 30 ||
) { // parseFloat(value) < 10
SetErrorForField(name, true); // ) {
// SetErrorForField(name, true);
// } else {
// SetErrorForField(name, false);
// }
// break;
case 'minimumSoC': {
const numValue = parseFloat(value);
// Check for invalid characters or non-numeric
if (/[^0-9.]/.test(value) || isNaN(numValue)) {
SetErrorForField(name, {
hasError: true,
message: 'Invalid number format',
});
break;
}
// Define device-based ranges
const minsocRanges = {
3: { min: 10, max: 30 },
4: { min: 5, max: 100 },
};
// Fallback range if device not listed
const { min, max } = minsocRanges[device] || { min: 10, max: 30 };
if (numValue < min || numValue > max) {
SetErrorForField(name, {
hasError: true,
message: `Value should be between ${min}-${max}%`,
});
} else { } else {
SetErrorForField(name, false); SetErrorForField(name, { hasError: false, message: '' });
} }
break; break;
}
case 'gridSetPoint': case 'gridSetPoint':
if (/[^0-9.]/.test(value) || isNaN(parseFloat(value))) { if (/[^0-9.]/.test(value) || isNaN(parseFloat(value))) {
SetErrorForField(name, true); SetErrorForField(name, true);
@ -238,7 +284,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
helperText={ helperText={
errors.minimumSoC ? ( errors.minimumSoC ? (
<span style={{ color: 'red' }}> <span style={{ color: 'red' }}>
Value should be between 0-100% Value should be between {device === 4 ? '5100' : '1030'}%
</span> </span>
) : ( ) : (
'' ''

View File

@ -78,7 +78,7 @@ function InstallationTree() {
return ( return (
<Route <Route
key={installation.id} key={installation.id}
path={routes.installation + installation.id + '*'} path={routes.installation + installation.id + '/*'}
element={ element={
installation.product == 0 || installation.product == 3 ? ( installation.product == 0 || installation.product == 3 ? (
<Installation <Installation