CEC-2211 CAN signals view (#176)
* CEC-2211 CAN signals view * Correct stg link
This commit is contained in:
2
.env.dev
2
.env.dev
@@ -2,4 +2,4 @@ REACT_APP_CERT_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/certificate
|
|||||||
REACT_APP_AUTH_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/compute_auth
|
REACT_APP_AUTH_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/compute_auth
|
||||||
REACT_APP_UPLOAD_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_UPLOAD_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_AUTH_CALLBACK_URL=https://dev-ota-admin.cloud.fiskerinc.com
|
REACT_APP_AUTH_CALLBACK_URL=https://dev-ota-admin.cloud.fiskerinc.com
|
||||||
REACT_APP_SUPERSET_URL=http://superset-dev.fiskercloud.internal/superset/dashboard/8/?native_filters_key=KPnPthpLQ8rT--6PUdsPzQAcwnleRGHk_3dg0PVYfrXc3SE6zZ2x0p7JuerAZ0Pg
|
REACT_APP_SUPERSET_URL=https://superset-dev.cloud.fiskerinc.com/superset/dashboard/8/?native_filters_key=KPnPthpLQ8rT--6PUdsPzQAcwnleRGHk_3dg0PVYfrXc3SE6zZ2x0p7JuerAZ0Pg
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ REACT_APP_AUTH_SERVICE_URL=http://localhost/compute_auth
|
|||||||
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
|
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
|
||||||
REACT_APP_UPLOAD_SERVICE_URL=http://localhost/ota_update
|
REACT_APP_UPLOAD_SERVICE_URL=http://localhost/ota_update
|
||||||
REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
|
REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
|
||||||
REACT_APP_SUPERSET_URL=http://superset-dev.fiskercloud.internal/superset/dashboard/8/?native_filters_key=KPnPthpLQ8rT--6PUdsPzQAcwnleRGHk_3dg0PVYfrXc3SE6zZ2x0p7JuerAZ0Pg
|
REACT_APP_SUPERSET_URL=https://superset-dev.cloud.fiskerinc.com/superset/dashboard/8/?native_filters_key=KPnPthpLQ8rT--6PUdsPzQAcwnleRGHk_3dg0PVYfrXc3SE6zZ2x0p7JuerAZ0Pg
|
||||||
|
|||||||
2
.env.prd
2
.env.prd
@@ -2,4 +2,4 @@ REACT_APP_AUTH_SERVICE_URL=https://gw.cloud.fiskerinc.com/compute_auth
|
|||||||
REACT_APP_CERT_SERVICE_URL=https://gw.cloud.fiskerinc.com/certificate
|
REACT_APP_CERT_SERVICE_URL=https://gw.cloud.fiskerinc.com/certificate
|
||||||
REACT_APP_UPLOAD_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_UPLOAD_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cloud.fiskerinc.com
|
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cloud.fiskerinc.com
|
||||||
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com/superset/dashboard/9/?native_filters_key=mfJ1VjGTcLUKz7gQs_DgClZhjcdNucYMrPruNibcyDnhkDwdHbAumBRVTpA5tFH_
|
||||||
|
|||||||
2
.env.stg
2
.env.stg
@@ -2,4 +2,4 @@ REACT_APP_AUTH_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/compute_auth
|
|||||||
REACT_APP_CERT_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/certificate
|
REACT_APP_CERT_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/certificate
|
||||||
REACT_APP_UPLOAD_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_UPLOAD_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_AUTH_CALLBACK_URL=https://stg-ota-admin.cloud.fiskerinc.com
|
REACT_APP_AUTH_CALLBACK_URL=https://stg-ota-admin.cloud.fiskerinc.com
|
||||||
REACT_APP_SUPERSET_URL=http://superset-dev.fiskercloud.internal/superset/dashboard/8/?native_filters_key=KPnPthpLQ8rT--6PUdsPzQAcwnleRGHk_3dg0PVYfrXc3SE6zZ2x0p7JuerAZ0Pg
|
REACT_APP_SUPERSET_URL=https://stg-superset.cloud.fiskerinc.com/superset/dashboard/6/?native_filters_key=XBwRgJIvmxhqBhqlz45kuTnXc1iUY_M_ovzXCzXy5_l-AOFAXEaGLWpYIsfrEHGR
|
||||||
|
|||||||
@@ -8298,6 +8298,24 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
aria-controls="tabpanel-4"
|
||||||
|
aria-selected="false"
|
||||||
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit"
|
||||||
|
id="tab-4"
|
||||||
|
role="tab"
|
||||||
|
tabindex="-1"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTab-wrapper"
|
||||||
|
>
|
||||||
|
CAN Signals
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="PrivateTabIndicator-root-1509 PrivateTabIndicator-colorSecondary-1511 MuiTabs-indicator"
|
class="PrivateTabIndicator-root-1509 PrivateTabIndicator-colorSecondary-1511 MuiTabs-indicator"
|
||||||
@@ -8454,6 +8472,13 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
id="tabpanel-3"
|
id="tabpanel-3"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
aria-labelledby="tab-4"
|
||||||
|
class="makeStyles-fullWidth-0"
|
||||||
|
hidden=""
|
||||||
|
id="tabpanel-4"
|
||||||
|
role="tabpanel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
104
src/components/Cars/CANSignals/index.jsx
Normal file
104
src/components/Cars/CANSignals/index.jsx
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { logger } from "../../../services/monitoring";
|
||||||
|
import { LocalDateTimeString } from "../../../utils/dates";
|
||||||
|
|
||||||
|
import { useVehicleContext } from "../../Contexts/VehicleContext";
|
||||||
|
|
||||||
|
const BlankSignal = (msg) => ({
|
||||||
|
timestamp: "",
|
||||||
|
signal: msg,
|
||||||
|
value: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformSignals = (signals) =>
|
||||||
|
signals
|
||||||
|
.map((signal) => {
|
||||||
|
const { Timestamp, ...Settings } = signal;
|
||||||
|
const keys = Object.keys(Settings);
|
||||||
|
|
||||||
|
return keys.map((key) => ({
|
||||||
|
timestamp: LocalDateTimeString(Timestamp),
|
||||||
|
signal: key,
|
||||||
|
value: Settings[key],
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
const CANSignals = (props) => {
|
||||||
|
const { vin, token } = props;
|
||||||
|
const { getCANSignals } = useVehicleContext();
|
||||||
|
const [signals, setSignals] = useState([]);
|
||||||
|
const delay = 500;
|
||||||
|
let timer = 0;
|
||||||
|
|
||||||
|
const stopTimer = async () => {
|
||||||
|
if (timer === 0) return;
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const startTimer = () => {
|
||||||
|
stopTimer();
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
updateSignals();
|
||||||
|
}, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateSignals = async () => {
|
||||||
|
try {
|
||||||
|
const result = await getCANSignals(vin, token);
|
||||||
|
const items = transformSignals(result.data);
|
||||||
|
|
||||||
|
if (items.length > 0) {
|
||||||
|
setSignals(items);
|
||||||
|
} else {
|
||||||
|
setSignals(BlankSignal("No signals"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delay > 0) startTimer();
|
||||||
|
} catch (e) {
|
||||||
|
setSignals(BlankSignal(e.message));
|
||||||
|
logger.warn(e.stack);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
startTimer();
|
||||||
|
return () => {
|
||||||
|
stopTimer();
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!signals || signals.length === 0) return <h3>Loading...</h3>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Timestamp</TableCell>
|
||||||
|
<TableCell>Signal</TableCell>
|
||||||
|
<TableCell>Value</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{signals.map((signal, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell>{signal.timestamp}</TableCell>
|
||||||
|
<TableCell>{signal.signal}</TableCell>
|
||||||
|
<TableCell>{signal.value}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CANSignals;
|
||||||
35
src/components/Cars/Status/CANSignalsTab.jsx
Normal file
35
src/components/Cars/Status/CANSignalsTab.jsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { Typography } from "@material-ui/core";
|
||||||
|
|
||||||
|
import useStyles from "../../useStyles";
|
||||||
|
import { useUserContext } from "../../Contexts/UserContext";
|
||||||
|
import CANSignals from "../CANSignals";
|
||||||
|
import { VehicleProvider } from "../../Contexts/VehicleContext";
|
||||||
|
|
||||||
|
const Main = (props) => {
|
||||||
|
const {
|
||||||
|
token: {
|
||||||
|
idToken: { jwtToken: token },
|
||||||
|
},
|
||||||
|
} = useUserContext();
|
||||||
|
const classes = useStyles();
|
||||||
|
const { vin } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={clsx(classes.paper, classes.tableSize)}>
|
||||||
|
<Typography variant="h6" style={{ paddingBottom: "10px" }}>
|
||||||
|
CAN Signals
|
||||||
|
</Typography>
|
||||||
|
<CANSignals vin={vin} token={token} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CANSignalsTab = (props) => (
|
||||||
|
<VehicleProvider>
|
||||||
|
<Main {...props} />
|
||||||
|
</VehicleProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default CANSignalsTab;
|
||||||
@@ -101,6 +101,24 @@ exports[`CarStatus Render 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
aria-controls="tabpanel-4"
|
||||||
|
aria-selected="false"
|
||||||
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit"
|
||||||
|
id="tab-4"
|
||||||
|
role="tab"
|
||||||
|
tabindex="-1"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTab-wrapper"
|
||||||
|
>
|
||||||
|
CAN Signals
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="PrivateTabIndicator-root-64 PrivateTabIndicator-colorSecondary-66 MuiTabs-indicator"
|
class="PrivateTabIndicator-root-64 PrivateTabIndicator-colorSecondary-66 MuiTabs-indicator"
|
||||||
@@ -203,6 +221,13 @@ exports[`CarStatus Render 1`] = `
|
|||||||
id="tabpanel-3"
|
id="tabpanel-3"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
aria-labelledby="tab-4"
|
||||||
|
class="makeStyles-fullWidth-0"
|
||||||
|
hidden=""
|
||||||
|
id="tabpanel-4"
|
||||||
|
role="tabpanel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import DigitalTwinTab from "./DigitalTwinTab";
|
|||||||
import TabPanel from "../../Controls/TabPanel";
|
import TabPanel from "../../Controls/TabPanel";
|
||||||
import { useStatusContext } from "../../Contexts/StatusContext";
|
import { useStatusContext } from "../../Contexts/StatusContext";
|
||||||
import useStyles from "../../useStyles";
|
import useStyles from "../../useStyles";
|
||||||
|
import CANSignalsTab from "./CANSignalsTab";
|
||||||
|
|
||||||
const tabHashes = ["details", "updates", "filters"];
|
const tabHashes = ["details", "updates", "filters"];
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ const CarStatus = () => {
|
|||||||
<Tab label="Car Updates" {...tabProps(1)} />
|
<Tab label="Car Updates" {...tabProps(1)} />
|
||||||
<Tab label="CAN Filters" {...tabProps(2)} />
|
<Tab label="CAN Filters" {...tabProps(2)} />
|
||||||
<Tab label="Digital Twin" {...tabProps(3)} />
|
<Tab label="Digital Twin" {...tabProps(3)} />
|
||||||
|
<Tab label="CAN Signals" {...tabProps(4)} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -80,6 +82,10 @@ const CarStatus = () => {
|
|||||||
<TabPanel value={tabIndex} index={3}>
|
<TabPanel value={tabIndex} index={3}>
|
||||||
<DigitalTwinTab vin={vin} />
|
<DigitalTwinTab vin={vin} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
|
<TabPanel value={tabIndex} index={4} className={classes.fullWidth}>
|
||||||
|
<CANSignalsTab vin={vin} />
|
||||||
|
</TabPanel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,6 +205,20 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getCANSignals = async (vin, token) => {
|
||||||
|
try {
|
||||||
|
setBusy(true);
|
||||||
|
validateVIN(vin);
|
||||||
|
|
||||||
|
const result = await api.getCANSignals(vin, token);
|
||||||
|
if (result.error)
|
||||||
|
throw new Error(`Get CAN signals error. ${result.message}`);
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
setBusy(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VehicleContext.Provider
|
<VehicleContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@@ -217,6 +231,7 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
addVehicle,
|
addVehicle,
|
||||||
deleteVehicle,
|
deleteVehicle,
|
||||||
getConnections,
|
getConnections,
|
||||||
|
getCANSignals,
|
||||||
getECUs,
|
getECUs,
|
||||||
getLocations,
|
getLocations,
|
||||||
getModels,
|
getModels,
|
||||||
|
|||||||
@@ -152,6 +152,17 @@ const vehiclesAPI = {
|
|||||||
})
|
})
|
||||||
.then(fetchRespHandler)
|
.then(fetchRespHandler)
|
||||||
.catch(errorHandler),
|
.catch(errorHandler),
|
||||||
|
|
||||||
|
getCANSignals: async (vin, token) =>
|
||||||
|
fetch(`${API_ENDPOINT}/cansignals/${vin}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: Object.assign(
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
getAuthHeaderOptions(token)
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.then(fetchRespHandler)
|
||||||
|
.catch(errorHandler),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default vehiclesAPI;
|
export default vehiclesAPI;
|
||||||
|
|||||||
Reference in New Issue
Block a user