1//! Interface traits for the BrewMaster Pro 3000 Coffee Machine
2//!
3//! This module contains trait definitions corresponding to the interface
4//! specifications defined in the sphinx-needs documentation.
5//! Each trait represents a communication contract between architectural
6//! components as specified in docs/coffee-machine/index.rst
7
[docs] 8// @ BrewStrength enum, IMPL_BREW_STRENGTH, impl, [SWREQ_BREW_STRENGTH]
9/// Brew strength selection for coffee brewing
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum BrewStrength {
12 /// Weak: 180ml water, 3 minutes
13 Weak,
14 /// Medium: 180ml water, 4 minutes
15 Medium,
16 /// Strong: 180ml water, 5 minutes
17 Strong,
18}
19
[docs] 20// @ SafetyCommand enum, IMPL_SAFETY_CMD_ENUM, impl, [INTF_SAFETY_CMD]
21/// Safety command types for emergency control
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum SafetyCommand {
24 /// Immediate shutdown (<100ms response required)
25 EmergencyStop,
26 /// Clear emergency state after fault resolved
27 ResumeNormal,
28}
29
[docs] 30// @ UserCommand enum, IMPL_USER_CMD_ENUM, impl, [INTF_USER_CMD]
31/// User command types for UI interaction
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum UserCommand {
34 /// Start brewing with specified strength
35 StartBrew(BrewStrength),
36 /// Stop/cancel current brewing operation
37 StopBrew,
38 /// Select brew strength (without starting)
39 SelectStrength(BrewStrength),
40}
41
42/// Temperature Status Interface (INTF_TEMP_STATUS)
43///
44/// **Provider**: Temperature Controller Module
45///
46/// **Consumer**: Brew Controller Module
47///
48/// **Description**: Provides current temperature readings and heating
49/// status to the brew controller.
50///
51/// **Protocol**: Shared memory with atomic updates, 100ms refresh rate
[docs] 52// @ TemperatureStatus struct, IMPL_TEMP_STATUS, impl, [INTF_TEMP_STATUS]
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub struct TemperatureStatus {
55 /// Current temperature in °C × 10 for 0.1°C resolution
56 pub current_temp: i16,
57 /// Target temperature in °C × 10
58 pub target_temp: i16,
59 /// True when within target range
60 pub is_ready: bool,
61 /// True when heating element is active
62 pub heating_active: bool,
63}
64
65impl TemperatureStatus {
66 /// Create a new temperature status
67 pub fn new(current_temp: i16, target_temp: i16, is_ready: bool, heating_active: bool) -> Self {
68 Self {
69 current_temp,
70 target_temp,
71 is_ready,
72 heating_active,
73 }
74 }
75
76 /// Get current temperature in °C (floating point)
77 pub fn current_temp_celsius(&self) -> f32 {
78 self.current_temp as f32 / 10.0
79 }
80
81 /// Get target temperature in °C (floating point)
82 pub fn target_temp_celsius(&self) -> f32 {
83 self.target_temp as f32 / 10.0
84 }
85}
86
[docs] 87// @ TemperatureStatusProvider trait, IMPL_TEMP_STATUS_PROVIDER, impl, [INTF_TEMP_STATUS, COMP_TEMP_CTRL]
88/// Trait for components that provide temperature status
89///
90/// Implements: Temperature Controller Module (COMP_TEMP_CTRL)
91pub trait TemperatureStatusProvider {
92 /// Get the current temperature status
93 fn get_temperature_status(&self) -> TemperatureStatus;
94}
95
[docs] 96// @ TemperatureStatusConsumer trait, IMPL_TEMP_STATUS_CONSUMER, impl, [INTF_TEMP_STATUS, COMP_BREW_CTRL]
97/// Trait for components that consume temperature status
98///
99/// Implements: Brew Controller Module (COMP_BREW_CTRL)
100pub trait TemperatureStatusConsumer {
101 /// Update with new temperature status
102 fn update_temperature_status(&mut self, status: TemperatureStatus);
103}
104
105/// Temperature Controller Status Interface (INTF_TEMP_CTRL_STATUS)
106///
107/// **Provider**: Temperature Controller Module (COMP_TEMP_CTRL)
108///
109/// **Consumer**: Safety Monitor Module (COMP_SAFETY_MON)
110///
111/// **Description**: Continuous status reporting from the Temperature Controller
112/// to the Safety Monitor, including temperature readings and fault flags.
113///
114/// **Protocol**: Polled by safety monitor at 10Hz
[docs]115// @ TempCtrlStatus struct, IMPL_TEMP_CTRL_STATUS, impl, [INTF_TEMP_CTRL_STATUS]
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117pub struct TempCtrlStatus {
118 /// Module identifier (fixed value for Temperature Controller)
119 pub module_id: u8,
120 /// Heartbeat counter (incremented each control cycle)
121 pub heartbeat_counter: u32,
122 /// Bitfield of detected faults (0 = no fault)
123 pub fault_flags: u16,
124 /// Current measured temperature (°C × 10 for 0.1°C resolution)
125 pub temperature_value: i16,
126}
127
128impl TempCtrlStatus {
129 /// Create a new temperature controller status
130 pub fn new(
131 module_id: u8,
132 heartbeat_counter: u32,
133 fault_flags: u16,
134 temperature_value: i16,
135 ) -> Self {
136 Self {
137 module_id,
138 heartbeat_counter,
139 fault_flags,
140 temperature_value,
141 }
142 }
143
144 /// Check if any faults are present
145 pub fn has_faults(&self) -> bool {
146 self.fault_flags != 0
147 }
148
149 /// Get temperature in °C (floating point)
150 pub fn temperature_celsius(&self) -> f32 {
151 self.temperature_value as f32 / 10.0
152 }
153}
154
[docs]155// @ TempCtrlStatusProvider trait, IMPL_TEMP_CTRL_STATUS_PROVIDER, impl, [INTF_TEMP_CTRL_STATUS, COMP_TEMP_CTRL]
156/// Trait for the Temperature Controller to expose its status to the Safety Monitor
157///
158/// Implements: Temperature Controller Module (COMP_TEMP_CTRL)
159pub trait TempCtrlStatusProvider {
160 /// Get the current temperature controller status
161 fn get_temp_ctrl_status(&self) -> TempCtrlStatus;
162}
163
[docs]164// @ TempCtrlStatusConsumer trait, IMPL_TEMP_CTRL_STATUS_CONSUMER, impl, [INTF_TEMP_CTRL_STATUS, COMP_SAFETY_MON]
165/// Trait for the Safety Monitor to consume temperature controller status
166///
167/// Implements: Safety Monitor Module (COMP_SAFETY_MON)
168pub trait TempCtrlStatusConsumer {
169 /// Process a temperature controller status update
170 fn process_temp_ctrl_status(&mut self, status: TempCtrlStatus);
171}
172
173/// Brew Controller Status Interface (INTF_BREW_CTRL_STATUS)
174///
175/// **Provider**: Brew Controller Module (COMP_BREW_CTRL)
176///
177/// **Consumer**: Safety Monitor Module (COMP_SAFETY_MON)
178///
179/// **Description**: Continuous status reporting from the Brew Controller
180/// to the Safety Monitor, including water level readings and fault flags.
181///
182/// **Protocol**: Polled by safety monitor at 10Hz
[docs]183// @ BrewCtrlStatus struct, IMPL_BREW_CTRL_STATUS, impl, [INTF_BREW_CTRL_STATUS]
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185pub struct BrewCtrlStatus {
186 /// Module identifier (fixed value for Brew Controller)
187 pub module_id: u8,
188 /// Heartbeat counter (incremented each control cycle)
189 pub heartbeat_counter: u32,
190 /// Bitfield of detected faults (0 = no fault)
191 pub fault_flags: u16,
192 /// Current water level (0–100%)
193 pub water_level: u8,
194}
195
196impl BrewCtrlStatus {
197 /// Create a new brew controller status
198 pub fn new(
199 module_id: u8,
200 heartbeat_counter: u32,
201 fault_flags: u16,
202 water_level: u8,
203 ) -> Self {
204 Self {
205 module_id,
206 heartbeat_counter,
207 fault_flags,
208 water_level,
209 }
210 }
211
212 /// Check if any faults are present
213 pub fn has_faults(&self) -> bool {
214 self.fault_flags != 0
215 }
216}
217
[docs]218// @ BrewCtrlStatusProvider trait, IMPL_BREW_CTRL_STATUS_PROVIDER, impl, [INTF_BREW_CTRL_STATUS, COMP_BREW_CTRL]
219/// Trait for the Brew Controller to expose its status to the Safety Monitor
220///
221/// Implements: Brew Controller Module (COMP_BREW_CTRL)
222pub trait BrewCtrlStatusProvider {
223 /// Get the current brew controller status
224 fn get_brew_ctrl_status(&self) -> BrewCtrlStatus;
225}
226
[docs]227// @ BrewCtrlStatusConsumer trait, IMPL_BREW_CTRL_STATUS_CONSUMER, impl, [INTF_BREW_CTRL_STATUS, COMP_SAFETY_MON]
228/// Trait for the Safety Monitor to consume brew controller status
229///
230/// Implements: Safety Monitor Module (COMP_SAFETY_MON)
231pub trait BrewCtrlStatusConsumer {
232 /// Process a brew controller status update
233 fn process_brew_ctrl_status(&mut self, status: BrewCtrlStatus);
234}
235
236/// Safety Command Interface (INTF_SAFETY_CMD)
237///
238/// **Provider**: Safety Monitor Module
239///
240/// **Consumers**: Temperature Controller, Brew Controller
241///
242/// **Description**: Emergency shutdown commands from safety monitor to
243/// all controlled subsystems.
244///
245/// **Protocol**: Interrupt-driven with hardware watchdog backup, highest priority
[docs]246// @ SafetyCommandProvider trait, IMPL_SAFETY_CMD_PROVIDER, impl, [INTF_SAFETY_CMD, COMP_SAFETY_MON]
247pub trait SafetyCommandProvider {
248 /// Send a safety command to subsystems
249 fn send_safety_command(&self, command: SafetyCommand);
250}
251
[docs]252// @ SafetyCommandConsumer trait, IMPL_SAFETY_CMD_CONSUMER, impl, [INTF_SAFETY_CMD, COMP_TEMP_CTRL, COMP_BREW_CTRL]
253/// Trait for components that receive safety commands
254///
255/// Implements: Temperature Controller (COMP_TEMP_CTRL), Brew Controller (COMP_BREW_CTRL)
256pub trait SafetyCommandConsumer {
257 /// Handle a safety command (must respond within 100ms for EMERGENCY_STOP)
258 fn handle_safety_command(&mut self, command: SafetyCommand);
259}
260
261/// User Command Interface (INTF_USER_CMD)
262///
263/// **Provider**: User Interface Module
264///
265/// **Consumer**: Brew Controller Module
266///
267/// **Description**: User commands and settings passed from UI to the
268/// brewing state machine.
269///
270/// **Protocol**: Message queue with event-driven processing, debounced at UI layer
[docs]271// @ UserCommandProvider trait, IMPL_USER_CMD_PROVIDER, impl, [INTF_USER_CMD, COMP_UI_MODULE]
272pub trait UserCommandProvider {
273 /// Send a user command to the brew controller
274 fn send_user_command(&self, command: UserCommand);
275}
276
[docs]277// @ UserCommandConsumer trait, IMPL_USER_CMD_CONSUMER, impl, [INTF_USER_CMD, COMP_BREW_CTRL]
278/// Trait for components that consume user commands
279///
280/// Implements: Brew Controller Module (COMP_BREW_CTRL)
281pub trait UserCommandConsumer {
282 /// Handle a user command
283 fn handle_user_command(&mut self, command: UserCommand);
284}
285
286/// Sensor Data Interface (INTF_SENSOR_DATA)
287///
288/// **Provider**: Hardware sensors (temperature, water level)
289///
290/// **Consumers**: Temperature Controller, Safety Monitor
291///
292/// **Description**: Raw sensor readings from hardware via ADC.
293///
294/// **Protocol**: ADC DMA with double buffering, 100Hz sampling rate
[docs]295// @ SensorData struct, IMPL_SENSOR_DATA, impl, [INTF_SENSOR_DATA]
296#[derive(Debug, Clone, Copy, PartialEq, Eq)]
297pub struct SensorData {
298 /// Temperature sensor ADC value (0-4095)
299 pub temp_sensor_raw: u16,
300 /// Water level sensor ADC value (0-4095)
301 pub water_level_raw: u16,
302 /// Timestamp in milliseconds
303 pub sensor_timestamp: u32,
304}
305
306impl SensorData {
307 /// Create new sensor data
308 pub fn new(temp_sensor_raw: u16, water_level_raw: u16, sensor_timestamp: u32) -> Self {
309 Self {
310 temp_sensor_raw,
311 water_level_raw,
312 sensor_timestamp,
313 }
314 }
315}
316
[docs]317// @ SensorDataProvider trait, IMPL_SENSOR_DATA_PROVIDER, impl, [INTF_SENSOR_DATA, COMP_HAL]
318/// Trait for components that provide sensor data
319///
320/// Implements: Hardware Abstraction Layer (COMP_HAL)
321pub trait SensorDataProvider {
322 /// Get the latest sensor readings
323 fn get_sensor_data(&self) -> SensorData;
324}
325
[docs]326// @ SensorDataConsumer trait, IMPL_SENSOR_DATA_CONSUMER, impl, [INTF_SENSOR_DATA, COMP_TEMP_CTRL, COMP_SAFETY_MON]
327/// Trait for components that consume sensor data
328///
329/// Implements: Temperature Controller (COMP_TEMP_CTRL), Safety Monitor (COMP_SAFETY_MON)
330pub trait SensorDataConsumer {
331 /// Process new sensor data
332 fn process_sensor_data(&mut self, data: SensorData);
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
340 fn test_temperature_status_conversions() {
341 let status = TemperatureStatus::new(900, 950, true, false);
342 assert_eq!(status.current_temp_celsius(), 90.0);
343 assert_eq!(status.target_temp_celsius(), 95.0);
344 assert_eq!(status.is_ready, true);
345 assert_eq!(status.heating_active, false);
346 }
347
348 #[test]
349 fn test_temp_ctrl_status_fault_detection() {
350 let status_no_fault = TempCtrlStatus::new(1, 100, 0, 900);
351 assert_eq!(status_no_fault.has_faults(), false);
352 assert_eq!(status_no_fault.temperature_celsius(), 90.0);
353
354 let status_with_fault = TempCtrlStatus::new(1, 101, 0x0001, 900);
355 assert_eq!(status_with_fault.has_faults(), true);
356 }
357
358 #[test]
359 fn test_brew_ctrl_status_fault_detection() {
360 let status_no_fault = BrewCtrlStatus::new(2, 100, 0, 80);
361 assert_eq!(status_no_fault.has_faults(), false);
362 assert_eq!(status_no_fault.water_level, 80);
363
364 let status_with_fault = BrewCtrlStatus::new(2, 101, 0x0001, 80);
365 assert_eq!(status_with_fault.has_faults(), true);
366 }
367
368 #[test]
369 fn test_brew_strength_enum() {
370 let strength = BrewStrength::Medium;
371 assert_eq!(strength, BrewStrength::Medium);
372 assert_ne!(strength, BrewStrength::Weak);
373 }
374
375 #[test]
376 fn test_user_command_variants() {
377 let cmd1 = UserCommand::StartBrew(BrewStrength::Strong);
378 let cmd2 = UserCommand::StopBrew;
379 let cmd3 = UserCommand::SelectStrength(BrewStrength::Weak);
380
381 match cmd1 {
382 UserCommand::StartBrew(BrewStrength::Strong) => (),
383 _ => panic!("Wrong command variant"),
384 }
385
386 match cmd2 {
387 UserCommand::StopBrew => (),
388 _ => panic!("Wrong command variant"),
389 }
390
391 match cmd3 {
392 UserCommand::SelectStrength(BrewStrength::Weak) => (),
393 _ => panic!("Wrong command variant"),
394 }
395 }
396
397 #[test]
398 fn test_sensor_data_creation() {
399 let data = SensorData::new(2048, 3000, 12345);
400 assert_eq!(data.temp_sensor_raw, 2048);
401 assert_eq!(data.water_level_raw, 3000);
402 assert_eq!(data.sensor_timestamp, 12345);
403 }
404}