aranet_core/
events.rs

1//! Device event system for connection and reading notifications.
2//!
3//! This module provides an event-based system for receiving notifications
4//! about device connections, disconnections, readings, and errors.
5
6use serde::{Deserialize, Serialize};
7use tokio::sync::broadcast;
8
9use aranet_types::{CurrentReading, DeviceInfo, DeviceType};
10
11/// Device identifier for events.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct DeviceId {
14    /// Unique identifier (peripheral ID or MAC address).
15    pub id: String,
16    /// Device name if known.
17    pub name: Option<String>,
18    /// Device type if known.
19    pub device_type: Option<DeviceType>,
20}
21
22impl DeviceId {
23    /// Create a new device ID.
24    pub fn new(id: impl Into<String>) -> Self {
25        Self {
26            id: id.into(),
27            name: None,
28            device_type: None,
29        }
30    }
31
32    /// Create a device ID with name.
33    pub fn with_name(id: impl Into<String>, name: impl Into<String>) -> Self {
34        Self {
35            id: id.into(),
36            name: Some(name.into()),
37            device_type: None,
38        }
39    }
40}
41
42/// Events that can be emitted by devices.
43///
44/// All events are serializable for logging, persistence, and IPC.
45///
46/// This enum is marked `#[non_exhaustive]` to allow adding new event types
47/// in future versions without breaking downstream code.
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(tag = "type", rename_all = "snake_case")]
50#[non_exhaustive]
51pub enum DeviceEvent {
52    /// Device was discovered during scanning.
53    Discovered { device: DeviceId, rssi: Option<i16> },
54    /// Successfully connected to device.
55    Connected {
56        device: DeviceId,
57        info: Option<DeviceInfo>,
58    },
59    /// Disconnected from device.
60    Disconnected {
61        device: DeviceId,
62        reason: DisconnectReason,
63    },
64    /// New reading received from device.
65    Reading {
66        device: DeviceId,
67        reading: CurrentReading,
68    },
69    /// Error occurred during device operation.
70    Error { device: DeviceId, error: String },
71    /// Reconnection attempt started.
72    ReconnectStarted { device: DeviceId, attempt: u32 },
73    /// Reconnection succeeded.
74    ReconnectSucceeded { device: DeviceId, attempts: u32 },
75    /// Battery level changed significantly.
76    BatteryLow { device: DeviceId, level: u8 },
77}
78
79/// Reason for disconnection.
80///
81/// This enum is marked `#[non_exhaustive]` to allow adding new reasons
82/// in future versions without breaking downstream code.
83#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
84#[non_exhaustive]
85pub enum DisconnectReason {
86    /// Normal disconnection requested by user.
87    UserRequested,
88    /// Device went out of range.
89    OutOfRange,
90    /// Connection timed out.
91    Timeout,
92    /// Device was powered off.
93    DevicePoweredOff,
94    /// BLE error occurred.
95    BleError(String),
96    /// Unknown reason.
97    Unknown,
98}
99
100/// Sender for device events.
101pub type EventSender = broadcast::Sender<DeviceEvent>;
102
103/// Receiver for device events.
104pub type EventReceiver = broadcast::Receiver<DeviceEvent>;
105
106/// Create a new event channel with the given capacity.
107pub fn event_channel(capacity: usize) -> (EventSender, EventReceiver) {
108    broadcast::channel(capacity)
109}
110
111/// Create a default event channel with capacity 100.
112pub fn default_event_channel() -> (EventSender, EventReceiver) {
113    event_channel(100)
114}
115
116/// Event dispatcher for sending events to multiple receivers.
117#[derive(Debug, Clone)]
118pub struct EventDispatcher {
119    sender: EventSender,
120}
121
122impl EventDispatcher {
123    /// Create a new event dispatcher.
124    pub fn new(capacity: usize) -> Self {
125        let (sender, _) = broadcast::channel(capacity);
126        Self { sender }
127    }
128
129    /// Subscribe to events.
130    pub fn subscribe(&self) -> EventReceiver {
131        self.sender.subscribe()
132    }
133
134    /// Send an event.
135    pub fn send(&self, event: DeviceEvent) {
136        // Ignore error if no receivers
137        let _ = self.sender.send(event);
138    }
139
140    /// Get the number of active receivers.
141    pub fn receiver_count(&self) -> usize {
142        self.sender.receiver_count()
143    }
144
145    /// Get the sender for direct use.
146    pub fn sender(&self) -> EventSender {
147        self.sender.clone()
148    }
149}
150
151impl Default for EventDispatcher {
152    fn default() -> Self {
153        Self::new(100)
154    }
155}