• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atomic14 / web-serial-plotter / 18927554430

30 Oct 2025 02:04AM UTC coverage: 60.213% (-1.0%) from 61.184%
18927554430

Pull #22

github

web-flow
Merge 6f890ce49 into ae73642b7
Pull Request #22: Feature: Add COBS-encoded float32 support

421 of 537 branches covered (78.4%)

Branch coverage included in aggregate %.

18 of 128 new or added lines in 4 files covered. (14.06%)

1 existing line in 1 file now uncovered.

2064 of 3590 relevant lines covered (57.49%)

33.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.2
/src/hooks/useDataConnection.ts
1
import { useCallback, useState, useEffect } from 'react'
1✔
2
import { useSerial } from './useSerial'
1✔
3
import { useSignalGenerator, type GeneratorConfig } from './useSignalGenerator'
1✔
4

5
export interface SerialConfig {
6
  baudRate: number
7
  dataBits: 5 | 6 | 7 | 8
8
  stopBits: 1 | 2
9
  parity: 'none' | 'even' | 'odd'
10
  flowControl: 'none' | 'hardware'
11
  encoding: 'ascii' | 'cobs-f32'
12
}
13

14
export type ConnectionType = 'serial' | 'generator'
15

16
export interface ConnectionState {
17
  type: ConnectionType | null
18
  isConnecting: boolean
19
  isConnected: boolean
20
  isSupported: boolean
21
  error: string | null
22
}
23

24
export interface UseDataConnection {
25
  state: ConnectionState
26
  connectSerial: (config: SerialConfig) => Promise<void>
27
  connectGenerator: (config: GeneratorConfig) => Promise<void>
28
  disconnect: () => Promise<void>
29
  write: (data: string) => Promise<void>
30
  generatorConfig: GeneratorConfig
31
  setGeneratorConfig: (config: Partial<GeneratorConfig>) => void
32
}
33

34
const DEFAULT_SERIAL_CONFIG: SerialConfig = {
1✔
35
  baudRate: 115200,
1✔
36
  dataBits: 8,
1✔
37
  stopBits: 1,
1✔
38
  parity: 'none',
1✔
39
  flowControl: 'none',
1✔
40
  encoding: 'ascii'
1✔
41
}
1✔
42

43
export function useDataConnection(onLine: (line: string) => void): UseDataConnection {
1✔
44
  const [connectionType, setConnectionType] = useState<ConnectionType | null>(null)
6✔
45
  const [isConnecting, setIsConnecting] = useState(false)
6✔
46
  const [error, setError] = useState<string | null>(null)
6✔
47

48

49
  const serial = useSerial()
6✔
50
  const generator = useSignalGenerator(onLine)
6✔
51

52
  const state: ConnectionState = {
6✔
53
    type: connectionType,
6✔
54
    isConnecting: isConnecting || serial.state.isConnecting,
6✔
55
    isConnected: serial.state.isConnected || generator.isRunning,
6✔
56
    isSupported: serial.state.isSupported,
6✔
57
    error: error || serial.state.error
6✔
58
  }
6✔
59

60

61
  const connectSerial = useCallback(async (config: SerialConfig) => {
6✔
62
    if (generator.isRunning) {
2!
63
      generator.stop()
×
64
    }
×
65
    
66
    setIsConnecting(true)
2✔
67
    setError(null)
2✔
68
    
69
    try {
2✔
70
      // Note: Web Serial API has limited configuration options
71
      await serial.connect(config);
2✔
72
      setConnectionType('serial')
2✔
73
      // The actual port configuration would need to be done at the port.open() level
74
    } catch (err) {
2!
UNCOV
75
      const message = err instanceof Error ? err.message : 'Failed to connect to serial port'
×
76
      setError(message)
×
77
      setConnectionType(null)
×
78
      throw err // Re-throw so ConnectModal knows the connection failed
×
79
    } finally {
2✔
80
      setIsConnecting(false)
2✔
81
    }
2✔
82
  }, [serial, generator])
6✔
83

84
  const connectGenerator = useCallback(async (config: GeneratorConfig) => {
6✔
85
    if (serial.state.isConnected) {
1!
86
      await serial.disconnect()
×
87
    }
×
88
    
89
    setError(null)
1✔
90
    setConnectionType('generator')
1✔
91
    
92
    try {
1✔
93
      generator.setConfig(config)
1✔
94
      generator.start()
1✔
95
    } catch (err) {
1!
96
      const message = err instanceof Error ? err.message : 'Failed to start signal generator'
×
97
      setError(message)
×
98
      setConnectionType(null)
×
99
    }
×
100
  }, [serial, generator])
6✔
101

102
  const disconnect = useCallback(async () => {
6✔
103
    setError(null)
1✔
104
    
105
    if (serial.state.isConnected) {
1!
106
      await serial.disconnect()
×
107
    }
×
108
    
109
    if (generator.isRunning) {
1!
110
      generator.stop()
×
111
    }
×
112
    
113
    setConnectionType(null)
1✔
114
  }, [serial, generator])
6✔
115

116
  // Set up serial line handler
117
  useEffect(() => {
6✔
118
    serial.onLine(onLine)
6✔
119
  }, [serial, onLine])
6✔
120

121
  const write = useCallback(async (data: string) => {
6✔
122
    if (connectionType !== 'serial' || !serial.state.isConnected) {
×
123
      throw new Error('Serial port not connected')
×
124
    }
×
125
    await serial.write(data)
×
126
  }, [connectionType, serial])
6✔
127

128
  return {
6✔
129
    state,
6✔
130
    connectSerial,
6✔
131
    connectGenerator,
6✔
132
    disconnect,
6✔
133
    write,
6✔
134
    generatorConfig: generator.config,
6✔
135
    setGeneratorConfig: generator.setConfig
6✔
136
  }
6✔
137
}
6✔
138

139
export { DEFAULT_SERIAL_CONFIG }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc