@@ -25,7 +25,8 @@ use bluer::{
25
25
gatt:: local:: {
26
26
characteristic_control, service_control, Application , ApplicationHandle , Characteristic ,
27
27
CharacteristicControl , CharacteristicNotify , CharacteristicNotifyMethod ,
28
- CharacteristicRead , Service , ServiceControl ,
28
+ CharacteristicRead , CharacteristicWrite , CharacteristicWriteMethod , Service ,
29
+ ServiceControl ,
29
30
} ,
30
31
Adapter , Result , Uuid ,
31
32
} ;
@@ -37,6 +38,7 @@ use tokio::sync::{
37
38
} ;
38
39
39
40
mod error;
41
+ mod rpc;
40
42
mod status;
41
43
42
44
const SERVICE_UUID : Uuid = Uuid :: from_u128 ( 0x00467768_6228_2272_4663_277478268000 ) ;
@@ -68,79 +70,60 @@ impl InnerState {
68
70
}
69
71
70
72
#[ derive( Clone , Debug ) ]
71
- pub struct State ( Arc < RwLock < InnerState > > ) ;
72
-
73
- impl State {
74
- pub fn new ( state : InnerState ) -> Self {
75
- Self ( Arc :: new ( RwLock :: new ( state) ) )
76
- }
73
+ pub struct State < T > {
74
+ inner : Arc < RwLock < InnerState > > ,
75
+ status_change_notifier : Sender < ( ) > ,
76
+ error_change_notifier : Sender < ( ) > ,
77
+ timeout : Option < Duration > ,
78
+ handler : T ,
79
+ }
77
80
78
- pub async fn status ( & self ) -> Status {
79
- self . 0 . read ( ) . await . status
81
+ impl < T > State < T >
82
+ where
83
+ T : WifiConfigurator ,
84
+ {
85
+ async fn status ( & self ) -> Status {
86
+ self . inner . read ( ) . await . status
80
87
}
81
88
82
- pub async fn last_error ( & self ) -> Option < Error > {
83
- self . 0 . read ( ) . await . last_error
89
+ async fn last_error ( & self ) -> Option < Error > {
90
+ self . inner . read ( ) . await . last_error
84
91
}
85
92
86
- pub async fn set_status ( & self , new : Status ) {
87
- self . 0 . write ( ) . await . status = new;
93
+ async fn set_status ( & self , new : Status ) {
94
+ self . inner . write ( ) . await . status = new;
88
95
}
89
96
90
- pub async fn set_last_error ( & self , new : Option < Error > ) {
91
- self . 0 . write ( ) . await . last_error = new;
97
+ async fn set_last_error ( & self , new : Option < Error > ) {
98
+ self . inner . write ( ) . await . last_error = new;
92
99
}
93
- }
94
-
95
- #[ derive( Debug ) ]
96
- pub struct ImprovWifi < T > {
97
- timeout : Option < Duration > ,
98
- state : State ,
99
- handler : T ,
100
- status_change_notifier : Sender < ( ) > ,
101
- error_change_notifier : Sender < ( ) > ,
102
- app : ApplicationHandle ,
103
- service : ServiceControl ,
104
- capabilities : CharacteristicControl ,
105
- current_state : CharacteristicControl ,
106
- error_state : CharacteristicControl ,
107
- rpc_command : CharacteristicControl ,
108
- rpc_result : CharacteristicControl ,
109
- }
110
-
111
- pub trait WifiConfigurator {
112
- fn can_authorize ( ) -> bool ;
113
- fn can_identify ( ) -> bool ;
114
- async fn provision ( & mut self ) -> std:: result:: Result < ( ) , Error > ;
115
- }
116
100
117
- impl < T : WifiConfigurator > ImprovWifi < T > {
118
- async fn modify_status ( & mut self , status : Status ) {
119
- self . state . set_status ( status) . await ;
101
+ async fn modify_status ( & self , status : Status ) {
102
+ self . set_status ( status) . await ;
120
103
self . status_change_notifier . send ( ( ) ) . ok ( ) ;
121
104
// TODO: pro-actively write to the client???
122
105
}
123
106
124
- pub async fn set_error ( & mut self , error : Error ) {
125
- self . state . set_last_error ( Some ( error) ) . await ;
107
+ pub async fn set_error ( & self , error : Error ) {
108
+ self . set_last_error ( Some ( error) ) . await ;
126
109
self . error_change_notifier . send ( ( ) ) . ok ( ) ;
127
110
// TODO: pro-actively write to the client???
128
111
}
129
112
130
- pub async fn clear_error ( & mut self ) {
131
- self . state . set_last_error ( None ) . await ;
113
+ pub async fn clear_error ( & self ) {
114
+ self . set_last_error ( None ) . await ;
132
115
self . error_change_notifier . send ( ( ) ) . ok ( ) ;
133
116
// TODO: pro-actively write to the client???
134
117
}
135
118
136
- pub async fn set_authorized ( & mut self ) {
137
- if self . state . status ( ) . await == Status :: AuthorizationRequired {
119
+ pub async fn set_authorized ( & self ) {
120
+ if self . status ( ) . await == Status :: AuthorizationRequired {
138
121
self . modify_status ( Status :: Authorized ) . await ;
139
122
}
140
123
}
141
124
142
125
pub async fn provision ( & mut self ) {
143
- if self . state . status ( ) . await != Status :: Authorized {
126
+ if self . status ( ) . await != Status :: Authorized {
144
127
self . set_error ( Error :: NotAuthorized ) . await ;
145
128
return ;
146
129
}
@@ -158,19 +141,80 @@ impl<T: WifiConfigurator> ImprovWifi<T> {
158
141
self . modify_status ( Status :: Provisioned ) . await ;
159
142
}
160
143
144
+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
145
+ pub async fn handle_raw_rpc ( & self , value : Vec < u8 > ) {
146
+ if let Err ( error) = Self :: inner_handle_raw_rpc ( & self , value) . await {
147
+ self . set_error ( error) . await ;
148
+ } else {
149
+ self . clear_error ( ) . await ;
150
+ }
151
+ }
152
+
153
+ async fn inner_handle_raw_rpc ( & self , value : Vec < u8 > ) -> std:: result:: Result < ( ) , Error > {
154
+ let rpc = rpc:: Rpc :: parse ( & value) . map_err ( |err| {
155
+ tracing:: error!( "Failed to parse RPC: {}" , err) ;
156
+ Error :: InvalidRPC
157
+ } ) ?;
158
+
159
+ todo ! ( )
160
+ }
161
+
162
+ pub fn set_timeout ( & mut self , timeout : Duration ) {
163
+ if T :: can_authorize ( ) {
164
+ self . timeout = Some ( timeout) ;
165
+ }
166
+ }
167
+ }
168
+
169
+ #[ derive( Debug ) ]
170
+ pub struct ImprovWifi < T > {
171
+ state : State < T > ,
172
+ app : ApplicationHandle ,
173
+ service : ServiceControl ,
174
+ capabilities : CharacteristicControl ,
175
+ current_state : CharacteristicControl ,
176
+ error_state : CharacteristicControl ,
177
+ rpc_command : CharacteristicControl ,
178
+ rpc_result : CharacteristicControl ,
179
+ }
180
+
181
+ pub trait WifiConfigurator : Clone + Send + Sync + ' static {
182
+ fn can_authorize ( ) -> bool ;
183
+ fn can_identify ( ) -> bool ;
184
+ async fn provision ( & mut self ) -> std:: result:: Result < ( ) , Error > ;
185
+ }
186
+
187
+ impl < T > ImprovWifi < T >
188
+ where
189
+ T : WifiConfigurator ,
190
+ {
191
+ pub fn set_timeout ( & mut self , timeout : Duration ) {
192
+ self . state . set_timeout ( timeout) ;
193
+ }
194
+
161
195
pub async fn install ( adapter : & Adapter , handler : T ) -> Result < Self > {
162
196
let initial_status = if T :: can_authorize ( ) {
163
197
Status :: AuthorizationRequired
164
198
} else {
165
199
Status :: Authorized
166
200
} ;
167
201
168
- let state = State :: new ( InnerState {
169
- status : initial_status,
170
- last_error : None ,
171
- } ) ;
172
202
let ( status_change_notifier, _) = broadcast_channel ( 2 ) ;
173
203
let ( error_change_notifier, _) = broadcast_channel ( 2 ) ;
204
+ let state = State {
205
+ inner : Arc :: new ( RwLock :: new ( InnerState {
206
+ status : initial_status,
207
+ last_error : None ,
208
+ } ) ) ,
209
+ status_change_notifier : status_change_notifier. clone ( ) ,
210
+ error_change_notifier : error_change_notifier. clone ( ) ,
211
+ timeout : if initial_status == Status :: AuthorizationRequired {
212
+ Some ( Duration :: from_secs ( 60 ) )
213
+ } else {
214
+ None
215
+ } ,
216
+ handler,
217
+ } ;
174
218
175
219
let ( service, service_handle) = service_control ( ) ;
176
220
let ( capabilities_control, capabilities_handle) = characteristic_control ( ) ;
@@ -289,6 +333,22 @@ impl<T: WifiConfigurator> ImprovWifi<T> {
289
333
} ,
290
334
Characteristic {
291
335
uuid: CHARACTERISTIC_UUID_RPC_COMMAND ,
336
+ write: Some ( CharacteristicWrite {
337
+ write: true ,
338
+ write_without_response: true ,
339
+ method: CharacteristicWriteMethod :: Fun ( Box :: new( {
340
+ let state = state. clone( ) ;
341
+ move |value, _req| {
342
+ let state = state. clone( ) ;
343
+ Box :: pin( async move {
344
+ // not sure if the bluer interface here will stitch writes together, let's ignore that for now
345
+ state. handle_raw_rpc( value) . await ;
346
+ Ok ( ( ) )
347
+ } )
348
+ }
349
+ } ) ) ,
350
+ ..Default :: default ( )
351
+ } ) ,
292
352
control_handle: rpc_command_handle,
293
353
..Default :: default ( )
294
354
} ,
@@ -305,15 +365,7 @@ impl<T: WifiConfigurator> ImprovWifi<T> {
305
365
} ;
306
366
307
367
Ok ( ImprovWifi {
308
- timeout : if initial_status == Status :: AuthorizationRequired {
309
- Some ( Duration :: from_secs ( 60 ) )
310
- } else {
311
- None
312
- } ,
313
368
state,
314
- handler,
315
- status_change_notifier,
316
- error_change_notifier,
317
369
app : adapter. serve_gatt_application ( app) . await ?,
318
370
service,
319
371
capabilities : capabilities_control,
@@ -323,10 +375,4 @@ impl<T: WifiConfigurator> ImprovWifi<T> {
323
375
rpc_result : rpc_result_control,
324
376
} )
325
377
}
326
-
327
- pub fn set_timeout ( & mut self , timeout : Duration ) {
328
- if T :: can_authorize ( ) {
329
- self . timeout = Some ( timeout) ;
330
- }
331
- }
332
378
}
0 commit comments