Skip to content

Commit bc5f558

Browse files
authored
Merge pull request #71 from UBCMint/frontend/websocket-fix
Fix websocket connection
2 parents 4b39361 + 0b26b66 commit bc5f558

File tree

3 files changed

+59
-82
lines changed

3 files changed

+59
-82
lines changed

frontend/components/nodes/filter-node/combo-box.tsx

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,15 @@ interface ComboBoxProps {
3232
export default function ComboBox({
3333
value = 'lowpass',
3434
onValueChange,
35+
lowCutoff,
36+
highCutoff,
37+
setLowCutoff,
38+
setHighCutoff,
3539
isConnected = false,
3640
isDataStreamOn = false,
3741
}: ComboBoxProps) {
3842
const [isExpanded, setIsExpanded] = React.useState(false);
3943
const titleRef = React.useRef<HTMLSpanElement>(null);
40-
const [sliderValue, setSliderValue] = React.useState([75]);
41-
const [cutoff, setCutoff] = React.useState([75]);
42-
43-
const [lowCutoff, setLowCutoff] = React.useState([25]);
44-
const [highCutoff, setHighCutoff] = React.useState([75]);
4544

4645
const toggleExpanded = () => {
4746
setIsExpanded(!isExpanded);
@@ -140,21 +139,17 @@ export default function ComboBox({
140139
paddingRight: '60px',
141140
}}
142141
>
143-
{value != 'bandpass' && (
142+
{value !== 'bandpass' && (
144143
<div>
145144
<Slider
146-
value={sliderValue}
145+
value={value === 'lowpass' ? [highCutoff] : [lowCutoff]}
147146
onValueChange={(val) => {
148-
setSliderValue(val);
149-
150147
if (value === 'lowpass') {
151-
setHighCutoff(val);
152-
}
153-
154-
if (value === 'highpass') {
155-
setLowCutoff(val);
148+
setHighCutoff(val[0]);
149+
} else {
150+
setLowCutoff(val[0]);
156151
}
157-
}}
152+
}}
158153
max={100}
159154
min={0}
160155
step={1}
@@ -167,54 +162,36 @@ export default function ComboBox({
167162
</div>
168163
)}
169164

170-
{/* Single slider for lowpass and highpass */}
171-
{value == 'bandpass' && (
165+
{value === 'bandpass' && (
172166
<div>
173167
{/* Low cutoff */}
174-
<div>
175-
176-
<Slider
177-
value={lowCutoff}
178-
onValueChange={(val) => {
179-
// prevent low from going above high
180-
const next =
181-
val[0] >= highCutoff[0]
182-
? highCutoff[0] - 1
183-
: val[0];
184-
setLowCutoff([next]);
185-
}}
186-
min={0}
187-
max={100}
188-
step={1}
189-
className="w-full mb-1"
190-
/>
191-
</div>
192-
168+
<Slider
169+
value={[lowCutoff]}
170+
onValueChange={(val) => {
171+
setLowCutoff(Math.min(val[0], highCutoff - 1));
172+
}}
173+
min={0}
174+
max={100}
175+
step={1}
176+
className="w-full mb-1"
177+
/>
193178
<div className="flex justify-between items-center mb-5">
194179
<span className="text-xs text-gray-500">0</span>
195180
<span className="text-xs text-gray-500">Low Cutoff</span>
196181
<span className="text-xs text-gray-500">100</span>
197182
</div>
198183

199184
{/* High cutoff */}
200-
<div>
201-
<Slider
202-
value={highCutoff}
203-
onValueChange={(val) => {
204-
// prevent high from going below low
205-
const next =
206-
val[0] <= lowCutoff[0]
207-
? lowCutoff[0] + 1
208-
: val[0];
209-
setHighCutoff([next]);
210-
}}
211-
min={0}
212-
max={100}
213-
step={1}
214-
className="w-full mb-1"
215-
/>
216-
</div>
217-
185+
<Slider
186+
value={[highCutoff]}
187+
onValueChange={(val) => {
188+
setHighCutoff(Math.max(val[0], lowCutoff + 1));
189+
}}
190+
min={0}
191+
max={100}
192+
step={1}
193+
className="w-full mb-1"
194+
/>
218195
<div className="flex justify-between items-center mb-1">
219196
<span className="text-xs text-gray-500">0</span>
220197
<span className="text-xs text-gray-500">High Cutoff</span>

frontend/components/nodes/filter-node/filter-node.tsx

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React from 'react';
33
import { Handle, Position, useReactFlow } from '@xyflow/react';
44
import { useGlobalContext } from '@/context/GlobalContext';
55
import ComboBox from './combo-box';
6-
import useWebsocket from '@/hooks/useWebsocket';
76
import { ProcessingConfig } from '@/lib/processing';
87

98
interface FilterNodeProps {
@@ -23,8 +22,6 @@ export default function FilterNode({ id }: FilterNodeProps) {
2322
// Get data stream status from global context
2423
const { dataStreaming } = useGlobalContext();
2524

26-
const { sendProcessingConfig } = useWebsocket(0, 0)
27-
2825
const buildConfig = (): ProcessingConfig => {
2926
if (!isConnected) {
3027
return {
@@ -138,9 +135,13 @@ export default function FilterNode({ id }: FilterNodeProps) {
138135
}, [checkConnectionStatus]);
139136

140137
React.useEffect(() => {
141-
if (!dataStreaming) return
142-
sendProcessingConfig(buildConfig())
143-
}, [selectedFilter, lowCutoff, highCutoff, isConnected, dataStreaming])
138+
if (!dataStreaming) return;
139+
window.dispatchEvent(
140+
new CustomEvent<ProcessingConfig>('processing-config-update', {
141+
detail: buildConfig(),
142+
})
143+
);
144+
}, [selectedFilter, lowCutoff, highCutoff, isConnected, dataStreaming]);
144145

145146
return (
146147
<div className="relative">
@@ -196,23 +197,6 @@ export default function FilterNode({ id }: FilterNodeProps) {
196197
isDataStreamOn={dataStreaming}
197198
/>
198199

199-
{isConnected && (
200-
<>
201-
<input
202-
type="range"
203-
min={1}
204-
max={100}
205-
value={cutoff}
206-
onChange={(e) => setCutoff(Number(e.target.value))}
207-
/>
208-
209-
<p className="text-xs text-muted-foreground">
210-
{selectedFilter === 'lowpass'
211-
? 'Frequencies below cutoff will pass through'
212-
: 'Frequencies above cutoff will pass through'}
213-
</p>
214-
</>
215-
)}
216200
</div>
217201
);
218202
}

frontend/hooks/useWebsocket.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ import { useEffect, useState, useRef } from 'react';
22
import { useGlobalContext } from '@/context/GlobalContext';
33
import { ProcessingConfig } from '@/lib/processing';
44

5+
const DEFAULT_PROCESSING_CONFIG: ProcessingConfig = {
6+
apply_bandpass: false,
7+
use_iir: false,
8+
l_freq: null,
9+
h_freq: null,
10+
downsample_factor: null,
11+
sfreq: 256,
12+
n_channels: 4,
13+
};
14+
515
export default function useWebsocket(
616
chartSize: number,
717
batchesPerSecond: number
@@ -23,7 +33,16 @@ export default function useWebsocket(
2333
wsRef.current.send(JSON.stringify(config))
2434
console.log('Sent processing config:', config)
2535
}
26-
}
36+
}
37+
38+
useEffect(() => {
39+
const handleConfigUpdate = (event: Event) => {
40+
sendProcessingConfig((event as CustomEvent<ProcessingConfig>).detail);
41+
};
42+
window.addEventListener('processing-config-update', handleConfigUpdate);
43+
return () => window.removeEventListener('processing-config-update', handleConfigUpdate);
44+
}, []);
45+
2746
const normalizeBatch = (batch: any) => {
2847
return batch.timestamps.map((time: number, i: number) => ({
2948
time,
@@ -65,10 +84,7 @@ export default function useWebsocket(
6584

6685
ws.onopen = () => {
6786
console.log('WebSocket connection opened.');
68-
69-
if (processingConfigRef.current) {
70-
ws.send(JSON.stringify(processingConfigRef.current))
71-
}
87+
ws.send(JSON.stringify(processingConfigRef.current ?? DEFAULT_PROCESSING_CONFIG));
7288
};
7389

7490
ws.onmessage = (event) => {

0 commit comments

Comments
 (0)