docs: enhance hardware protocol documentation and reorganize project docs
- Complete hardware communication protocol documentation with: * Add ping/pong health check protocol (0x01) * Add hardware control protocols (0x03 brightness, 0x04 volume) * Add mDNS service discovery specifications * Add connection state management and retry logic * Add comprehensive troubleshooting guide * Update hardware implementation examples - Reorganize project documentation: * Move device auto-refresh docs from root to docs/ directory * Rename files to follow kebab-case convention * Maintain complete technical implementation details - Fix markdown formatting issues: * Add proper language tags to code blocks * Ensure consistent documentation structure
This commit is contained in:
99
docs/device-auto-refresh-implementation.md
Normal file
99
docs/device-auto-refresh-implementation.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# LED Strip Test Device Auto-Refresh Implementation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Implemented automatic refresh functionality for the device dropdown in the LED strip test interface. The device list now updates in real-time when devices are discovered, connected, or disconnected.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### 1. Frontend Changes (`src/components/led-strip-test/led-strip-test.tsx`)
|
||||||
|
|
||||||
|
#### Added Event Listener Import
|
||||||
|
```typescript
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Enhanced Device Loading Logic
|
||||||
|
- **Initial Load**: Still loads devices on component mount using `get_boards()`
|
||||||
|
- **Real-time Updates**: Added listener for `boards_changed` events from backend
|
||||||
|
- **Smart Selection**: Automatically handles device selection when devices are added/removed:
|
||||||
|
- If current device disconnects, automatically selects first available device
|
||||||
|
- If no device was selected and devices become available, selects the first one
|
||||||
|
- Properly cleans up event listeners on component unmount
|
||||||
|
|
||||||
|
#### Improved UI Display
|
||||||
|
- **Device Count**: Shows number of devices found in label
|
||||||
|
- **Connection Status**: Each device option shows:
|
||||||
|
- Status icon (🟢 Connected, 🟡 Connecting, 🔴 Disconnected)
|
||||||
|
- Device name and address
|
||||||
|
- Connection status text
|
||||||
|
- **Empty State**: Shows "Searching..." when no devices found
|
||||||
|
|
||||||
|
#### Type Safety Improvements
|
||||||
|
- Updated `BoardInfo` interface to match backend types
|
||||||
|
- Proper handling of `connect_status` union type
|
||||||
|
- Type-safe status checking functions
|
||||||
|
|
||||||
|
### 2. Backend Integration
|
||||||
|
The implementation leverages existing backend infrastructure:
|
||||||
|
- **UdpRpc Manager**: Continuously searches for devices via mDNS
|
||||||
|
- **Device Monitoring**: Checks device connectivity every second
|
||||||
|
- **Event Broadcasting**: Sends `boards_changed` events to frontend
|
||||||
|
- **Status Tracking**: Maintains real-time connection status for each device
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Event Flow
|
||||||
|
1. Backend `UdpRpc` discovers devices via mDNS service discovery
|
||||||
|
2. Backend monitors device connectivity with periodic health checks
|
||||||
|
3. Backend broadcasts `boards_changed` events when device list changes
|
||||||
|
4. Frontend listens for events and updates UI automatically
|
||||||
|
5. Frontend handles device selection logic intelligently
|
||||||
|
|
||||||
|
### Connection Status Types
|
||||||
|
- `Connected`: Device is responding to ping requests
|
||||||
|
- `Connecting`: Device is in retry state (with retry count)
|
||||||
|
- `Disconnected`: Device is not responding
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- Graceful fallback if initial device load fails
|
||||||
|
- Proper cleanup of event listeners
|
||||||
|
- Maintains UI state consistency during device changes
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
1. **Real-time Updates**: No need to manually refresh device list
|
||||||
|
2. **Better UX**: Visual indicators for device status
|
||||||
|
3. **Automatic Recovery**: Handles device disconnections gracefully
|
||||||
|
4. **Type Safety**: Proper TypeScript types prevent runtime errors
|
||||||
|
5. **Performance**: Efficient event-driven updates instead of polling
|
||||||
|
|
||||||
|
## Implementation Status
|
||||||
|
✅ **Completed**: LED Strip Test device dropdown auto-refresh
|
||||||
|
✅ **Already Implemented**: Board Index page auto-refresh (was already working)
|
||||||
|
✅ **Type Safety**: Fixed TypeScript type definitions for BoardInfo
|
||||||
|
✅ **UI Improvements**: Added status indicators and device count display
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
To test the functionality:
|
||||||
|
1. Start the application with `npm run tauri dev`
|
||||||
|
2. Navigate to LED Strip Test page
|
||||||
|
3. Observe device list updates as devices come online/offline
|
||||||
|
4. Verify status indicators show correct connection states:
|
||||||
|
- 🟢 Connected devices
|
||||||
|
- 🟡 Connecting devices (with retry count)
|
||||||
|
- 🔴 Disconnected devices
|
||||||
|
5. Test device selection behavior when devices disconnect
|
||||||
|
6. Check that device count is displayed in the label
|
||||||
|
|
||||||
|
## Code Quality
|
||||||
|
- ✅ No TypeScript errors
|
||||||
|
- ✅ Proper event listener cleanup
|
||||||
|
- ✅ Type-safe status checking
|
||||||
|
- ✅ Consistent with existing codebase patterns
|
||||||
|
- ✅ Follows SolidJS best practices
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
- Add device refresh button for manual refresh
|
||||||
|
- Show device discovery progress indicator
|
||||||
|
- Add device connection retry controls
|
||||||
|
- Display device ping latency information
|
||||||
|
- Add device connection history/logs
|
105
docs/device-auto-refresh-testing.md
Normal file
105
docs/device-auto-refresh-testing.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# Device Auto-Refresh Testing Guide
|
||||||
|
|
||||||
|
## Test Scenarios
|
||||||
|
|
||||||
|
### 1. Initial Load Test
|
||||||
|
**Expected Behavior**: Device list loads automatically when component mounts
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Start the application: `npm run tauri dev`
|
||||||
|
2. Navigate to LED Strip Test page
|
||||||
|
3. Observe the device dropdown
|
||||||
|
|
||||||
|
**Expected Results**:
|
||||||
|
- Device dropdown shows "Searching..." if no devices found
|
||||||
|
- Device dropdown shows device count if devices are found
|
||||||
|
- First available device is automatically selected
|
||||||
|
- Status icons appear next to device names
|
||||||
|
|
||||||
|
### 2. Device Discovery Test
|
||||||
|
**Expected Behavior**: New devices appear automatically when discovered
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Start with no devices connected
|
||||||
|
2. Connect a device to the network
|
||||||
|
3. Wait for device discovery (should be automatic)
|
||||||
|
|
||||||
|
**Expected Results**:
|
||||||
|
- Device count updates automatically
|
||||||
|
- New device appears in dropdown
|
||||||
|
- If no device was selected, new device gets selected automatically
|
||||||
|
- Status icon shows connection state
|
||||||
|
|
||||||
|
### 3. Device Disconnection Test
|
||||||
|
**Expected Behavior**: Disconnected devices are handled gracefully
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Start with connected devices
|
||||||
|
2. Select a device in the dropdown
|
||||||
|
3. Disconnect the selected device from network
|
||||||
|
4. Wait for connection timeout
|
||||||
|
|
||||||
|
**Expected Results**:
|
||||||
|
- Device status changes to disconnected (🔴)
|
||||||
|
- If device becomes unavailable, another device is selected automatically
|
||||||
|
- Device count updates
|
||||||
|
- UI remains responsive
|
||||||
|
|
||||||
|
### 4. Connection Status Test
|
||||||
|
**Expected Behavior**: Status indicators reflect actual device states
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Observe devices in different connection states
|
||||||
|
2. Check status icons and text
|
||||||
|
|
||||||
|
**Expected Results**:
|
||||||
|
- 🟢 "Connected" for responsive devices
|
||||||
|
- 🟡 "Connecting" for devices in retry state
|
||||||
|
- 🔴 "Disconnected" for unresponsive devices
|
||||||
|
- Status text matches icon state
|
||||||
|
|
||||||
|
### 5. UI Responsiveness Test
|
||||||
|
**Expected Behavior**: Interface remains responsive during device changes
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Rapidly connect/disconnect devices
|
||||||
|
2. Interact with other UI elements during device changes
|
||||||
|
3. Switch between pages and return
|
||||||
|
|
||||||
|
**Expected Results**:
|
||||||
|
- No UI freezing or lag
|
||||||
|
- Event listeners are properly cleaned up
|
||||||
|
- No memory leaks
|
||||||
|
- Smooth transitions
|
||||||
|
|
||||||
|
## Verification Checklist
|
||||||
|
|
||||||
|
- [ ] Device dropdown shows correct device count
|
||||||
|
- [ ] Status icons display correctly (🟢🟡🔴)
|
||||||
|
- [ ] Automatic device selection works
|
||||||
|
- [ ] Event listeners are cleaned up on component unmount
|
||||||
|
- [ ] No TypeScript errors in console
|
||||||
|
- [ ] No runtime errors in console
|
||||||
|
- [ ] Performance remains good with multiple devices
|
||||||
|
- [ ] UI updates smoothly without flickering
|
||||||
|
|
||||||
|
## Common Issues to Watch For
|
||||||
|
|
||||||
|
1. **Memory Leaks**: Event listeners not cleaned up
|
||||||
|
2. **Type Errors**: Incorrect BoardInfo type handling
|
||||||
|
3. **Selection Logic**: Device selection not updating correctly
|
||||||
|
4. **Performance**: UI lag during rapid device changes
|
||||||
|
5. **State Consistency**: UI state not matching actual device state
|
||||||
|
|
||||||
|
## Debug Information
|
||||||
|
|
||||||
|
Check browser console for:
|
||||||
|
- `boards_changed` events
|
||||||
|
- Device list updates
|
||||||
|
- Selection changes
|
||||||
|
- Any error messages
|
||||||
|
|
||||||
|
Check Tauri logs for:
|
||||||
|
- Device discovery messages
|
||||||
|
- Connection status changes
|
||||||
|
- mDNS service events
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
UDP-based protocol for sending LED color data from desktop application to ambient light hardware boards. The hardware acts as a simple UDP-to-WS2812 bridge, directly forwarding color data without any processing or LED type distinction.
|
UDP-based bidirectional protocol for communication between desktop application and ambient light hardware boards. The protocol supports LED color data transmission, device health monitoring, and remote control capabilities.
|
||||||
|
|
||||||
## Connection
|
## Connection
|
||||||
|
|
||||||
@ -11,12 +11,61 @@ UDP-based protocol for sending LED color data from desktop application to ambien
|
|||||||
- **Discovery**: mDNS (`_ambient_light._udp.local.`)
|
- **Discovery**: mDNS (`_ambient_light._udp.local.`)
|
||||||
- **Example Board**: `192.168.31.206:23042`
|
- **Example Board**: `192.168.31.206:23042`
|
||||||
|
|
||||||
## Packet Format
|
## mDNS Service Discovery
|
||||||
|
|
||||||
|
### Service Registration (Hardware Side)
|
||||||
|
|
||||||
|
Hardware boards must register the following mDNS service:
|
||||||
|
|
||||||
|
- **Service Type**: `_ambient_light._udp.local.`
|
||||||
|
- **Port**: 23042
|
||||||
|
- **TXT Records**: Optional, can include device information
|
||||||
|
|
||||||
|
### Service Discovery (Desktop Side)
|
||||||
|
|
||||||
|
Desktop application continuously browses for `_ambient_light._udp.local.` services and automatically connects to discovered devices.
|
||||||
|
|
||||||
|
## Protocol Messages
|
||||||
|
|
||||||
|
The protocol uses different message headers to distinguish message types:
|
||||||
|
|
||||||
|
| Header | Direction | Purpose | Format |
|
||||||
|
|--------|-----------|---------|---------|
|
||||||
|
| 0x01 | Desktop → Hardware | Ping (Health Check) | `[0x01]` |
|
||||||
|
| 0x01 | Hardware → Desktop | Pong (Health Response) | `[0x01]` |
|
||||||
|
| 0x02 | Desktop → Hardware | LED Color Data | `[0x02][Offset_H][Offset_L][Color_Data...]` |
|
||||||
|
| 0x03 | Hardware → Desktop | Display Brightness Control | `[0x03][Display_Index][Brightness]` |
|
||||||
|
| 0x04 | Hardware → Desktop | Volume Control | `[0x04][Volume_Percent]` |
|
||||||
|
|
||||||
|
## Health Check Protocol (Ping/Pong)
|
||||||
|
|
||||||
|
### Desktop → Hardware (Ping)
|
||||||
|
|
||||||
|
```text
|
||||||
|
Byte 0: Header (0x01)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Hardware → Desktop (Pong)
|
||||||
|
|
||||||
|
```text
|
||||||
|
Byte 0: Header (0x01)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Behavior:**
|
||||||
|
|
||||||
|
- Desktop sends ping every 1 second to each connected device
|
||||||
|
- Hardware must respond with pong within 1 second
|
||||||
|
- Timeout or incorrect response triggers reconnection logic
|
||||||
|
- After 10 failed attempts, device is marked as disconnected
|
||||||
|
|
||||||
|
## LED Color Data Protocol
|
||||||
|
|
||||||
|
### Packet Format
|
||||||
|
|
||||||
|
```text
|
||||||
Byte 0: Header (0x02)
|
Byte 0: Header (0x02)
|
||||||
Byte 1: Offset High (upper 8 bits of LED start position)
|
Byte 1: Offset High (upper 8 bits of LED start position)
|
||||||
Byte 2: Offset Low (lower 8 bits of LED start position)
|
Byte 2: Offset Low (lower 8 bits of LED start position)
|
||||||
Byte 3+: LED Color Data (variable length)
|
Byte 3+: LED Color Data (variable length)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -24,13 +73,13 @@ Byte 3+: LED Color Data (variable length)
|
|||||||
|
|
||||||
### RGB LEDs (3 bytes per LED)
|
### RGB LEDs (3 bytes per LED)
|
||||||
|
|
||||||
```
|
```text
|
||||||
[R][G][B][R][G][B][R][G][B]...
|
[R][G][B][R][G][B][R][G][B]...
|
||||||
```
|
```
|
||||||
|
|
||||||
### RGBW LEDs (4 bytes per LED)
|
### RGBW LEDs (4 bytes per LED)
|
||||||
|
|
||||||
```
|
```text
|
||||||
[R][G][B][W][R][G][B][W][R][G][B][W]...
|
[R][G][B][W][R][G][B][W][R][G][B][W]...
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -57,13 +106,78 @@ calibrated_b = (original_b * calibration_b) / 255
|
|||||||
calibrated_w = calibration_w // Direct value
|
calibrated_w = calibration_w // Direct value
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Hardware Control Protocol (Hardware → Desktop)
|
||||||
|
|
||||||
|
### Display Brightness Control
|
||||||
|
|
||||||
|
Hardware can send display brightness adjustment commands to the desktop:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Byte 0: Header (0x03)
|
||||||
|
Byte 1: Display Index (0-based display number)
|
||||||
|
Byte 2: Brightness (0-255, where 255 = 100% brightness)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:** Set display 0 to 50% brightness
|
||||||
|
|
||||||
|
```text
|
||||||
|
03 00 80
|
||||||
|
│ │ └─ Brightness (128 = ~50%)
|
||||||
|
│ └─ Display Index (0)
|
||||||
|
└─ Header (0x03)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Volume Control
|
||||||
|
|
||||||
|
Hardware can send system volume adjustment commands to the desktop:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Byte 0: Header (0x04)
|
||||||
|
Byte 1: Volume Percent (0-100)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:** Set system volume to 75%
|
||||||
|
|
||||||
|
```text
|
||||||
|
04 4B
|
||||||
|
│ └─ Volume (75%)
|
||||||
|
└─ Header (0x04)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connection State Management
|
||||||
|
|
||||||
|
### Connection States
|
||||||
|
|
||||||
|
- **Unknown**: Initial state when device is first discovered
|
||||||
|
- **Connecting**: Device is being tested, includes retry count (1-10)
|
||||||
|
- **Connected**: Device is responding to ping requests normally
|
||||||
|
- **Disconnected**: Device failed to respond after 10 retry attempts
|
||||||
|
|
||||||
|
### State Transitions
|
||||||
|
|
||||||
|
```text
|
||||||
|
Unknown → Connecting(1) → Connected
|
||||||
|
↓ ↓ ↓
|
||||||
|
↓ Connecting(2-10) ↓
|
||||||
|
↓ ↓ ↓
|
||||||
|
└─→ Disconnected ←────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Retry Logic
|
||||||
|
|
||||||
|
1. **Initial Connection**: When device discovered via mDNS
|
||||||
|
2. **Health Check Failure**: If ping timeout or wrong response
|
||||||
|
3. **Retry Attempts**: Up to 10 attempts with 1-second intervals
|
||||||
|
4. **Disconnection**: After 10 failed attempts, mark as disconnected
|
||||||
|
5. **Recovery**: Disconnected devices continue to receive ping attempts
|
||||||
|
|
||||||
## Packet Examples
|
## Packet Examples
|
||||||
|
|
||||||
### RGB Example
|
### RGB Example
|
||||||
|
|
||||||
3 RGB LEDs starting at position 0: Red, Green, Blue
|
3 RGB LEDs starting at position 0: Red, Green, Blue
|
||||||
|
|
||||||
```
|
```text
|
||||||
02 00 00 FF 00 00 00 FF 00 00 00 FF
|
02 00 00 FF 00 00 00 FF 00 00 00 FF
|
||||||
│ │ │ └─────────────────────────── 9 bytes color data
|
│ │ │ └─────────────────────────── 9 bytes color data
|
||||||
│ │ └─ Offset Low (0)
|
│ │ └─ Offset Low (0)
|
||||||
@ -71,11 +185,11 @@ calibrated_w = calibration_w // Direct value
|
|||||||
└─ Header (0x02)
|
└─ Header (0x02)
|
||||||
```
|
```
|
||||||
|
|
||||||
### RGBW Example
|
### RGBW Example
|
||||||
|
|
||||||
2 RGBW LEDs starting at position 10: White, Warm White
|
2 RGBW LEDs starting at position 10: White, Warm White
|
||||||
|
|
||||||
```
|
```text
|
||||||
02 00 0A FF FF FF FF FF C8 96 C8
|
02 00 0A FF FF FF FF FF C8 96 C8
|
||||||
│ │ │ └─────────────────────── 8 bytes color data
|
│ │ │ └─────────────────────── 8 bytes color data
|
||||||
│ │ └─ Offset Low (10)
|
│ │ └─ Offset Low (10)
|
||||||
@ -94,20 +208,48 @@ calibrated_w = calibration_w // Direct value
|
|||||||
|
|
||||||
## Hardware Implementation
|
## Hardware Implementation
|
||||||
|
|
||||||
The hardware board acts as a simple UDP-to-WS2812 bridge, directly forwarding color data to the LED strips without any processing or type distinction.
|
The hardware board handles multiple protocol functions: UDP-to-WS2812 bridge for LED data, health monitoring, and optional control input capabilities.
|
||||||
|
|
||||||
### Packet Processing
|
### Required Functions
|
||||||
|
|
||||||
1. **Validation**: Check minimum 3 bytes and header (0x02)
|
1. **mDNS Service Registration**: Advertise `_ambient_light._udp.local.` service
|
||||||
2. **Extract Offset**: Parse 16-bit LED start position
|
2. **UDP Server**: Listen on port 23042 for incoming packets
|
||||||
3. **Forward Data**: Send color data directly to WS2812 controller
|
3. **Packet Processing**: Handle different message types based on header
|
||||||
4. **No Type Logic**: Hardware doesn't distinguish RGB/RGBW - just forwards bytes
|
4. **Health Monitoring**: Respond to ping requests with pong
|
||||||
|
5. **LED Control**: Forward color data to WS2812 strips
|
||||||
|
6. **Optional Control**: Send brightness/volume commands to desktop
|
||||||
|
|
||||||
### Example C Code
|
### Packet Processing Logic
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void process_packet(uint8_t* data, size_t len) {
|
void process_packet(uint8_t* data, size_t len) {
|
||||||
if (len < 3 || data[0] != 0x02) return;
|
if (len < 1) return;
|
||||||
|
|
||||||
|
switch (data[0]) {
|
||||||
|
case 0x01: // Ping request
|
||||||
|
handle_ping(data, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02: // LED color data
|
||||||
|
handle_led_data(data, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown packet type, ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_ping(uint8_t* data, size_t len) {
|
||||||
|
if (len != 1) return;
|
||||||
|
|
||||||
|
// Respond with pong
|
||||||
|
uint8_t pong = 0x01;
|
||||||
|
udp_send_response(&pong, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_led_data(uint8_t* data, size_t len) {
|
||||||
|
if (len < 3) return;
|
||||||
|
|
||||||
uint16_t offset = (data[1] << 8) | data[2];
|
uint16_t offset = (data[1] << 8) | data[2];
|
||||||
uint8_t* color_data = &data[3];
|
uint8_t* color_data = &data[3];
|
||||||
@ -118,23 +260,119 @@ void process_packet(uint8_t* data, size_t len) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key Simplifications
|
### Optional Control Features
|
||||||
|
|
||||||
- **No LED Type Detection**: Hardware doesn't need to know RGB vs RGBW
|
Hardware can optionally send control commands to desktop:
|
||||||
- **Direct Data Forward**: Color bytes sent as-is to WS2812 controller
|
|
||||||
- **Desktop Handles Logic**: All RGB/RGBW processing done on desktop side
|
```c
|
||||||
- **Simple Bridge**: Hardware is just a UDP-to-WS2812 data bridge
|
// Send display brightness control
|
||||||
|
void send_brightness_control(uint8_t display_index, uint8_t brightness) {
|
||||||
|
uint8_t packet[3] = {0x03, display_index, brightness};
|
||||||
|
udp_send_to_desktop(packet, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send volume control
|
||||||
|
void send_volume_control(uint8_t volume_percent) {
|
||||||
|
uint8_t packet[2] = {0x04, volume_percent};
|
||||||
|
udp_send_to_desktop(packet, 2);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Implementation Notes
|
||||||
|
|
||||||
|
- **Ping Response**: Must respond to ping (0x01) within 1 second
|
||||||
|
- **LED Data**: Direct forward to WS2812, no processing required
|
||||||
|
- **Control Commands**: Optional feature for hardware with input capabilities
|
||||||
|
- **mDNS Registration**: Essential for automatic device discovery
|
||||||
|
- **UDP Server**: Must handle concurrent connections from multiple desktops
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
**No Updates**: Check network connectivity, mDNS discovery, port 23042
|
### Device Discovery Issues
|
||||||
**Wrong Colors**: Verify calibration settings on desktop application
|
|
||||||
**Flickering**: Monitor packet rate, network congestion, power supply
|
**Device Not Found**:
|
||||||
**Partial Updates**: Check strip configuration, offset calculations
|
|
||||||
**Hardware Issues**: Verify WS2812 wiring, power supply, data signal integrity
|
- Verify mDNS service registration on hardware
|
||||||
|
- Check service type: `_ambient_light._udp.local.`
|
||||||
|
- Ensure port 23042 is accessible
|
||||||
|
- Verify network connectivity between desktop and hardware
|
||||||
|
|
||||||
|
**Device Shows as Disconnected**:
|
||||||
|
|
||||||
|
- Check ping/pong response implementation
|
||||||
|
- Verify hardware responds to 0x01 packets within 1 second
|
||||||
|
- Monitor network latency and packet loss
|
||||||
|
- Check UDP server implementation on hardware
|
||||||
|
|
||||||
|
### LED Control Issues
|
||||||
|
|
||||||
|
**No LED Updates**:
|
||||||
|
|
||||||
|
- Verify hardware processes 0x02 packets correctly
|
||||||
|
- Check WS2812 wiring and power supply
|
||||||
|
- Monitor packet reception on hardware side
|
||||||
|
- Verify offset calculations and LED strip configuration
|
||||||
|
|
||||||
|
**Wrong Colors**:
|
||||||
|
|
||||||
|
- Check color calibration settings on desktop
|
||||||
|
- Verify RGB/RGBW data format matches LED strip type
|
||||||
|
- Monitor color data in packets (bytes 3+)
|
||||||
|
- Check WS2812 color order (GRB vs RGB)
|
||||||
|
|
||||||
|
**Flickering or Lag**:
|
||||||
|
|
||||||
|
- Monitor packet rate and network congestion
|
||||||
|
- Check power supply stability for LED strips
|
||||||
|
- Verify WS2812 data signal integrity
|
||||||
|
- Consider reducing update frequency
|
||||||
|
|
||||||
|
### Control Protocol Issues
|
||||||
|
|
||||||
|
**Brightness/Volume Control Not Working**:
|
||||||
|
|
||||||
|
- Verify hardware sends correct packet format (0x03/0x04)
|
||||||
|
- Check desktop receives and processes control packets
|
||||||
|
- Monitor packet transmission from hardware
|
||||||
|
- Verify display index and value ranges
|
||||||
|
|
||||||
|
### Connection State Issues
|
||||||
|
|
||||||
|
**Frequent Disconnections**:
|
||||||
|
|
||||||
|
- Check network stability and latency
|
||||||
|
- Verify ping response timing (< 1 second)
|
||||||
|
- Monitor retry logic and connection state transitions
|
||||||
|
- Check for UDP packet loss
|
||||||
|
|
||||||
|
**Stuck in Connecting State**:
|
||||||
|
|
||||||
|
- Verify ping/pong packet format
|
||||||
|
- Check hardware UDP server implementation
|
||||||
|
- Monitor ping response timing
|
||||||
|
- Verify network firewall settings
|
||||||
|
|
||||||
|
### Network Debugging
|
||||||
|
|
||||||
|
**Packet Monitoring**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Monitor UDP traffic on port 23042
|
||||||
|
tcpdump -i any -X port 23042
|
||||||
|
|
||||||
|
# Check mDNS service discovery
|
||||||
|
dns-sd -B _ambient_light._udp.local.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hardware Debug Output**:
|
||||||
|
|
||||||
|
- Log received packet headers and lengths
|
||||||
|
- Monitor ping/pong timing
|
||||||
|
- Track LED data processing
|
||||||
|
- Log mDNS service registration status
|
||||||
|
|
||||||
## Protocol Version
|
## Protocol Version
|
||||||
|
|
||||||
- **Current**: 1.0
|
- **Current**: 1.0
|
||||||
- **Header**: 0x02
|
- **Headers**: 0x01 (Ping/Pong), 0x02 (LED Data), 0x03 (Brightness), 0x04 (Volume)
|
||||||
- **Future**: Different headers for backward compatibility
|
- **Future**: Additional headers for new features, backward compatibility maintained
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { createSignal, createEffect, For, Show, onCleanup } from 'solid-js';
|
import { createSignal, createEffect, For, Show, onCleanup } from 'solid-js';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
|
||||||
interface BoardInfo {
|
interface BoardInfo {
|
||||||
fullname: string;
|
fullname: string;
|
||||||
host: string;
|
host: string;
|
||||||
address: string;
|
address: string;
|
||||||
port: number;
|
port: number;
|
||||||
connect_status: string;
|
connect_status: 'Connected' | 'Disconnected' | { Connecting: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestPattern {
|
interface TestPattern {
|
||||||
@ -31,8 +32,9 @@ export const LedStripTest = () => {
|
|||||||
const [currentPattern, setCurrentPattern] = createSignal<TestPattern | null>(null);
|
const [currentPattern, setCurrentPattern] = createSignal<TestPattern | null>(null);
|
||||||
const [animationSpeed, setAnimationSpeed] = createSignal(33); // ~30fps
|
const [animationSpeed, setAnimationSpeed] = createSignal(33); // ~30fps
|
||||||
|
|
||||||
// Load available boards
|
// Load available boards and listen for changes
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
|
// Initial load
|
||||||
invoke<BoardInfo[]>('get_boards').then((boardList) => {
|
invoke<BoardInfo[]>('get_boards').then((boardList) => {
|
||||||
setBoards(boardList);
|
setBoards(boardList);
|
||||||
if (boardList.length > 0 && !selectedBoard()) {
|
if (boardList.length > 0 && !selectedBoard()) {
|
||||||
@ -41,6 +43,35 @@ export const LedStripTest = () => {
|
|||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('Failed to load boards:', error);
|
console.error('Failed to load boards:', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Listen for board changes
|
||||||
|
const unlisten = listen<BoardInfo[]>('boards_changed', (event) => {
|
||||||
|
const boardList = event.payload;
|
||||||
|
setBoards(boardList);
|
||||||
|
|
||||||
|
// If currently selected board is no longer available, select the first available one
|
||||||
|
const currentBoard = selectedBoard();
|
||||||
|
if (currentBoard) {
|
||||||
|
const stillExists = boardList.find(board =>
|
||||||
|
board.host === currentBoard.host &&
|
||||||
|
board.address === currentBoard.address &&
|
||||||
|
board.port === currentBoard.port
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!stillExists) {
|
||||||
|
// Current board is no longer available, select first available or null
|
||||||
|
setSelectedBoard(boardList.length > 0 ? boardList[0] : null);
|
||||||
|
}
|
||||||
|
} else if (boardList.length > 0) {
|
||||||
|
// No board was selected, select the first one
|
||||||
|
setSelectedBoard(boardList[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cleanup listener when effect is disposed
|
||||||
|
onCleanup(() => {
|
||||||
|
unlisten.then((unlistenFn) => unlistenFn());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cleanup when component is unmounted
|
// Cleanup when component is unmounted
|
||||||
@ -161,8 +192,11 @@ export const LedStripTest = () => {
|
|||||||
<div class="form-control w-full max-w-xs">
|
<div class="form-control w-full max-w-xs">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">Select Hardware Board</span>
|
<span class="label-text">Select Hardware Board</span>
|
||||||
|
<span class="label-text-alt">
|
||||||
|
{boards().length > 0 ? `${boards().length} device(s) found` : 'Searching...'}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
class="select select-bordered w-full max-w-xs"
|
class="select select-bordered w-full max-w-xs"
|
||||||
value={selectedBoard()?.host || ''}
|
value={selectedBoard()?.host || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -170,13 +204,29 @@ export const LedStripTest = () => {
|
|||||||
setSelectedBoard(board || null);
|
setSelectedBoard(board || null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option disabled value="">Choose a board</option>
|
<option disabled value="">
|
||||||
|
{boards().length > 0 ? 'Choose a board' : 'No boards found'}
|
||||||
|
</option>
|
||||||
<For each={boards()}>
|
<For each={boards()}>
|
||||||
{(board) => (
|
{(board) => {
|
||||||
<option value={board.host}>
|
const getStatusIcon = (status: BoardInfo['connect_status']) => {
|
||||||
{board.host} ({board.address}:{board.port})
|
if (status === 'Connected') return '🟢';
|
||||||
</option>
|
if (typeof status === 'object' && 'Connecting' in status) return '🟡';
|
||||||
)}
|
return '🔴';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusText = (status: BoardInfo['connect_status']) => {
|
||||||
|
if (status === 'Connected') return 'Connected';
|
||||||
|
if (typeof status === 'object' && 'Connecting' in status) return 'Connecting';
|
||||||
|
return 'Disconnected';
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<option value={board.host}>
|
||||||
|
{getStatusIcon(board.connect_status)} {board.host} ({board.address}:{board.port}) - {getStatusText(board.connect_status)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
}}
|
||||||
</For>
|
</For>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user