+
@@ -101,45 +113,27 @@ const SendCommand = ({ vins }) => {
))}
-
-
- Parameter
-
-
-
-
+
);
};
diff --git a/src/components/Controls/SendCommand/sanitize.js b/src/components/Controls/SendCommand/sanitize.js
new file mode 100644
index 0000000..45560e5
--- /dev/null
+++ b/src/components/Controls/SendCommand/sanitize.js
@@ -0,0 +1,115 @@
+export const onOff = {
+ false: "off",
+ true: "on",
+}
+
+export const onOffTemp = {
+ 0: "off",
+ 1: "on",
+ ...Object.fromEntries(Array.from({length: 26}, (_, i) => [i+2, `${i+15}`]))
+}
+
+export const precond = {
+ 0: "battery",
+ 1: "all",
+ 2: "climate",
+ 3: "stop"
+}
+
+export const hmol = {
+ 0: "off",
+ 1: "low",
+ 2: "mid",
+ 3: "high"
+}
+
+export const emptyCommands = [
+ "doors_lock", "doors_unlock", "vent_windows",
+ "close_windows", "trunk_close", "flash_headlights",
+ "alert"
+]
+
+export const onOffCommands = ["california_mode", "steering_wheel_preheat", "defrost", "charging"]
+
+export const hmolCommands = ["passenger_seat_preheat", "driver_seat_preheat"]
+
+
+const removeIfFieldsAreEmpty = (cmd, fields) => {
+ for (const field of fields) {
+ if (cmd[field] == null) {
+ delete cmd[field]
+ }
+ }
+
+ return cmd
+}
+
+const tempCabinPeriodConvert = (cmd) => {
+ if (cmd.data == null || typeof cmd.data !== "number" || cmd.data < 0 || cmd.data > 27) {
+ cmd.data = 0
+ }
+
+ cmd.data = onOffTemp[cmd.data]
+
+ return cmd
+}
+
+const onOffConvert = (cmd) => {
+ if (cmd.data == null || cmd.data !== true) {
+ cmd.data = false
+ }
+
+ cmd.data = onOff[cmd.data]
+
+ return cmd
+}
+
+const precondConvert = cmd => {
+ if (cmd.data == null || typeof cmd.data !== "number" || cmd.data < 0 || cmd.data > 3) {
+ cmd.data = 0
+ }
+
+ cmd.data = precond[cmd.data]
+
+ return cmd
+}
+
+const hmolConvert = (cmd) => {
+ if (cmd.data == null || typeof cmd.data !== "number" || cmd.data < 0 || cmd.data > 3) {
+ cmd.data = 0
+ }
+
+ cmd.data = hmol[cmd.data]
+
+ return cmd
+}
+
+const trunkOpenConvert = (cmd) => {
+ if (cmd.data == null || typeof cmd.data !== "number" || cmd.data < 1 || cmd.data > 5) {
+ cmd.data = 1
+ }
+
+ cmd.data = cmd.data.toString()
+
+ return cmd
+}
+
+export const sanitize = (cmd) => {
+ cmd = removeIfFieldsAreEmpty(cmd, ["data", "start", "end"])
+
+ if (onOffCommands.includes(cmd.command)) {
+ cmd = onOffConvert(cmd)
+ } else if (hmolCommands.includes(cmd.command)) {
+ cmd = hmolConvert(cmd)
+ } else if (cmd.command === "precondition") {
+ cmd = precondConvert(cmd)
+ } else if (cmd.command === "trunk_open") {
+ cmd = trunkOpenConvert(cmd)
+ } else if (cmd.command === "temp_cabin") {
+ cmd = tempCabinPeriodConvert(cmd)
+ } else {
+ delete cmd.data;
+ }
+
+ return cmd
+}
diff --git a/src/components/Controls/SendCommand/sanitize.test.js b/src/components/Controls/SendCommand/sanitize.test.js
new file mode 100644
index 0000000..4e748f6
--- /dev/null
+++ b/src/components/Controls/SendCommand/sanitize.test.js
@@ -0,0 +1,150 @@
+import {emptyCommands, hmol, hmolCommands, onOff, onOffCommands, onOffTemp, precond, sanitize,} from "./sanitize";
+
+const randomValues = [null, undefined, "someString", 33]
+
+describe("Sanitize test", () => {
+ it("empty commands", () => {
+ for (const command of emptyCommands) {
+ const cmd = sanitize({command})
+ expect(cmd.command).toEqual(command)
+ expect("data" in cmd).toEqual(false);
+ expect("start" in cmd).toEqual(false);
+ expect("end" in cmd).toEqual(false);
+ }
+ })
+
+ it("on-off commands with proper values", () => {
+ for (const command of onOffCommands) {
+ for (const data of [false, true]) {
+ const cmd = sanitize({command, data})
+
+ expect(cmd.data).toEqual(onOff[data])
+ expect(cmd.command).toEqual(command)
+ expect("start" in cmd).toEqual(false);
+ expect("end" in cmd).toEqual(false);
+ }
+ }
+ })
+
+ it("on-off commands with dirty values", () => {
+ for (const command of onOffCommands) {
+ const cmd = {command}
+ for (const rVal of randomValues) {
+ if (rVal !== undefined) {
+ cmd.data = rVal
+ }
+ const res = sanitize(cmd)
+
+ expect(res.data).toEqual("off")
+ expect(res.command).toEqual(command)
+ expect("start" in res).toEqual(false);
+ expect("end" in res).toEqual(false);
+ }
+ }
+ })
+
+ it("high-mid-low-off with proper values", () => {
+ for (const command of hmolCommands) {
+ for (const data of [0,1,2,3]) {
+ const cmd = sanitize({command, data})
+
+ expect(cmd.data).toEqual(hmol[data])
+ expect(cmd.command).toEqual(command)
+ expect("start" in cmd).toEqual(false);
+ expect("end" in cmd).toEqual(false);
+ }
+ }
+ })
+
+ it("precondition with proper values", () => {
+ for (const data of [0,1,2,3]) {
+ const cmd = sanitize({command:"precondition", data})
+
+ expect(cmd.data).toEqual(precond[data])
+ expect(cmd.command).toEqual("precondition")
+ expect("start" in cmd).toEqual(false);
+ expect("end" in cmd).toEqual(false);
+ }
+ })
+
+ it("precondition with wrong values", () => {
+ const cmd = {command:"precondition"}
+ for (const rVal of randomValues) {
+ if (rVal !== undefined) {
+ cmd.data = rVal
+ }
+ const res = sanitize(cmd)
+
+ expect(res.data).toEqual("battery")
+ expect(res.command).toEqual("precondition")
+ expect("start" in res).toEqual(false);
+ expect("end" in res).toEqual(false);
+ }
+ })
+
+
+
+ it("high-mid-low-off with wrong values", () => {
+ for (const command of hmolCommands) {
+ const cmd = {command}
+ for (const rVal of randomValues) {
+ if (rVal !== undefined) {
+ cmd.data = rVal
+ }
+ const res = sanitize(cmd)
+
+ expect(res.data).toEqual("off")
+ expect(res.command).toEqual(command)
+ expect("start" in res).toEqual(false);
+ expect("end" in res).toEqual(false);
+ }
+ }
+ })
+
+ it("open trunk", () => {
+ const cmd = {command: "trunk_open"}
+ for (let i = 1; i <= 5; i++) {
+ cmd.data = i
+
+ const res = sanitize(cmd)
+
+ expect(res.data).toEqual(i.toString())
+ expect(res.command).toEqual("trunk_open")
+ expect("start" in res).toEqual(false);
+ expect("end" in res).toEqual(false);
+ }
+ })
+
+ it("open trunk with wrong values", () => {
+ const cmd = {command: "trunk_open"}
+ for (const rVal of randomValues) {
+ if (rVal !== undefined) {
+ cmd.data = rVal
+ }
+ const res = sanitize(cmd)
+
+ expect(res.data).toEqual("1")
+ expect(res.command).toEqual("trunk_open")
+ expect("start" in res).toEqual(false);
+ expect("end" in res).toEqual(false);
+ }
+ })
+
+
+ it("cabin temp with period with proper values", () => {
+ for (let i = 0; i <= 27; i++) {
+ const res = sanitize({
+ command: "temp_cabin",
+ data: i,
+ start: new Date(),
+ end: new Date(),
+ })
+
+
+ expect(res.command).toEqual("temp_cabin")
+ expect(res.data).toEqual(onOffTemp[i])
+ expect(typeof res.start).toEqual("object")
+ expect(typeof res.end).toEqual("object")
+ }
+ })
+})
\ No newline at end of file
diff --git a/src/services/__mocks__/vehiclesAPI.js b/src/services/__mocks__/vehiclesAPI.js
index ea3d879..b66976c 100644
--- a/src/services/__mocks__/vehiclesAPI.js
+++ b/src/services/__mocks__/vehiclesAPI.js
@@ -94,11 +94,10 @@ const vehiclesAPI = {
data: [2021, 2022],
};
},
- sendCommand: async (vin, command, parameters) => {
+ sendCommand: async (vin, command) => {
return {
vin,
command,
- parameters,
};
},
updateVehicle: async (vin, vehicle) => {
diff --git a/src/services/commands.js b/src/services/commands.js
index ac1c305..53806da 100644
--- a/src/services/commands.js
+++ b/src/services/commands.js
@@ -1,81 +1,26 @@
-const Locks = [
+const Commands = [
+ {value: "doors_lock", label: "Lock doors"},
+ {value: "doors_unlock", label: "Unlock doors"},
+ {value: "vent_windows", label: "Vent windows"},
+ {value: "close_windows", label: "Close windows"},
+ {value: "california_mode", label: "California mode"},
+ {value: "trunk_open", label: "Open trunk"},
+ {value: "trunk_close", label: "Close trunk "},
+ {value: "flash_headlights", label: "Flash headlights"},
+ {value: "alert", label: "Alert"},
+ {value: "temp_cabin", label: "Set cabin temperature"},
{
- value: "right_front",
- label: "Front right door",
- },{
- value: "left_front",
- label: "Front left door",
- },{
- value: "right_rear",
- label: "Rear right door",
- },{
- value: "left_rear",
- label: "Rear left door",
- },{
- value: "trunk",
- label: "Trunk",
+ value: "temp_cabin",
+ label: "Set cabin temperature for period",
+ params: {
+ data: ""
+ },
},
-];
-
-const Windows = [
- {
- value: "right_front",
- label: "Front right window",
- },{
- value: "left_front",
- label: "Front left window",
- },{
- value: "right_rear",
- label: "Rear right window",
- },{
- value: "left_rear",
- label: "Rear left window",
- },
-];
-
-const Commands = [{
- value: "lock",
- label: "Lock door",
- parameters: Locks,
- },
- {
- value: "unlock",
- label: "Unlock door",
- parameters: Locks,
- },{
- value: "open",
- label: "Open window",
- parameters: Windows,
- },
- {
- value: "close",
- label: "Close window",
- parameters: Windows,
- },
- {
- value: "ecu",
- label: "ECU Versions",
- },
- {
- value: "log",
- label: "Log level",
- parameters: [
- {
- value: "info",
- label: "Info",
- },
- {
- value: "debug",
- label: "Debug",
- },
- {
- value: "trace",
- label: "Trace",
- },
- ],
- },{
- value: "headlights",
- label: "Flash headlights",
- }];
+ {value: "defrost", label: "Defrost"},
+ {value: "driver_seat_preheat", label: "Driver seat preheat"},
+ {value: "passenger_seat_preheat", label: "Preheat passenger seat"},
+ {value: "steering_wheel_preheat", label: "Preheat Steering wheel"},
+ {value: "precondition", label: "Precondition"},
+ {value: "charging", label: "Charging"}]
export default Commands;
diff --git a/src/services/vehiclesAPI.js b/src/services/vehiclesAPI.js
index d57c1d0..d99c1d2 100644
--- a/src/services/vehiclesAPI.js
+++ b/src/services/vehiclesAPI.js
@@ -125,7 +125,7 @@ const vehiclesAPI = {
.then(fetchRespHandler)
.catch(errorHandler),
- sendCommand: async (vins, command, parameters, token) =>
+ sendCommand: async (vins, command, token) =>
fetch(`${API_ENDPOINT}/vehiclecommand`, {
method: "POST",
headers: Object.assign(
@@ -134,8 +134,7 @@ const vehiclesAPI = {
),
body: JSON.stringify({
vins,
- command,
- parameters,
+ ...command,
}),
})
.then(fetchRespHandler)