1+ import { Box , Paper , Typography } from "@mui/material" ;
2+ import React , { useEffect , useState } from "react" ;
3+ import VideoFeed from "../components/VideoFeed" ;
4+ import OnePedalDrive from "../components/OnePedalDrive" ;
5+ import { io } from "socket.io-client" ;
6+
7+ const socket = io ( "http://localhost:5050" ) ;
8+ const MAX_LENGTH = 50 ;
9+
10+ type DataSet = { value : number ; timestamp : Date } [ ] ;
11+ interface Data {
12+ car_speed : DataSet ;
13+ battery_temp : DataSet ;
14+ panel_temp : DataSet ;
15+ pedal_value : DataSet ;
16+ }
17+
18+ interface Update {
19+ number : number ;
20+ timestamp : string ;
21+ }
22+
23+ type StringDataSet = { value : string ; timestamp : Date } [ ] ;
24+ interface StringData {
25+ gear_state : StringDataSet ;
26+ hazard_state : StringDataSet ;
27+ turn_state : StringDataSet ;
28+ }
29+ interface StringUpdate {
30+ string : string ;
31+ timestamp : string ;
32+ }
33+
34+ const HeadsUpPage = ( ) => {
35+ const [ data , setData ] = useState < Data > ( {
36+ car_speed : [ ] ,
37+ battery_temp : [ ] ,
38+ panel_temp : [ ] ,
39+ pedal_value : [ ] ,
40+ } ) ;
41+
42+ const [ stringData , setStringData ] = useState < StringData > ( {
43+ gear_state : [ ] ,
44+ hazard_state : [ ] ,
45+ turn_state : [ ] ,
46+ } ) ;
47+
48+ useEffect ( ( ) => {
49+ //Attaches socket listeners for each value of the data object on mount
50+ Object . keys ( data ) . forEach ( ( name ) => {
51+ socket . on ( name , ( update : Update ) => {
52+ setData ( ( oldData ) => {
53+ const updatedData = {
54+ ...oldData ,
55+ [ name ] : [
56+ ...oldData [ name as keyof Data ] ,
57+ { value : update . number , timestamp : new Date ( update . timestamp ) } ,
58+ ] ,
59+ } ;
60+ if ( updatedData [ name as keyof Data ] . length > MAX_LENGTH ) {
61+ updatedData [ name as keyof Data ] = updatedData [ name as keyof Data ] . slice ( - MAX_LENGTH ) ;
62+ }
63+ return updatedData ;
64+ } ) ;
65+ } ) ;
66+ } ) ;
67+
68+ Object . keys ( stringData ) . forEach ( ( name ) => {
69+ socket . on ( name , ( update : StringUpdate ) => {
70+ setStringData ( ( oldData ) => {
71+ const updatedData = {
72+ ...oldData ,
73+ [ name ] : [
74+ ...oldData [ name as keyof StringData ] ,
75+ { value : update . string , timestamp : new Date ( update . timestamp ) } ,
76+ ] ,
77+ } ;
78+ if ( updatedData [ name as keyof StringData ] . length > MAX_LENGTH ) {
79+ updatedData [ name as keyof StringData ] = updatedData [ name as keyof StringData ] . slice ( - MAX_LENGTH ) ;
80+ }
81+ return updatedData ;
82+ } ) ;
83+ } ) ;
84+ } ) ;
85+
86+ //Removes all socket listeners for each value of the data object on unmount
87+ //This is to prevent multiple listeners from being attached to the same value
88+ return ( ) => {
89+ Object . keys ( data ) . forEach ( ( name ) => {
90+ socket . off ( name ) ;
91+ } ) ;
92+ } ;
93+ } , [ ] ) ;
94+
95+ return (
96+ < Box p = "16px" height = "100vh" boxSizing = "border-box" >
97+ < h1 > Heads up</ h1 >
98+ < Box
99+ height = "75%"
100+ display = "flex"
101+ flexDirection = "row"
102+ gap = "16px"
103+ justifyContent = "center"
104+ >
105+ < Box >
106+ { /* Replace this paper component with mph */ }
107+ < Paper
108+ sx = { {
109+ flex : "1 0 0" ,
110+ display : "flex" ,
111+ alignItems : "center" ,
112+ justifyContent : "center" ,
113+ } }
114+ >
115+ < Typography > MPH</ Typography >
116+ </ Paper >
117+ </ Box >
118+ < Box >
119+ < VideoFeed />
120+ </ Box >
121+ </ Box >
122+ < OnePedalDrive value = { data . pedal_value . length != 0 ? data . pedal_value [ data . pedal_value . length - 1 ] . value : 50 } />
123+ </ Box >
124+ ) ;
125+ } ;
126+
127+ export default HeadsUpPage ;
0 commit comments