1use btleplug::api::{Characteristic, Peripheral as _, WriteType};
22use btleplug::platform::Peripheral;
23use std::collections::BTreeMap;
24use std::fmt::Debug;
25use std::sync::Arc;
26use tokio_util::sync::CancellationToken;
27
28use crate::consts::{HubPropertyOperation, HubPropertyRef, HubType};
29use crate::error::{Error, OptionContext, Result};
30use crate::notifications::{
31 AlertOperation, AlertPayload, AlertType, ErrorMessageFormat, HubAction,
32 HubActionRequest, HubAlert, HubProperty, HubPropertyValue,
33 InformationRequest, InformationType, InputSetupSingle,
34 ModeInformationRequest, ModeInformationType, NetworkCommand,
35 NotificationMessage, PortOutputCommandFeedbackFormat,
36 PortValueCombinedFormat, PortValueSingleFormat,
37};
38use crate::{IoDevice, IoTypeId};
39pub type Tokens = Arc<(Peripheral, Characteristic)>;
40
41pub mod generic_hub;
42pub mod io_event;
43
44#[async_trait::async_trait]
46pub trait Hub: Debug + Send + Sync {
47 async fn name(&self) -> Result<String>;
48 async fn disconnect(&self) -> Result<()>;
49 async fn shutdown(&self) -> Result<()>;
50 async fn is_connected(&self) -> Result<bool>;
51 fn properties(&self) -> &HubProperties;
54 fn kind(&self) -> HubType;
55 fn connected_io(&self) -> &BTreeMap<u8, IoDevice>;
56 fn connected_io_mut(&mut self) -> &mut BTreeMap<u8, IoDevice>;
57 fn channels(&mut self) -> &mut crate::hubs::Channels;
58 async fn subscribe(&self, char: Characteristic) -> Result<()>;
60 fn io_from_port(&self, port_id: u8) -> Result<IoDevice>;
61 fn io_from_kind(&self, kind: IoTypeId) -> Result<IoDevice>;
62 fn io_multi_from_kind(&self, kind: IoTypeId) -> Result<Vec<IoDevice>>;
63
64 fn tokens(&self) -> Tokens;
65 fn attach_io(&mut self, io_type_id: IoTypeId, port_id: u8) -> Result<()>;
66 fn peripheral(&self) -> Arc<Peripheral>;
67 fn characteristic(&self) -> Arc<Characteristic>;
68 fn device_cache(&self, d: IoDevice) -> IoDevice;
69 fn cancel_token(&self) -> CancellationToken;
70
71 async fn request_port_info(
73 &self,
74 port_id: u8,
75 infotype: InformationType,
76 ) -> Result<()> {
77 let msg =
78 NotificationMessage::PortInformationRequest(InformationRequest {
79 port_id,
80 information_type: infotype,
81 });
82 self.send(msg).await
83 }
84 async fn req_mode_info(
85 &self,
86 port_id: u8,
87 mode: u8,
88 infotype: ModeInformationType,
89 ) -> Result<()> {
90 let msg = NotificationMessage::PortModeInformationRequest(
91 ModeInformationRequest {
92 port_id,
93 mode,
94 information_type: infotype,
95 },
96 );
97 self.send(msg).await
98 }
99
100 async fn set_port_mode(
101 &self,
102 port_id: u8,
103 mode: u8,
104 delta: u32,
105 notification_enabled: bool,
106 ) -> Result<()> {
107 let msg =
108 NotificationMessage::PortInputFormatSetupSingle(InputSetupSingle {
109 port_id,
110 mode,
111 delta,
112 notification_enabled,
113 });
114 self.send(msg).await
115 }
116
117 async fn hub_props(
119 &self,
120 reference: HubPropertyRef,
121 operation: HubPropertyOperation,
122 ) -> Result<()> {
123 let msg = NotificationMessage::HubProperties(HubProperty {
124 reference,
125 operation,
126 property: HubPropertyValue::SecondaryMacAddress, });
128 self.send(msg).await
129 }
130
131 async fn hub_action(&self, action_type: HubAction) -> Result<()> {
133 let msg =
134 NotificationMessage::HubActions(HubActionRequest { action_type });
135 self.send(msg).await
136 }
137
138 async fn hub_alerts(
140 &self,
141 alert_type: AlertType,
142 operation: AlertOperation,
143 ) -> Result<()> {
144 let msg = NotificationMessage::HubAlerts(HubAlert {
145 alert_type,
146 operation,
147 payload: AlertPayload::StatusOk,
148 });
149 self.send(msg).await
150 }
151
152 async fn send(&self, msg: NotificationMessage) -> Result<()> {
153 let buf = msg.serialise();
154 let tokens = self.tokens();
155 tokens
156 .0
157 .write(&tokens.1, &buf, WriteType::WithoutResponse)
158 .await?;
159 Ok(())
160 }
161
162 async fn send_raw(&self, msg: &[u8]) -> Result<()>;
164}
165
166pub type VersionNumber = u8;
167#[derive(Debug, Default)]
169pub struct HubProperties {
170 pub name: String,
172 pub fw_version: String,
174 pub hw_version: String,
176 pub mac_address: String,
178 pub battery_level: usize,
180 pub rssi: i16,
182}
183
184pub async fn send(tokens: Tokens, msg: NotificationMessage) -> Result<()> {
186 let buf = msg.serialise();
187 tokens
188 .0
189 .write(&tokens.1, &buf, WriteType::WithoutResponse)
190 .await?;
191 Ok(())
192}
193
194#[derive(Debug, Default, Clone)]
195pub struct Channels {
196 pub singlevalue_sender:
197 Option<tokio::sync::broadcast::Sender<PortValueSingleFormat>>,
198 pub combinedvalue_sender:
199 Option<tokio::sync::broadcast::Sender<PortValueCombinedFormat>>,
200 pub networkcmd_sender:
201 Option<tokio::sync::broadcast::Sender<NetworkCommand>>,
202 pub hubnotification_sender:
203 Option<tokio::sync::broadcast::Sender<HubNotification>>,
204 pub commandfeedback_sender:
205 Option<tokio::sync::broadcast::Sender<PortOutputCommandFeedbackFormat>>,
206}
207
208#[derive(Debug, Default, Clone)]
209pub struct HubNotification {
210 pub hub_property: Option<HubProperty>,
211 pub hub_action: Option<HubActionRequest>,
212 pub hub_alert: Option<HubAlert>,
213 pub hub_error: Option<ErrorMessageFormat>,
214}