mirror of
https://github.com/seemueller-io/yachtpit.git
synced 2025-09-08 22:46:45 +00:00
Gpyes integration (#11)
* Introduce core modules: device management, bus communication, and discovery protocol. Adds system device interface, virtual hardware bus, and device discovery logic. Includes tests for all components. * improve map - Fix typos in variable and function names (`vessle` to `vessel`). - Add `update_vessel_data_with_gps` function to enable GPS integration for vessel data updates. - Integrate real GPS data into vessel systems and UI components (speed, heading, etc.). - Initialize speed gauge display at 0 kts. - Include `useEffect` in `MapNext` to log and potentially handle `vesselPosition` changes. **Add compass heading update system using GPS heading data.** - Remove `UserLocationMarker` component and related code from `MapNext.tsx` - Simplify logic for layer selection and navigation within `App.tsx` - Replace map style 'Bathymetry' with 'OSM' in layer options improve map * update image --------- Co-authored-by: geoffsee <>
This commit is contained in:
366
crates/hardware/README.md
Normal file
366
crates/hardware/README.md
Normal file
@@ -0,0 +1,366 @@
|
||||
# Virtual Hardware Abstraction Layer - Integration Guide
|
||||
|
||||
This document provides detailed instructions on how to integrate the virtual hardware abstraction layer into yachtpit systems.
|
||||
|
||||
## Overview
|
||||
|
||||
The virtual hardware abstraction layer consists of three main components:
|
||||
|
||||
1. **Hardware Bus** - Communication infrastructure for virtual devices
|
||||
2. **System Device** - Interface and base implementation for virtual hardware devices
|
||||
3. **Discovery Protocol** - Device discovery and capability advertisement
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Yachtpit Application │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Systems Crate │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ GPS System │ │Radar System │ │ AIS System │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Hardware Abstraction Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │Hardware Bus │ │System Device│ │Discovery │ │
|
||||
│ │ │ │Interface │ │Protocol │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Integration Steps
|
||||
|
||||
### Step 1: Add Hardware Dependency
|
||||
|
||||
Add the hardware crate as a dependency to the systems crate:
|
||||
|
||||
```toml
|
||||
# crates/systems/Cargo.toml
|
||||
[dependencies]
|
||||
hardware = { path = "../hardware" }
|
||||
```
|
||||
|
||||
### Step 2: Create Hardware-Aware System Implementations
|
||||
|
||||
Modify existing systems to implement the `SystemDevice` trait:
|
||||
|
||||
```rust
|
||||
// crates/systems/src/gps/gps_system.rs
|
||||
use hardware::prelude::*;
|
||||
|
||||
pub struct GpsSystemDevice {
|
||||
base: BaseSystemDevice,
|
||||
// GPS-specific fields
|
||||
position: Option<Position>,
|
||||
satellites: u8,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl SystemDevice for GpsSystemDevice {
|
||||
async fn initialize(&mut self) -> Result<()> {
|
||||
self.base.initialize().await?;
|
||||
// GPS-specific initialization
|
||||
self.satellites = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn process(&mut self) -> Result<Vec<BusMessage>> {
|
||||
// Generate GPS data messages
|
||||
let mut messages = Vec::new();
|
||||
|
||||
if let Some(position) = &self.position {
|
||||
let payload = serde_json::to_vec(&position)?;
|
||||
let message = BusMessage::Data {
|
||||
from: self.base.info.address.clone(),
|
||||
to: BusAddress::new("navigation_system"), // Example target
|
||||
payload,
|
||||
message_id: Uuid::new_v4(),
|
||||
};
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
// Implement other required methods...
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Set Up Hardware Bus
|
||||
|
||||
Create a central hardware bus manager:
|
||||
|
||||
```rust
|
||||
// crates/systems/src/hardware_manager.rs
|
||||
use hardware::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct HardwareManager {
|
||||
bus: Arc<HardwareBus>,
|
||||
device_manager: DeviceManager,
|
||||
discovery_protocol: DiscoveryProtocol,
|
||||
}
|
||||
|
||||
impl HardwareManager {
|
||||
pub async fn new() -> Result<Self> {
|
||||
let bus = Arc::new(HardwareBus::new());
|
||||
let device_manager = DeviceManager::new();
|
||||
|
||||
// Create discovery protocol for the manager itself
|
||||
let manager_info = DeviceInfo {
|
||||
address: BusAddress::new("hardware_manager"),
|
||||
config: DeviceConfig {
|
||||
name: "Hardware Manager".to_string(),
|
||||
capabilities: vec![DeviceCapability::Communication],
|
||||
..Default::default()
|
||||
},
|
||||
status: DeviceStatus::Online,
|
||||
last_seen: SystemTime::now(),
|
||||
version: "1.0.0".to_string(),
|
||||
manufacturer: "Yachtpit".to_string(),
|
||||
};
|
||||
|
||||
let discovery_protocol = DiscoveryProtocol::new(
|
||||
manager_info,
|
||||
DiscoveryConfig::default(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
bus,
|
||||
device_manager,
|
||||
discovery_protocol,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn add_system_device(&mut self, device: Box<dyn SystemDevice>) -> Result<()> {
|
||||
let address = device.get_info().address.clone();
|
||||
|
||||
// Connect device to bus
|
||||
let connection = self.bus.connect_device(address.clone()).await?;
|
||||
|
||||
// Add to device manager
|
||||
self.device_manager.add_device(device);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn start_all_systems(&mut self) -> Result<()> {
|
||||
self.device_manager.start_all().await?;
|
||||
self.discovery_protocol.start().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Integrate with Existing Systems
|
||||
|
||||
Modify the existing vessel systems to use the hardware abstraction:
|
||||
|
||||
```rust
|
||||
// crates/systems/src/vessel/vessel_systems.rs
|
||||
use crate::hardware_manager::HardwareManager;
|
||||
|
||||
pub async fn create_vessel_systems_with_hardware() -> Result<HardwareManager> {
|
||||
let mut hardware_manager = HardwareManager::new().await?;
|
||||
|
||||
// Create GPS system
|
||||
let gps_config = DeviceConfig {
|
||||
name: "GPS System".to_string(),
|
||||
capabilities: vec![DeviceCapability::Gps],
|
||||
update_interval_ms: 1000,
|
||||
..Default::default()
|
||||
};
|
||||
let gps_device = Box::new(GpsSystemDevice::new(gps_config));
|
||||
hardware_manager.add_system_device(gps_device).await?;
|
||||
|
||||
// Create Radar system
|
||||
let radar_config = DeviceConfig {
|
||||
name: "Radar System".to_string(),
|
||||
capabilities: vec![DeviceCapability::Radar],
|
||||
update_interval_ms: 500,
|
||||
..Default::default()
|
||||
};
|
||||
let radar_device = Box::new(RadarSystemDevice::new(radar_config));
|
||||
hardware_manager.add_system_device(radar_device).await?;
|
||||
|
||||
// Create AIS system
|
||||
let ais_config = DeviceConfig {
|
||||
name: "AIS System".to_string(),
|
||||
capabilities: vec![DeviceCapability::Ais],
|
||||
update_interval_ms: 2000,
|
||||
..Default::default()
|
||||
};
|
||||
let ais_device = Box::new(AisSystemDevice::new(ais_config));
|
||||
hardware_manager.add_system_device(ais_device).await?;
|
||||
|
||||
hardware_manager.start_all_systems().await?;
|
||||
|
||||
Ok(hardware_manager)
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Update Main Application
|
||||
|
||||
Integrate the hardware manager into the main yachtpit application:
|
||||
|
||||
```rust
|
||||
// crates/yachtpit/src/core/system_manager.rs
|
||||
use systems::vessel::vessel_systems::create_vessel_systems_with_hardware;
|
||||
|
||||
pub struct SystemManager {
|
||||
hardware_manager: Option<HardwareManager>,
|
||||
}
|
||||
|
||||
impl SystemManager {
|
||||
pub async fn initialize_with_hardware(&mut self) -> Result<()> {
|
||||
let hardware_manager = create_vessel_systems_with_hardware().await?;
|
||||
self.hardware_manager = Some(hardware_manager);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn discover_devices(&self) -> Result<Vec<DeviceInfo>> {
|
||||
if let Some(ref manager) = self.hardware_manager {
|
||||
// Use discovery protocol to find devices
|
||||
manager.discovery_protocol.discover_devices(None).await?;
|
||||
tokio::time::sleep(Duration::from_millis(100)).await; // Wait for responses
|
||||
Ok(manager.discovery_protocol.get_known_devices().await)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Message Flow Examples
|
||||
|
||||
### GPS Data Flow
|
||||
```
|
||||
GPS Device → Hardware Bus → Navigation System
|
||||
→ Discovery Protocol (heartbeat)
|
||||
→ Other interested devices
|
||||
```
|
||||
|
||||
### Device Discovery Flow
|
||||
```
|
||||
New Device → Announce Message → Hardware Bus → All Devices
|
||||
Discovery Request → Hardware Bus → Matching Devices → Response
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Device Configuration
|
||||
Each device can be configured with:
|
||||
- Update intervals
|
||||
- Capabilities
|
||||
- Custom configuration parameters
|
||||
- Message queue sizes
|
||||
|
||||
### Discovery Configuration
|
||||
- Heartbeat intervals
|
||||
- Device timeout periods
|
||||
- Cleanup intervals
|
||||
- Maximum tracked devices
|
||||
|
||||
## Testing Integration
|
||||
|
||||
### Unit Tests
|
||||
Run tests for individual components:
|
||||
```bash
|
||||
cargo test -p hardware
|
||||
cargo test -p systems
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
Create integration tests that verify the complete flow:
|
||||
|
||||
```rust
|
||||
#[tokio::test]
|
||||
async fn test_complete_hardware_integration() {
|
||||
let mut hardware_manager = HardwareManager::new().await.unwrap();
|
||||
|
||||
// Add test devices
|
||||
let gps_device = Box::new(create_test_gps_device());
|
||||
hardware_manager.add_system_device(gps_device).await.unwrap();
|
||||
|
||||
// Start systems
|
||||
hardware_manager.start_all_systems().await.unwrap();
|
||||
|
||||
// Verify device discovery
|
||||
let devices = hardware_manager.discovery_protocol.get_known_devices().await;
|
||||
assert!(!devices.is_empty());
|
||||
|
||||
// Test message passing
|
||||
// ... additional test logic
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
1. **Message Throughput**: The hardware bus uses unbounded channels for high throughput
|
||||
2. **Device Limits**: Configure maximum device limits based on system resources
|
||||
3. **Update Intervals**: Balance between data freshness and system load
|
||||
4. **Memory Usage**: Monitor device registry size and message history
|
||||
|
||||
## Error Handling
|
||||
|
||||
The hardware abstraction layer provides comprehensive error handling:
|
||||
|
||||
- **Device Errors**: Automatic retry and fallback mechanisms
|
||||
- **Bus Errors**: Connection recovery and message queuing
|
||||
- **Discovery Errors**: Timeout handling and device cleanup
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Parallel Implementation
|
||||
- Keep existing systems running
|
||||
- Implement hardware abstraction alongside
|
||||
- Gradual migration of individual systems
|
||||
|
||||
### Phase 2: Feature Parity
|
||||
- Ensure all existing functionality is available
|
||||
- Add comprehensive testing
|
||||
- Performance validation
|
||||
|
||||
### Phase 3: Full Migration
|
||||
- Switch to hardware abstraction as primary
|
||||
- Remove legacy system implementations
|
||||
- Optimize performance
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Device Not Found**: Check device registration and bus connection
|
||||
2. **Message Delivery Failures**: Verify device addresses and bus connectivity
|
||||
3. **Discovery Timeouts**: Adjust discovery configuration parameters
|
||||
4. **Performance Issues**: Monitor message queue sizes and update intervals
|
||||
|
||||
### Debugging Tools
|
||||
|
||||
```rust
|
||||
// Enable debug logging
|
||||
use tracing::{info, debug, warn};
|
||||
|
||||
// Check device status
|
||||
// let device_info = hardware_manager.get_device_info(&address).await;
|
||||
// debug!("Device status: {:?}", device_info.status);
|
||||
|
||||
// Monitor message history
|
||||
// let messages = hardware_bus.get_message_history().await;
|
||||
// info!("Recent messages: {}", messages.len());
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Network Discovery**: Extend discovery protocol to work across network boundaries
|
||||
2. **Device Simulation**: Add comprehensive device simulators for testing
|
||||
3. **Hot-Plugging**: Support for dynamic device addition/removal
|
||||
4. **Load Balancing**: Distribute device processing across multiple threads
|
||||
5. **Persistence**: Save and restore device configurations and state
|
||||
|
||||
## Conclusion
|
||||
|
||||
The virtual hardware abstraction layer provides a robust foundation for managing yacht systems. By following this integration guide, you can gradually migrate existing systems while maintaining full functionality and adding new capabilities for device discovery and communication.
|
||||
|
||||
For questions or issues during integration, refer to the individual module documentation in the hardware crate or create an issue in the project repository.
|
Reference in New Issue
Block a user