Skip to content

Commit bad0b03

Browse files
committed
new
1 parent 57fd35b commit bad0b03

35 files changed

+1137
-255
lines changed

public/dcv/dcv23.glb

6.03 MB
Binary file not shown.

public/dials/dial_thermoemter6.glb

2.25 MB
Binary file not shown.

public/dials/dial_thermometer1.glb

5.73 MB
Binary file not shown.

public/dials/dial_thermometer5.glb

2.25 MB
Binary file not shown.

public/knobs/currentKnob.glb

354 KB
Binary file not shown.

public/knobs/vvrKnob.fbx

446 KB
Binary file not shown.

public/knobs/vvrKnob15.glb

18.4 MB
Binary file not shown.

public/knobs/vvrKnob17.glb

18.5 MB
Binary file not shown.

public/knobs/vvrKnob22.glb

18.5 MB
Binary file not shown.

public/labIcons/fh.png

2.68 MB
Loading

public/thermometer/thermometer11.glb

3.13 MB
Binary file not shown.

public/thermometer/thermometer6.glb

-1.15 MB
Binary file not shown.

src/App.tsx

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1-
import React from "react"
2-
import { RouterProvider } from "react-router-dom"
3-
import routers from "./routes"
1+
import React from "react";
2+
import { RouterProvider } from "react-router-dom";
3+
import routers from "./routes";
4+
import { ThemeProvider, CssBaseline } from "@mui/material";
5+
import { createTheme } from "@mui/material/styles";
46

5-
const App: React.FC = () => <RouterProvider router={routers} />
7+
const theme = createTheme({
8+
palette: {
9+
mode: "light", // Set default theme to light
10+
},
11+
});
612

7-
export default App
13+
const App: React.FC = () => (
14+
<ThemeProvider theme={theme}>
15+
<CssBaseline />
16+
<RouterProvider router={routers} />
17+
</ThemeProvider>
18+
);
19+
20+
export default App;

src/LABS/Lab1MainComponent.tsx

+16-12
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ import VVR from "../labComponents/FrankHertzMainComp/VariableVoltageRegulator/ma
1616
import FloatingSquare from "../taskbar/mainBlock.tsx";
1717
import { CameraProvider } from "../contexts/cameraPositionContext.tsx";
1818
import Lab1Camera from "./cameras/lab1Camera.tsx";
19+
import { WebSocketProvider } from '../contexts/websocketContext';
1920

2021
const GraphPaperComponent: React.FC = () => {
2122
return (
2223
<Suspense
2324
fallback={<CornerText position="top-left" text="Loading your Lab..." />}
2425
>
2526
<CameraProvider>
26-
27+
{/* <WebSocketProvider url="ws://localhost:8080/" labID="frankhertz1"> */}
2728
<div style={{ width: "100vw", height: "100vh", overflow: "hidden" }}>
2829
<CornerText position="top-left" text="Frank-Hertz Lab" />
2930
<FloatingSquare />
@@ -36,8 +37,6 @@ const GraphPaperComponent: React.FC = () => {
3637
}}
3738
>
3839
{/* Raycasting Component */}
39-
<RaycastingComponent />
40-
4140
{/* Camera and Thermometer */}
4241
<Lab1Camera/>
4342

@@ -49,16 +48,21 @@ const GraphPaperComponent: React.FC = () => {
4948
{/* <ControlsComponent /> */}
5049

5150
{/* Components: From Bottom to Top*/}
52-
<Grid />
53-
<TripleOutput position={[-22, -0.3, 22]} />
54-
<CurrentInstrument position={[27, 0.5, 0]} />
55-
<OakPlank />
56-
<FrankHertzMain position={[5, 12, 0]}/>
57-
<CurrentRegulator position={[40, 26, 5]}/>
58-
<DVM position={[20, 30, 23]} scale={[1.7, 1.7, 1.85]} unique_id="DVM_2"/>
59-
<VVR position={[-30, 24, 2]} />
60-
<DVM position={[30, 80, 8]} scale={[1.7, 1.7, 1.85]} rotation={[0, Math.PI, 0]} unique_id="DVM_1"/> </Canvas>
51+
<WebSocketProvider url="ws://localhost:8080/" labID="frankhertz1">
52+
<RaycastingComponent />
53+
<Grid />
54+
<TripleOutput position={[-22, -0.3, 22]} />
55+
<CurrentInstrument position={[27, 0.5, 0]} />
56+
<OakPlank />
57+
<FrankHertzMain position={[5, 12, 0]}/>
58+
<CurrentRegulator position={[40, 26, 5]}/>
59+
<DVM position={[20, 30, 23]} scale={[1.7, 1.7, 1.85]} unique_id="DVM_2"/>
60+
<VVR position={[-30, 24, 2]} />
61+
<DVM position={[30, 80, 8]} scale={[1.7, 1.7, 1.85]} rotation={[0, Math.PI, 0]} unique_id="DVM_1"/>
62+
</WebSocketProvider>
63+
</Canvas>
6164
</div>
65+
{/* </WebSocketProvider> */}
6266
</CameraProvider>
6367
</Suspense>
6468
)

src/contexts/frontFaceContext.tsx

-25
This file was deleted.

src/contexts/websocketContext.tsx

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import React, {
2+
createContext,
3+
useContext,
4+
useEffect,
5+
useState,
6+
useRef,
7+
PropsWithChildren,
8+
} from "react";
9+
10+
interface WebSocketContextType {
11+
sendMessage: (message: { type: string; payload?: any }) => void;
12+
registerHandler: (type: string, handler: (payload: any) => void) => void;
13+
}
14+
15+
// Create a WebSocket context
16+
const WebSocketContext = createContext<WebSocketContextType | null>(null);
17+
18+
interface WebSocketProviderProps {
19+
url: string;
20+
labID: string;
21+
}
22+
23+
export const WebSocketProvider: React.FC<PropsWithChildren<WebSocketProviderProps>> = ({
24+
url,
25+
labID,
26+
children,
27+
}) => {
28+
const socketRef = useRef<WebSocket | null>(null);
29+
const handlersRef = useRef<Map<string, (payload: any) => void>>(new Map());
30+
31+
useEffect(() => {
32+
const ws = new WebSocket(url);
33+
socketRef.current = ws;
34+
35+
ws.onopen = async () => {
36+
try {
37+
// Make a request to the Django endpoint to get verification token and email
38+
const response = await fetch("http://127.0.0.1:8000/auth/get_email_and_verification/", {
39+
method: "POST",
40+
credentials: "include",
41+
headers: {
42+
"Content-Type": "application/json",
43+
},
44+
body: JSON.stringify({ lab_id: labID }),
45+
});
46+
47+
if (!response.ok) {
48+
throw new Error(`Django request failed: ${response.statusText}`);
49+
}
50+
51+
const data = await response.json();
52+
53+
ws.send(
54+
JSON.stringify({
55+
type: "initial_message",
56+
payload: {
57+
verification_token: data.verification_token,
58+
user_email: data.user_email,
59+
lab_id: data.lab_id,
60+
},
61+
})
62+
);
63+
64+
} catch (error) {
65+
console.error("Error fetching verification token and email:", error);
66+
}
67+
};
68+
69+
ws.onmessage = (event) => {
70+
try {
71+
if (!event.data || event.data === "null") { // Check if the message is null or empty
72+
console.log("state change")
73+
return;
74+
}
75+
const { type, payload } = JSON.parse(event.data);
76+
const handler = handlersRef.current.get(type);
77+
if (handler) {
78+
handler(payload); // Call the registered handler
79+
} else {
80+
console.warn(`No handler found for type: ${type}`);
81+
}
82+
} catch (err) {
83+
console.error("Error parsing WebSocket message:", err);
84+
}
85+
};
86+
87+
ws.onerror = (error) => {
88+
console.error("WebSocket Error:", error);
89+
};
90+
91+
ws.onclose = () => {
92+
console.log("WebSocket connection closed. Attempting to reconnect...");
93+
setTimeout(() => {
94+
const newWs = new WebSocket(url);
95+
socketRef.current = newWs;
96+
}, 3000);
97+
};
98+
99+
return () => {
100+
ws.close();
101+
};
102+
}, [url]);
103+
104+
const sendMessage = (message: { type: string; payload?: any }) => {
105+
if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
106+
socketRef.current.send(JSON.stringify(message));
107+
} else {
108+
console.error("WebSocket not connected.");
109+
}
110+
};
111+
112+
const registerHandler = (type: string, handler: (payload: any) => void) => {
113+
handlersRef.current.set(type, handler); // Update the ref directly
114+
};
115+
116+
return (
117+
<WebSocketContext.Provider value={{ sendMessage, registerHandler }}>
118+
{children}
119+
</WebSocketContext.Provider>
120+
);
121+
};
122+
123+
export const useWebSocket = () => {
124+
const context = useContext(WebSocketContext);
125+
if (!context) {
126+
throw new Error("useWebSocket must be used within a WebSocketProvider");
127+
}
128+
return context;
129+
};

src/hooks/useFrontFaceContext.tsx

-14
This file was deleted.

src/labComponents/FrankHertzMainComp/VariableVoltageRegulator/knob.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const OvenKnob: React.FC<OvenKnobProps> = ({
1919
const groupRef = useRef<THREE.Group | null>(null)
2020

2121
// Load GLTF
22-
const gltf = useLoader(GLTFLoader, "/knobs/oven_knob1.glb")
22+
const gltf = useLoader(GLTFLoader, "/knobs/vvrKnob22.glb")
2323
const [model, setModel] = useState<THREE.Object3D | null>(null)
2424

2525
useEffect(() => {
@@ -28,6 +28,7 @@ const OvenKnob: React.FC<OvenKnobProps> = ({
2828

2929
clonedScene.traverse((child) => {
3030
if ((child as THREE.Mesh).isMesh) {
31+
console.log(child)
3132
const mesh = child as THREE.Mesh
3233
mesh.userData.unique_id = unique_id
3334
mesh.userData.type = "VVR_knob"

src/labComponents/FrankHertzMainComp/VariableVoltageRegulator/mainframe.tsx

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React, { useRef, useEffect, useState } from "react"
2+
import { useFrame } from "@react-three/fiber"
23
import { useLoader } from "@react-three/fiber"
3-
import { GLTFLoader } from "three-stdlib"
4+
import { GLTFLoader, PLYLoader } from 'three-stdlib';
45
import * as THREE from "three"
56
import OvenKnob from "./knob"
7+
import { useWebSocket } from "../../../contexts/websocketContext"
68

79
interface VVRProps {
810
position: [number, number, number]
@@ -20,7 +22,10 @@ const VVR: React.FC<VVRProps> = ({
2022
// Load GLTF
2123
const gltf = useLoader(GLTFLoader, "/vvr/vvr6.glb")
2224
const [model, setModel] = useState<THREE.Object3D | null>(null)
23-
25+
const { sendMessage, registerHandler } = useWebSocket(); // Use WebSocket context
26+
const [angle, setAngle] = useState<number>(0);
27+
const cooldownRef = useRef(0); // Time accumulator for cooldown
28+
2429
useEffect(() => {
2530
if (gltf.scene) {
2631
const clonedScene = gltf.scene.clone()
@@ -36,10 +41,27 @@ const VVR: React.FC<VVRProps> = ({
3641
}
3742
}, [gltf])
3843

44+
// useEffect(() => {
45+
// registerHandler("dial_vvr_1_angle", (payload) => {
46+
// console.log('received payload', payload)
47+
// setAngle(payload.angle);
48+
// console.log(payload.id)
49+
// });
50+
// }, []);
51+
52+
// useFrame((_, delta) => {
53+
// cooldownRef.current += delta; // Increment by elapsed time since last frame
54+
// if (cooldownRef.current >= 1) { // 1-second cooldown
55+
// sendMessage({ type: "dial_vvr_1_angle", payload: { get: true } });
56+
// cooldownRef.current = 0; // Reset cooldown accumulator
57+
// }
58+
// });
59+
60+
3961
return (
4062
<group ref={groupRef} position={position} rotation={rotation} scale={scale}>
4163
{model && <primitive object={model} />}
42-
<OvenKnob rotation={[0, Math.PI / 2.7, 0]} position={[5, 20.5, -7]} unique_id="oven_knob_1" scale={[0.9, 0.9, 0.9]}/>
64+
<OvenKnob rotation={[0, 0, 0]} position={[5, 20.5, -7]} unique_id="oven_knob_1" scale={[0.9, 0.9, 0.9]}/>
4365
</group>
4466
)
4567
}

src/labComponents/FrankHertzMainComp/digitalVoltmeter.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const FrankHertzMain: React.FC<FrankHertzMainProps> = ({
1717
unique_id,
1818
scale = [0.5, 0.5, 0.5],
1919
}) => {
20-
const gltf = useLoader(GLTFLoader, "/dcv/dcv4.glb")
20+
const gltf = useLoader(GLTFLoader, "/dcv/dcv23.glb")
2121
const [model, setModel] = useState<THREE.Object3D | null>(null)
2222
const groupRef = useRef<THREE.Group | null>(null)
2323

src/labComponents/FrankHertzMainComp/frankHertz.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const FrankHertzMain: React.FC<FrankHertzMainProps> = ({
4141
return (
4242
<group ref={groupRef} position={position} rotation={rotation} scale={scale}>
4343
{model && <primitive object={model} scale={[0.65, 0.65, 0.65]} />}
44-
<CircularTherm position={[2, 53.5, -15]} />
44+
<CircularTherm position={[4, 49.2, -13.5]} />
4545
</group>
4646
)
4747
}

src/labComponents/FrankHertzMainComp/tripleOutPutPowerSupply/mainComponent.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useLoader } from "@react-three/fiber"
44
import { useState, useEffect } from "react"
55
import { GLTFLoader } from "three-stdlib"
66
import LightSwitch from "../../../clickables/VVR_switch/switchAndCasing"
7+
import RadioDial from "../../SmallInstruments/circularTherm/radioDial"
78

89
interface TripleOutputProps {
910
position: [number, number, number] // Position prop
@@ -42,6 +43,8 @@ const TripleOutput: React.FC<TripleOutputProps> = ({
4243
{model && <primitive object={model} scale={[1.25, 1.25, 1.25]} />}{" "}
4344
<LightSwitch position={[20, 17, 0.6]} unique_id = "triple_output_switch1" />
4445
<LightSwitch position={[-22, 17, 0.6]} unique_id = "triple_output_switch2" />
46+
<RadioDial position={[11.69, 11.5, 0.01]} unique_id="tops_dial2" scale={[0.3, 0.3, 0.42]} rotation={[Math.PI / 2, 0.75, 0]}/>
47+
<RadioDial position={[-11.46, 11.5, 0.01]} unique_id="tops_dial1" scale={[0.3, 0.3, 0.42]} rotation={[Math.PI / 2, 0.75, 0]}/>
4548
</group>
4649
)
4750
}

0 commit comments

Comments
 (0)