From 506238fb90ff4178c825027391350930f05d271e Mon Sep 17 00:00:00 2001 From: Ashwin Varughese George Date: Sun, 26 Mar 2023 15:55:26 +1100 Subject: [PATCH 1/3] Added Anemometer functionality to be displayed on the dashboard --- client/src/api/common/data.ts | 2 + .../v3/status/AnemometerStatus.stories.tsx | 16 ++ .../components/v3/status/AnemometerStatus.tsx | 217 ++++++++++++++++++ .../v3/status/AnemometerStatusContainer.tsx | 30 +++ client/src/components/v3/status/WMStatus.tsx | 29 +++ client/src/types/data.ts | 12 + client/src/views/v3/StatusView.tsx | 7 + 7 files changed, 313 insertions(+) create mode 100644 client/src/components/v3/status/AnemometerStatus.stories.tsx create mode 100644 client/src/components/v3/status/AnemometerStatus.tsx create mode 100644 client/src/components/v3/status/AnemometerStatusContainer.tsx diff --git a/client/src/api/common/data.ts b/client/src/api/common/data.ts index 48627177..c91f24e6 100644 --- a/client/src/api/common/data.ts +++ b/client/src/api/common/data.ts @@ -21,6 +21,8 @@ export enum Sensor { SteeringAngle = 'steeringAngle', CO2 = 'co2', Accelerometer = 'accelerometer', + WindSpeed = 'windSpeed', + windDirection = 'windDirection', Gyroscope = 'gyroscope', ReedVelocity = 'reedVelocity', ReedDistance = 'reedDistance', diff --git a/client/src/components/v3/status/AnemometerStatus.stories.tsx b/client/src/components/v3/status/AnemometerStatus.stories.tsx new file mode 100644 index 00000000..ecab56d2 --- /dev/null +++ b/client/src/components/v3/status/AnemometerStatus.stories.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { addArgs, createStory } from 'utils/stories'; +import { SensorDataT, SensorsT } from 'types/data'; +import WMStatus, { WMStatusProps } from './WMStatus'; + +export default { + component: WMStatus, + title: 'components/v3/status/WirelessModuleStatus', +}; + +const Template = addArgs((props) => ); + +const sensorData = (type: string, value: SensorsT): SensorDataT => ({ + type, + value, +}); diff --git a/client/src/components/v3/status/AnemometerStatus.tsx b/client/src/components/v3/status/AnemometerStatus.tsx new file mode 100644 index 00000000..52e73e3c --- /dev/null +++ b/client/src/components/v3/status/AnemometerStatus.tsx @@ -0,0 +1,217 @@ +import React from 'react'; +import { Accordion, Button, Card, Col, Table } from 'react-bootstrap'; +import OnlineStatusPill from 'components/common/OnlineStatusPill'; +import { WMStatus as WMStatusT } from 'types/data'; +import { isOnline, roundNum } from 'utils/data'; +import { camelCaseToStartCase } from 'utils/string'; + +export type WMStatusProps = WMStatusT; + +export default function WMStatus(props: WMStatusProps) { + const { moduleName, online } = props; + + const statusPill = ( + + {moduleName} + + ); + + function extractData(type: string, data: any) { + interface strMap { + [key: string]: string; + } + interface numMap2 { + [key: string]: number; + } + + const units: strMap = { + speed: 'km/h', + satellites: '', + pdop: '', + latitude: '°N', + longitude: '°E', + altitude: 'm', + course: '°', + datetime: '', + temperature: '°C', + humidity: '%', + steeringAngle: '°', + co2: 'ppm', + power: 'W', + cadence: 'rpm', + heartRate: 'bpm', + reedVelocity: 'km/h', + reedDistance: 'km', + antSpeed: 'km/h', + antDistance: 'km', + }; + + const decimals: numMap2 = { + speed: 2, + satellites: 0, + pdop: 2, + latitude: 5, + longitude: 5, + altitude: 1, + course: 1, + temperature: 1, + humidity: 0, + steeringAngle: 1, + co2: 0, + power: 0, + cadence: 0, + heartRate: 0, + reedVelocity: 2, + reedDistance: 2, + antSpeed: 2, + antDistance: 2, + x: 2, + y: 2, + z: 2, + }; + + /** + * receives a value and its unit and format them appropriately + * + * @param name type's name + * @param value type's value + * @param unit the unit + * @returns string containing the value and its unit + */ + function formatValue(name: string, value: any, unit: any) { + let displayValue; + let val = value; + if (val !== null && val !== undefined) { + if (name === 'Date' || name === 'Time') { + displayValue = + name === 'Date' ? value.substring(0, 10) : value.substring(11, 19); + } else { + const dec = decimals[name]; + if (unit === 'km') { + val /= 1000; + } else if (unit === 'km/h') { + val *= 3.6; + } + displayValue = roundNum(val, dec); + } + } else { + displayValue = '-'; + } + const displayUnit = unit ? ` ${unit}` : ''; + + return `${displayValue}${displayUnit}`; + } + + let output = <>; + if (type === 'anemometer') { + const anemRows: any[] = []; + Object.entries(data).forEach((arr) => { + anemRows.push({ name: arr[0], value: arr[1] }); + }); + output = ( + + + {anemRows.map(({ name, value }) => ( + + + + + ))} + +
{camelCaseToStartCase(name.toLowerCase())} +
+ {formatValue(name, value, '')} +
+
+ ); + } else { + output = ( +
+ {formatValue(type, JSON.stringify(data), units[type])} +
+ ); + } + return output; + } + + let info = <> ; + + if (isOnline(props)) { + const { data, batteryVoltage } = props; + info = ( + <> + + + {/* Battery Voltage */} + + + + + + {/* Sensors List of Names */} + + + + + +
+ Battery Voltage + {batteryVoltage ? batteryVoltage.toFixed(2) : '-'} V
+ Sensors + + {data + .map(({ type }) => camelCaseToStartCase(type.toLowerCase())) + .join(', ')} +
+ + {/* Sensor Data Toggle Section */} + + + + Sensor Data + + + + + + {data.map(({ type, value }) => ( + + + + + ))} + +
+ + {camelCaseToStartCase(type.toLowerCase())} + + {extractData(type, value)}
+
+
+
+
+ + ); + } + + return ( + + {statusPill} + + {/* Only show more information if the camera is online */} + {info} + + ); +} diff --git a/client/src/components/v3/status/AnemometerStatusContainer.tsx b/client/src/components/v3/status/AnemometerStatusContainer.tsx new file mode 100644 index 00000000..23392081 --- /dev/null +++ b/client/src/components/v3/status/AnemometerStatusContainer.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Card, Row } from 'react-bootstrap'; + +import AnemometerStatus from 'components/v3/status/AnemometerStatus'; +import { useModuleStatus } from 'api/common/data'; + +/** + * Container for Wireless Module Statuses + * + * @returns Component + */ +export default function AnemometerStatusContainer() { + const front = useModuleStatus(1, 'Wind Speed'); + const back = useModuleStatus(3, 'Wind Direction'); + + return ( + + + Anemometer + + {/* Front WM Status */} + + + {/* Back WM Status */} + + + + + ); +} diff --git a/client/src/components/v3/status/WMStatus.tsx b/client/src/components/v3/status/WMStatus.tsx index f7b1d0cf..ccc2cda3 100644 --- a/client/src/components/v3/status/WMStatus.tsx +++ b/client/src/components/v3/status/WMStatus.tsx @@ -148,6 +148,35 @@ export default function WMStatus(props: WMStatusProps) { ); + } else if (type === 'anemometer') { + const anemRows: any[] = []; + Object.entries(data).forEach((arr) => { + anemRows.push({ name: arr[0], value: arr[1] }); + }); + output = ( + + + {anemRows.map(({ name, value }) => ( + + + + + ))} + +
{camelCaseToStartCase(name.toLowerCase())} +
+ {formatValue(name, value, '')} +
+
+ ); } else if (type === 'gyroscope') { const gyroRows: any[] = []; Object.entries(data).forEach((arr) => { diff --git a/client/src/types/data.ts b/client/src/types/data.ts index 57c5bf3a..67f5a988 100644 --- a/client/src/types/data.ts +++ b/client/src/types/data.ts @@ -37,6 +37,14 @@ export const GyroscopeRT = Record({ z: Number, }); +export const AnemometerRT = Record({ + /** Wind Speed value */ + windSpeed: Number, + + /** Wind Direction value */ + windDirection: Number, +}); + /** Value runtype of reedVelocity sensor data */ export const ReedVelocityRT = Number; @@ -92,6 +100,7 @@ export const SensorsRT = Union( PowerRT, CadenceRT, HeartRateRT, + AnemometerRT, ); /** Sensor data as incoming from MQTT */ @@ -117,6 +126,9 @@ export type CO2T = Static; /** Value type of accelerometer sensor data */ export type AccelerometerT = Static; +/** Value type of aneomometer sensor data */ +export type AnemometerRT = Static; + /** Value type of gyroscope sensor data */ export type GyroscopeT = Static; diff --git a/client/src/views/v3/StatusView.tsx b/client/src/views/v3/StatusView.tsx index de59ba9e..14032451 100644 --- a/client/src/views/v3/StatusView.tsx +++ b/client/src/views/v3/StatusView.tsx @@ -3,6 +3,7 @@ import { Row, Col } from 'react-bootstrap'; import ContentPage from 'components/common/ContentPage'; import CameraStatusContainer from 'components/v3/status/CameraStatusContainer'; import WMStatusContainer from 'components/v3/status/WMStatusContainer'; +import AnemometerStatusContainer from 'components/v3/status/AnemometerStatusContainer'; /** * Status View component @@ -23,6 +24,12 @@ export default function StatusView(): JSX.Element { + + {/* Anemometer Status */} + + + + ); } From 64fc88d131fdf495ecb5087ec2ffcd3f915476c3 Mon Sep 17 00:00:00 2001 From: Ashwin George Date: Mon, 8 May 2023 13:14:57 +1000 Subject: [PATCH 2/3] anemometer status container get data from WMStatus --- client/src/components/v3/status/AnemometerStatus.tsx | 2 +- .../v3/status/AnemometerStatusContainer.tsx | 12 +++++++----- client/src/types/data.ts | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/src/components/v3/status/AnemometerStatus.tsx b/client/src/components/v3/status/AnemometerStatus.tsx index 52e73e3c..c5def866 100644 --- a/client/src/components/v3/status/AnemometerStatus.tsx +++ b/client/src/components/v3/status/AnemometerStatus.tsx @@ -210,7 +210,7 @@ export default function WMStatus(props: WMStatusProps) { {statusPill} - {/* Only show more information if the camera is online */} + {/* Only show more information if the anemometer is online */} {info} ); diff --git a/client/src/components/v3/status/AnemometerStatusContainer.tsx b/client/src/components/v3/status/AnemometerStatusContainer.tsx index 23392081..143931b5 100644 --- a/client/src/components/v3/status/AnemometerStatusContainer.tsx +++ b/client/src/components/v3/status/AnemometerStatusContainer.tsx @@ -4,14 +4,16 @@ import { Card, Row } from 'react-bootstrap'; import AnemometerStatus from 'components/v3/status/AnemometerStatus'; import { useModuleStatus } from 'api/common/data'; +import WMStatus from 'components/v3/status/WMStatus'; + /** - * Container for Wireless Module Statuses + * Container for Anemometer Statuses * * @returns Component */ export default function AnemometerStatusContainer() { - const front = useModuleStatus(1, 'Wind Speed'); - const back = useModuleStatus(3, 'Wind Direction'); + const speed = useModuleStatus(1, 'Wind Speed'); + const direction = useModuleStatus(3, 'Wind Direction'); return ( @@ -19,10 +21,10 @@ export default function AnemometerStatusContainer() { Anemometer {/* Front WM Status */} - + {/* Back WM Status */} - + diff --git a/client/src/types/data.ts b/client/src/types/data.ts index 67f5a988..bc5c3199 100644 --- a/client/src/types/data.ts +++ b/client/src/types/data.ts @@ -127,7 +127,7 @@ export type CO2T = Static; export type AccelerometerT = Static; /** Value type of aneomometer sensor data */ -export type AnemometerRT = Static; +export type AnemometerT = Static; /** Value type of gyroscope sensor data */ export type GyroscopeT = Static; From 2d7cb53e36083dc1f96b7da70bff69cde9bfb745 Mon Sep 17 00:00:00 2001 From: Ashwin George Date: Mon, 8 May 2023 13:46:11 +1000 Subject: [PATCH 3/3] consolelog data --- client/src/components/v3/status/AnemometerStatus.tsx | 1 + client/src/components/v3/status/AnemometerStatusContainer.tsx | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/v3/status/AnemometerStatus.tsx b/client/src/components/v3/status/AnemometerStatus.tsx index c5def866..9031098a 100644 --- a/client/src/components/v3/status/AnemometerStatus.tsx +++ b/client/src/components/v3/status/AnemometerStatus.tsx @@ -107,6 +107,7 @@ export default function WMStatus(props: WMStatusProps) { const anemRows: any[] = []; Object.entries(data).forEach((arr) => { anemRows.push({ name: arr[0], value: arr[1] }); + console.log(data); }); output = ( diff --git a/client/src/components/v3/status/AnemometerStatusContainer.tsx b/client/src/components/v3/status/AnemometerStatusContainer.tsx index 143931b5..164acf45 100644 --- a/client/src/components/v3/status/AnemometerStatusContainer.tsx +++ b/client/src/components/v3/status/AnemometerStatusContainer.tsx @@ -4,8 +4,6 @@ import { Card, Row } from 'react-bootstrap'; import AnemometerStatus from 'components/v3/status/AnemometerStatus'; import { useModuleStatus } from 'api/common/data'; -import WMStatus from 'components/v3/status/WMStatus'; - /** * Container for Anemometer Statuses *