Merge branch 'main' into CEC-5443

This commit is contained in:
Paul Adamsen
2024-01-18 17:24:28 -05:00
committed by GitHub
4 changed files with 116 additions and 18 deletions

View File

@@ -1,17 +1,31 @@
import { forwardRef, useImperativeHandle, useState, useEffect } from "react"; import { forwardRef, useImperativeHandle, useState, useEffect } from "react";
import { import {
Box,
FormControl, FormControl,
FormControlLabel,
Grid,
TextField,
InputLabel, InputLabel,
Select, Select,
Switch,
} from "@material-ui/core"; } from "@material-ui/core";
import api from "../../../services/vehiclesAPI"; import api from "../../../services/vehiclesAPI";
import TaskRunner from "../../../utils/taskRunner"; import TaskRunner from "../../../utils/taskRunner";
import { AllECUsCommand, DIAGNOSTIC_COMMANDS } from "../../Controls/SendDiagnosticCommand"; import { AllECUsCommand } from "../../Controls/SendDiagnosticCommand";
import useStyles from "../../useStyles"; import useStyles from "../../useStyles";
import { useStatusContext } from "../../Contexts/StatusContext"; import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext"; import { useUserContext } from "../../Contexts/UserContext";
import unionIntersect from "../../../utils/unionIntersect"; import unionIntersect from "../../../utils/unionIntersect";
const DIAGNOSTIC_COMMANDS = [
{ displayname: "Reset", val: "remote_reset", ecu_name: true },
{ displayname: "Set CAN Network State", val: "can_network", state: "can_net_action" },
{ displayname: "Set Remote Ignition", val: "remote_ignition", state: "can_net_action" },
{ displayname: "Read ECU versions", val: "read_ecu_versions", allowAll: true, ecu_name: true },
];
const DEFAULT_SECONDS = 180;
async function getECUsByVINs(vins, token) { async function getECUsByVINs(vins, token) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const taskRunner = new TaskRunner(30, vins.length); const taskRunner = new TaskRunner(30, vins.length);
@@ -46,6 +60,8 @@ export default forwardRef(({
const [currentECU, setCurrentECU] = useState(""); const [currentECU, setCurrentECU] = useState("");
const [validateECUs, setValidateECUs] = useState(false); const [validateECUs, setValidateECUs] = useState(false);
const [command, setCommand] = useState(DIAGNOSTIC_COMMANDS[0]); const [command, setCommand] = useState(DIAGNOSTIC_COMMANDS[0]);
const [checked, setChecked] = useState(false);
const [seconds, setSeconds] = useState(DEFAULT_SECONDS);
const classes = useStyles(); const classes = useStyles();
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
const { token: { idToken: { jwtToken: token } } } = useUserContext(); const { token: { idToken: { jwtToken: token } } } = useUserContext();
@@ -56,15 +72,12 @@ export default forwardRef(({
return Promise.reject("Invalid ECUs found, cannot submit"); return Promise.reject("Invalid ECUs found, cannot submit");
} }
return api.sendDiagnosticCommand(ids, { return api.sendDiagnosticCommand(ids, createDiagnosticPayload(command, checked, currentECU, seconds), token)
command: command.val,
ecu_name: currentECU,
}, token)
.then(() => { .then(() => {
setMessage(`Sent ${command} command to ${ids.length} vehicles.`); setMessage(`Sent ${command.val} command to ${ids.length} vehicles.`);
}) })
.catch(() => { .catch(() => {
setMessage(`Failed to send ${command} command.`); setMessage(`Failed to send ${command.val} command.`);
}); });
} }
})); }));
@@ -73,6 +86,17 @@ export default forwardRef(({
setCommand(DIAGNOSTIC_COMMANDS[e.target.value]); setCommand(DIAGNOSTIC_COMMANDS[e.target.value]);
}; };
const handleSwitch = (e) => {
setChecked(e.target.checked);
}
const handleSecondsChange = (e) => {
const value = Number(e.target.value);
if (value > 0) {
setSeconds();
}
}
useEffect(() => { useEffect(() => {
async function fetchData() { async function fetchData() {
setValidateECUs(false); setValidateECUs(false);
@@ -82,22 +106,26 @@ export default forwardRef(({
fetchData(); fetchData();
}, [ids, token]); }, [ids, token]);
useEffect(() => {
if (!checked) {
setSeconds(DEFAULT_SECONDS);
}
}, [checked, setSeconds]);
useEffect(() => {
setChecked(false);
}, [command, setChecked]);
useEffect(() => { useEffect(() => {
setValidateECUs(true); setValidateECUs(true);
setCurrentECU(ecus[0].ecu); setCurrentECU(ecus[0].ecu);
}, [ecus]); }, [ecus]);
return ( return (
<div> <Box minHeight="185px">
<p> <p>
Attempt to send a vehicle diagnostic command to the following VINs: {idCSV}. Attempt to send a vehicle diagnostic command to the following VINs: {idCSV}.
</p> </p>
<AllECUsCommand
classes={classes}
ecus={command.allowAll ? [...ecus, { ecu: "*" }] : ecus}
currentECU={currentECU}
setCurrentECU={setCurrentECU}
/>
<FormControl className={classes.formControl} variant="outlined" size="small" margin="normal"> <FormControl className={classes.formControl} variant="outlined" size="small" margin="normal">
<InputLabel htmlFor="send-command" className={classes.whiteBackground}> <InputLabel htmlFor="send-command" className={classes.whiteBackground}>
@@ -117,6 +145,57 @@ export default forwardRef(({
))} ))}
</Select> </Select>
</FormControl> </FormControl>
</div>
{["remote_reset", "read_ecu_versions"].includes(command.val) && <AllECUsCommand
classes={classes}
ecus={command.allowAll ? [...ecus, { ecu: "*" }] : ecus}
currentECU={currentECU}
setCurrentECU={setCurrentECU}
/>}
{["can_network", "remote_ignition"].includes(command.val) && (
<Grid container direction="row" alignItems="flex-end" >
<div>
<FormControlLabel
label="State"
labelPlacement="end"
control={<Switch checked={checked} onChange={handleSwitch} />}
/>
</div>
<TextField
label="Seconds"
type="number"
onChange={handleSecondsChange}
value={seconds}
disabled={!checked}
inputProps={{
min: "0",
step: "10",
}}
/>
</Grid>
)}
</Box>
); );
}); });
const hasOwnProperty = (obj, key) => {
return Object.prototype.hasOwnProperty.call(obj, key);
}
const createDiagnosticPayload = (command = {}, checked, ecu, seconds) => {
const payload = {
command: command.val,
};
if (hasOwnProperty(command, "ecu_name")) {
payload.ecu_name = ecu;
}
if (hasOwnProperty(command, "state")) {
payload[command.state] = checked ? "on" : "off";
payload.timeout = seconds;
}
return payload;
}

View File

@@ -14,6 +14,8 @@ function parseVin(vin = "") {
return [true, vin.replace(prefix, "")]; return [true, vin.replace(prefix, "")];
} }
vin = vin.replace(/[^\p{L}\d]/gu, '');
var re = new RegExp("^[A-HJ-NPR-Z0-9]{8}[0-9X][A-HJ-NPR-Z0-9]{2}[0-9]{6}$"); var re = new RegExp("^[A-HJ-NPR-Z0-9]{8}[0-9X][A-HJ-NPR-Z0-9]{2}[0-9]{6}$");
return [vin.match(re), vin]; return [vin.match(re), vin];
} }

View File

@@ -89,6 +89,22 @@ describe("useQuery", () => {
["test", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "test vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"] ["test", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "test vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
], ],
[
"parses a space separated search query with special characters",
"[ocean] pe@r a!aska r*nin",
["[ocean] pe@r a!aska r*nin", "", "[ocean] pe@r a!aska r*nin"]
],
[
"parses a space separated vin query with special characters",
"[\"VCF1EBE2008016235\", \"VCF1EBE20PG001002\", \"VCF1EBE20PG001162\"]",
["", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
],
[
"parses a space separated mixed search and vin query with special characters",
"te$t VCF1EBE20@*(08016235 [VCF1EBE2]0PG001002 VCF*1EBE20PG001162",
["te$t", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "te$t vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
],
[ [
"trims extraneous values from search", "trims extraneous values from search",
"ocean,, , ,,,,pear,,, ", "ocean,, , ,,,,pear,,, ",

View File

@@ -13,13 +13,13 @@ import {
useVehicleContext useVehicleContext
} from "../../Contexts/VehicleContext"; } from "../../Contexts/VehicleContext";
export const DIAGNOSTIC_COMMANDS = [ const DIAGNOSTIC_COMMANDS = [
{ displayname: "Reset", val: "remote_reset" }, { displayname: "Reset", val: "remote_reset" },
{ displayname: "Set CAN Network State", val: "can_network" }, { displayname: "Set CAN Network State", val: "can_network" },
{ displayname: "Set Remote Ignition", val: "remote_ignition" }, { displayname: "Set Remote Ignition", val: "remote_ignition" },
{ displayname: "Send Wake Up SMS", val: "sms" }, { displayname: "Send Wake Up SMS", val: "sms" },
// { displayname: "Update SecOC keys", val: "write_secoc_key" }, // { displayname: "Update SecOC keys", val: "write_secoc_key" },
{ displayname: "Read ECU versions", val: "read_ecu_versions", allowAll: true }, { displayname: "Read ECU versions", val: "read_ecu_versions" },
] ]
const SendDiagnosticCommand = ({ vin, token, classes }) => { const SendDiagnosticCommand = ({ vin, token, classes }) => {
@@ -195,6 +195,7 @@ export const AllECUsCommand = ({ classes, ecus, currentECU, setCurrentECU }) =>
className={classes.formControl} className={classes.formControl}
variant="outlined" variant="outlined"
size="small" size="small"
margin="normal"
> >
<InputLabel className={classes.whiteBackground}> <InputLabel className={classes.whiteBackground}>
ECU ECU