From 8c5a38b843ed9b4bb45b0320a5ebb7903541b2ba Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Mon, 6 Nov 2023 14:51:25 -0800 Subject: [PATCH 1/3] CEC-5356: use new can signal api --- src/components/Cars/CANSignals/index.jsx | 39 ++++++++++--------- src/components/Contexts/CANSignalsContext.jsx | 28 +++++++++---- src/services/vehiclesAPI.js | 22 +++++++++-- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/components/Cars/CANSignals/index.jsx b/src/components/Cars/CANSignals/index.jsx index 37febbc..5832b99 100644 --- a/src/components/Cars/CANSignals/index.jsx +++ b/src/components/Cars/CANSignals/index.jsx @@ -13,7 +13,7 @@ import { } from "../../Contexts/CANSignalsContext"; const Main = ({ vin }) => { - const { signals, setVIN } = useCANSignalContext(); + const { signals, setVIN, duration } = useCANSignalContext(); useEffect(() => { setVIN(vin); @@ -26,24 +26,27 @@ const Main = ({ vin }) => { if (!signals || signals.length === 0) return

Loading...

; return ( - - - - Timestamp - Signal - Value - - - - {signals.map((signal, i) => ( - - {signal.timestamp} - {signal.signal} - {signal.value} + <> + (Received within the last {duration} seconds) +
+ + + Timestamp + Signal + Value - ))} - -
+ + + {signals.map((signal, i) => ( + + {signal.timestamp} + {signal.signal} + {signal.value} + + ))} + + + ); }; diff --git a/src/components/Contexts/CANSignalsContext.jsx b/src/components/Contexts/CANSignalsContext.jsx index 30c49b8..4324b4c 100644 --- a/src/components/Contexts/CANSignalsContext.jsx +++ b/src/components/Contexts/CANSignalsContext.jsx @@ -1,8 +1,8 @@ -import React, {useContext, useState} from "react"; +import React, { useContext, useState } from "react"; import api from "../../services/vehiclesAPI"; import { LocalDateTimeString } from "../../utils/dates"; -import {useInterval} from "usehooks-ts"; +import { useInterval } from "usehooks-ts"; const CANSignalContext = React.createContext(); @@ -26,31 +26,44 @@ const transformSignals = (signals) => .flat(); export const CANSignalProvider = ({ token, children }) => { + // auto scale polling if not getting response + const durations = [10000, 30000, 60000, 120000]; + const delays = [500, 1500, 3000, 6000]; const [vin, setVIN] = useState(null); const [signals, setSignals] = useState([]); - const [delay, setDelay] = useState(500); + const [delayIndex, setDelayIndex] = useState(0); useInterval( () => { getCANSignals() - }, vin?delay:null + }, vin ? delays[delayIndex] : null ) const getCANSignals = async () => { try { if (!vin) return; - const result = await api.getCANSignals(vin, token); + const date = new Date(); + date.setUTCSeconds(date.getUTCSeconds() - durations[delayIndex]); + + const result = await api.getCANSignals(vin, { + after_utc: date, + }, token); if (result.error) throw new Error(`Get CAN signals error. ${result.message}`); const items = transformSignals(result.data); if (items.length > 0) { - setDelay(500); + setDelayIndex(0); setSignals(items); } else { - setDelay(1000); + setDelayIndex((index) => { + if (index < delays.length - 1) { + return index += 1; + } + return index; + }); setSignals([BlankSignal("No signals")]); } } catch (e) { @@ -61,6 +74,7 @@ export const CANSignalProvider = ({ token, children }) => { return ( - fetch(`${API_ENDPOINT}/cansignals/${vin}`, { + /** + * + * @param {String} vin The VIN of the car + * @param {Object} filter + * @param {Date} filter.after_utc Point in time to begin signal response + * @param {Integer} filter.limit Max number of CAN Signals to return + * @param {String} token + * @returns {Array} + */ + getCANSignals: async (vin, filter = {}, token) => { + if (filter.after_utc instanceof Date && !isNaN(filter.after_utc)) { + filter.after_utc = filter.after_utc.getTime(); + } + + const url = addQueryParams(`${API_ENDPOINT}/cansignals/${vin}`, filter); + console.log(url) + return fetch(url, { method: "GET", headers: Object.assign( { "Content-Type": "application/json" }, @@ -222,7 +237,8 @@ const vehiclesAPI = { ), }) .then(fetchRespHandler) - .catch(errorHandler), + .catch(errorHandler); + }, getTRexLogs: async (vin, date, offset, count, direction, token, controller) => fetch(`${API_ENDPOINT}/vehicle/${vin}/trex-logs?date=${date}&offset=${offset}&count=${count}&direction=${direction}`, { From 0851434e135ddb43945ea2396ce27b7223a379a4 Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Mon, 6 Nov 2023 14:58:20 -0800 Subject: [PATCH 2/3] add scale-down --- src/components/Contexts/CANSignalsContext.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Contexts/CANSignalsContext.jsx b/src/components/Contexts/CANSignalsContext.jsx index 4324b4c..a9408e7 100644 --- a/src/components/Contexts/CANSignalsContext.jsx +++ b/src/components/Contexts/CANSignalsContext.jsx @@ -55,7 +55,12 @@ export const CANSignalProvider = ({ token, children }) => { const items = transformSignals(result.data); if (items.length > 0) { - setDelayIndex(0); + setDelayIndex((index) => { + if (index === 0) { + return 0; + } + return index -= 1; + }); setSignals(items); } else { setDelayIndex((index) => { From 87cb44652df38479b808dc47adac7f2794a36199 Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Tue, 7 Nov 2023 21:01:02 -0800 Subject: [PATCH 3/3] use last CAN signal as timestamp for pagination --- src/components/Cars/CANSignals/index.jsx | 42 ++++++++++++++++++- src/components/Contexts/CANSignalsContext.jsx | 39 ++++++++--------- .../Contexts/CANSignalsContext.test.jsx | 11 ++--- src/services/vehiclesAPI.js | 7 +--- 4 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/components/Cars/CANSignals/index.jsx b/src/components/Cars/CANSignals/index.jsx index 5832b99..0dfe8bd 100644 --- a/src/components/Cars/CANSignals/index.jsx +++ b/src/components/Cars/CANSignals/index.jsx @@ -5,6 +5,11 @@ import { TableCell, TableHead, TableRow, + Box, + FormControl, + InputLabel, + Select, + MenuItem, } from "@material-ui/core"; import { @@ -13,7 +18,7 @@ import { } from "../../Contexts/CANSignalsContext"; const Main = ({ vin }) => { - const { signals, setVIN, duration } = useCANSignalContext(); + const { signals, setVIN, queryDate, delays, delayIndex, setDelayIndex } = useCANSignalContext(); useEffect(() => { setVIN(vin); @@ -27,7 +32,11 @@ const Main = ({ vin }) => { return ( <> - (Received within the last {duration} seconds) + + Searching every + + seconds for signals sent after {queryDate}. + @@ -56,4 +65,33 @@ const CANSignals = (props) => ( ); +const DelayController = ({ + delays, + delayIndex, + setDelayIndex +}) => { + const label = "Delay"; + const handleChange = (event) => { + setDelayIndex(event.target.value); + } + + return ( + + {label} + + + ) +} + export default CANSignals; diff --git a/src/components/Contexts/CANSignalsContext.jsx b/src/components/Contexts/CANSignalsContext.jsx index a9408e7..d399159 100644 --- a/src/components/Contexts/CANSignalsContext.jsx +++ b/src/components/Contexts/CANSignalsContext.jsx @@ -27,48 +27,42 @@ const transformSignals = (signals) => export const CANSignalProvider = ({ token, children }) => { // auto scale polling if not getting response - const durations = [10000, 30000, 60000, 120000]; const delays = [500, 1500, 3000, 6000]; + const [delayIndex, setDelayIndex] = useState(2); const [vin, setVIN] = useState(null); const [signals, setSignals] = useState([]); - const [delayIndex, setDelayIndex] = useState(0); + const [utc, setUtc] = useState(undefined); useInterval( () => { getCANSignals() }, vin ? delays[delayIndex] : null - ) + ); const getCANSignals = async () => { try { if (!vin) return; - const date = new Date(); - date.setUTCSeconds(date.getUTCSeconds() - durations[delayIndex]); - const result = await api.getCANSignals(vin, { - after_utc: date, + after_utc: utc, }, token); - if (result.error) + + if (result.error) { throw new Error(`Get CAN signals error. ${result.message}`); + } + + const mostRecentTimestamp = result.data?.[0]?.timestamp; + if (mostRecentTimestamp) { + setUtc(new Date(mostRecentTimestamp).getTime() - 50); // apply slight offset to ensure last CAN Signals sent before sleep are returned. + } else { + setUtc(new Date().getTime()); + } const items = transformSignals(result.data); if (items.length > 0) { - setDelayIndex((index) => { - if (index === 0) { - return 0; - } - return index -= 1; - }); setSignals(items); } else { - setDelayIndex((index) => { - if (index < delays.length - 1) { - return index += 1; - } - return index; - }); setSignals([BlankSignal("No signals")]); } } catch (e) { @@ -79,9 +73,12 @@ export const CANSignalProvider = ({ token, children }) => { return ( {children} diff --git a/src/components/Contexts/CANSignalsContext.test.jsx b/src/components/Contexts/CANSignalsContext.test.jsx index 57b98e8..13be103 100644 --- a/src/components/Contexts/CANSignalsContext.test.jsx +++ b/src/components/Contexts/CANSignalsContext.test.jsx @@ -8,7 +8,7 @@ import { waitFor, act, } from "@testing-library/react"; -import {CANSignalProvider, useCANSignalContext} from "./CANSignalsContext"; +import { CANSignalProvider, useCANSignalContext } from "./CANSignalsContext"; const checkSignalsResults = (filters) => { expect(screen.getByTestId("signals").innerHTML).toEqual(filters); @@ -19,14 +19,15 @@ describe("CANSignalsContext", () => { beforeEach(() => { jest.useFakeTimers("setInterval"); const TestComp = () => { - const { signals, setVIN } = useCANSignalContext(); + const { signals, setVIN, setDelayIndex } = useCANSignalContext(); + setDelayIndex(0); return ( <>
{JSON.stringify(signals)}