add all crates: domain, protocol, application, client, adapters, ESP32 firmware
Server: domain (entities, value objects, ports), protocol (postcard wire types), application (config service, data projection), adapters (config-memory, tcp-server), bootstrap (composition root with fake data). Client: client-domain (layout engine, render tree, HAL ports), client-application (message handling, repaint commands), adapters (tcp-client, display-terminal), client-desktop (end-to-end working). ESP32: client-esp32 firmware with ILI9341 display over SPI, WiFi networking. Display test verified on hardware — landscape orientation, text rendering works. 60 workspace tests, all passing.
This commit is contained in:
17
crates/domain/src/ports/broadcast.rs
Normal file
17
crates/domain/src/ports/broadcast.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use crate::entities::WidgetId;
|
||||
use crate::value_objects::{Layout, WidgetState};
|
||||
|
||||
pub trait BroadcastPort {
|
||||
type Error;
|
||||
|
||||
async fn push_screen_update(
|
||||
&self,
|
||||
layout: &Layout,
|
||||
widgets: &[(WidgetId, WidgetState)],
|
||||
) -> Result<(), Self::Error>;
|
||||
|
||||
async fn push_data_update(
|
||||
&self,
|
||||
updates: &[(WidgetId, WidgetState)],
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
26
crates/domain/src/ports/config_repository.rs
Normal file
26
crates/domain/src/ports/config_repository.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use crate::entities::{
|
||||
DataSource, DataSourceId, LayoutPreset, LayoutPresetId, WidgetConfig, WidgetId,
|
||||
};
|
||||
use crate::value_objects::Layout;
|
||||
|
||||
pub trait ConfigRepository {
|
||||
type Error;
|
||||
|
||||
async fn get_widget(&self, id: WidgetId) -> Result<Option<WidgetConfig>, Self::Error>;
|
||||
async fn list_widgets(&self) -> Result<Vec<WidgetConfig>, Self::Error>;
|
||||
async fn save_widget(&self, config: &WidgetConfig) -> Result<(), Self::Error>;
|
||||
async fn delete_widget(&self, id: WidgetId) -> Result<(), Self::Error>;
|
||||
|
||||
async fn get_data_source(&self, id: DataSourceId) -> Result<Option<DataSource>, Self::Error>;
|
||||
async fn list_data_sources(&self) -> Result<Vec<DataSource>, Self::Error>;
|
||||
async fn save_data_source(&self, source: &DataSource) -> Result<(), Self::Error>;
|
||||
async fn delete_data_source(&self, id: DataSourceId) -> Result<(), Self::Error>;
|
||||
|
||||
async fn get_layout(&self) -> Result<Option<Layout>, Self::Error>;
|
||||
async fn save_layout(&self, layout: &Layout) -> Result<(), Self::Error>;
|
||||
|
||||
async fn get_preset(&self, id: LayoutPresetId) -> Result<Option<LayoutPreset>, Self::Error>;
|
||||
async fn list_presets(&self) -> Result<Vec<LayoutPreset>, Self::Error>;
|
||||
async fn save_preset(&self, preset: &LayoutPreset) -> Result<(), Self::Error>;
|
||||
async fn delete_preset(&self, id: LayoutPresetId) -> Result<(), Self::Error>;
|
||||
}
|
||||
8
crates/domain/src/ports/data_source_port.rs
Normal file
8
crates/domain/src/ports/data_source_port.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use crate::entities::DataSource;
|
||||
use crate::value_objects::Value;
|
||||
|
||||
pub trait DataSourcePort {
|
||||
type Error;
|
||||
|
||||
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error>;
|
||||
}
|
||||
7
crates/domain/src/ports/event.rs
Normal file
7
crates/domain/src/ports/event.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use crate::events::DomainEvent;
|
||||
|
||||
pub trait EventPublisher {
|
||||
type Error;
|
||||
|
||||
async fn publish(&self, event: DomainEvent) -> Result<(), Self::Error>;
|
||||
}
|
||||
9
crates/domain/src/ports/mod.rs
Normal file
9
crates/domain/src/ports/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod config_repository;
|
||||
mod data_source_port;
|
||||
mod broadcast;
|
||||
mod event;
|
||||
|
||||
pub use config_repository::ConfigRepository;
|
||||
pub use data_source_port::DataSourcePort;
|
||||
pub use broadcast::BroadcastPort;
|
||||
pub use event::EventPublisher;
|
||||
Reference in New Issue
Block a user