@@ -10,6 +10,7 @@ use trouble_host::attribute::Characteristic;
10
10
use trouble_host:: gatt:: GattEvent ;
11
11
use trouble_host:: prelude:: * ;
12
12
13
+ use crate :: device:: Battery ;
13
14
use crate :: DfuConfig ;
14
15
15
16
pub const ATT_MTU : usize = L2CAP_MTU - 4 - 3 ;
@@ -39,6 +40,16 @@ impl NrfUartService {
39
40
}
40
41
*/
41
42
43
+ // Battery service
44
+ #[ gatt_service( uuid = service:: BATTERY ) ]
45
+ struct BatteryService {
46
+ /// Battery Level
47
+ #[ descriptor( uuid = descriptors:: VALID_RANGE , read, value = [ 0 , 100 ] ) ]
48
+ #[ descriptor( uuid = descriptors:: MEASUREMENT_DESCRIPTION , read, value = "Battery Level" ) ]
49
+ #[ characteristic( uuid = characteristic:: BATTERY_LEVEL , read, notify) ]
50
+ level : u8 ,
51
+ }
52
+
42
53
#[ gatt_service( uuid = "FE59" ) ]
43
54
pub struct NrfDfuService {
44
55
#[ characteristic( uuid = "8EC90001-F315-4F60-9FB8-838830DAEA50" , write, notify) ]
@@ -51,25 +62,27 @@ pub struct NrfDfuService {
51
62
packet : Vec < u8 , ATT_MTU > ,
52
63
}
53
64
54
- #[ gatt_service( uuid = "23D1BCEA-5F78-2315-DEEF-121230150000" ) ]
55
- pub struct InfinitimeDfuService {
56
- #[ characteristic( uuid = "23D1BCEA-5F78-2315-DEEF-121231150000" , write, notify) ]
57
- control : Vec < u8 , ATT_MTU > ,
58
-
59
- #[ characteristic( uuid = "23D1BCEA-5F78-2315-DEEF-121231150000" , read) ] //, value = "8")]
60
- revision : u16 ,
61
-
62
- /// The maximum size of each packet is derived from the Att MTU size of the connection.
63
- /// The maximum Att MTU size of the DFU Service is 256 bytes (saved in NRF_SDH_BLE_GATT_MAX_MTU_SIZE),
64
- /// making the maximum size of the DFU Packet characteristic 253 bytes. (3 bytes are used for opcode and handle ID upon writing.)
65
- #[ characteristic( uuid = "23D1BCEA-5F78-2315-DEEF-121232150000" , write_without_response) ]
66
- packet : Vec < u8 , ATT_MTU > ,
67
- }
65
+ // NOTE: Disabled as it doesn't properly deal with init/start specific to infinitime protocol
66
+ //#[gatt_service(uuid = "23D1BCEA-5F78-2315-DEEF-121230150000")]
67
+ //pub struct InfinitimeDfuService {
68
+ // #[characteristic(uuid = "23D1BCEA-5F78-2315-DEEF-121231150000", write, notify)]
69
+ // control: Vec<u8, ATT_MTU>,
70
+ //
71
+ // #[characteristic(uuid = "23D1BCEA-5F78-2315-DEEF-121234150000", read, value = 8)]
72
+ // revision: u16,
73
+ //
74
+ // /// The maximum size of each packet is derived from the Att MTU size of the connection.
75
+ // /// The maximum Att MTU size of the DFU Service is 256 bytes (saved in NRF_SDH_BLE_GATT_MAX_MTU_SIZE),
76
+ // /// making the maximum size of the DFU Packet characteristic 253 bytes. (3 bytes are used for opcode and handle ID upon writing.)
77
+ // #[characteristic(uuid = "23D1BCEA-5F78-2315-DEEF-121232150000", write_without_response)]
78
+ // packet: Vec<u8, ATT_MTU>,
79
+ //}
68
80
69
81
#[ gatt_server]
70
82
pub struct PineTimeServer {
71
83
nrfdfu : NrfDfuService ,
72
- infdfu : InfinitimeDfuService ,
84
+ battery : BatteryService ,
85
+ // infdfu: InfinitimeDfuService,
73
86
// uart: NrfUartService,
74
87
}
75
88
@@ -135,17 +148,17 @@ impl PineTimeServer<'_> {
135
148
if handle == self . nrfdfu . control . handle {
136
149
self . handle_dfu_control ( target, dfu, connection, & self . nrfdfu . control )
137
150
. await
138
- } else if handle == self . infdfu . control . handle {
139
- self . handle_dfu_control ( target, dfu, connection, & self . infdfu . control )
140
- . await
151
+ // } else if handle == self.infdfu.control.handle {
152
+ // self.handle_dfu_control(target, dfu, connection, &self.infdfu.control)
153
+ // .await
141
154
} else if handle == self . nrfdfu . packet . handle {
142
155
self . handle_dfu_packet ( target, dfu, connection, & self . nrfdfu . control , & self . nrfdfu . packet )
143
156
. await
144
- } else if handle == self . infdfu . packet . handle {
145
- self . handle_dfu_packet ( target, dfu, connection, & self . infdfu . control , & self . infdfu . packet )
146
- . await
157
+ // } else if handle == self.infdfu.packet.handle {
158
+ // self.handle_dfu_packet(target, dfu, connection, &self.infdfu.control, &self.infdfu.packet)
159
+ // .await
147
160
} else {
148
- warn ! ( "unknown handle {}!" , handle) ;
161
+ // Ignore, no need to handle
149
162
None
150
163
}
151
164
}
@@ -171,7 +184,12 @@ fn ble_addr() -> Address {
171
184
172
185
const NAME : & str = "Watchful" ;
173
186
174
- pub fn start ( spawner : Spawner , controller : NrfController , dfu_config : DfuConfig < ' static > ) {
187
+ pub fn start (
188
+ spawner : Spawner ,
189
+ controller : NrfController ,
190
+ dfu_config : DfuConfig < ' static > ,
191
+ battery : & ' static Battery < ' static > ,
192
+ ) {
175
193
let resources = RESOURCES . init ( BleResources :: new ( ) ) ;
176
194
let stack = STACK . init ( trouble_host:: new ( controller, resources) . set_random_address ( ble_addr ( ) ) ) ;
177
195
@@ -187,7 +205,7 @@ pub fn start(spawner: Spawner, controller: NrfController, dfu_config: DfuConfig<
187
205
let server = SERVER . init ( gatt) ;
188
206
189
207
spawner. must_spawn ( ble_task ( runner) ) ;
190
- spawner. must_spawn ( advertise_task ( stack, peripheral, server, dfu_config) ) ;
208
+ spawner. must_spawn ( advertise_task ( stack, peripheral, server, dfu_config, battery ) ) ;
191
209
}
192
210
193
211
#[ embassy_executor:: task]
@@ -201,12 +219,15 @@ async fn advertise_task(
201
219
mut peripheral : Peripheral < ' static , NrfController > ,
202
220
server : & ' static PineTimeServer < ' static > ,
203
221
mut dfu_config : DfuConfig < ' static > ,
222
+ battery : & ' static Battery < ' static > ,
204
223
) {
224
+ const BAS : [ u8 ; 2 ] = [ 0x0F , 0x18 ] ;
225
+ const DFU : [ u8 ; 2 ] = [ 0x59 , 0xFE ] ;
205
226
let mut advertiser_data = [ 0 ; 31 ] ;
206
227
unwrap ! ( AdStructure :: encode_slice(
207
228
& [
208
229
AdStructure :: Flags ( LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED ) ,
209
- AdStructure :: ServiceUuids16 ( & [ Uuid :: Uuid16 ( [ 0x59 , 0xFE ] ) ] ) ,
230
+ AdStructure :: ServiceUuids16 ( & [ Uuid :: Uuid16 ( BAS ) , Uuid :: Uuid16 ( DFU ) ] ) ,
210
231
AdStructure :: CompleteLocalName ( NAME . as_bytes( ) ) ,
211
232
] ,
212
233
& mut advertiser_data[ ..] ,
@@ -225,7 +246,7 @@ async fn advertise_task(
225
246
. await
226
247
) ;
227
248
match advertiser. accept ( ) . await {
228
- Ok ( conn) => process ( stack, conn, server, & mut dfu_config) . await ,
249
+ Ok ( conn) => process ( stack, conn, server, & mut dfu_config, battery ) . await ,
229
250
Err ( e) => {
230
251
warn ! ( "Error advertising: {:?}" , e) ;
231
252
}
@@ -238,6 +259,7 @@ async fn process(
238
259
connection : Connection < ' static > ,
239
260
server : & ' static PineTimeServer < ' _ > ,
240
261
dfu_config : & mut DfuConfig < ' static > ,
262
+ battery : & ' static Battery < ' static > ,
241
263
) {
242
264
let ficr = embassy_nrf:: pac:: FICR ;
243
265
let part = ficr. info ( ) . part ( ) . read ( ) . part ( ) . to_bits ( ) ;
@@ -273,6 +295,17 @@ async fn process(
273
295
break ;
274
296
}
275
297
ConnectionEvent :: Gatt { data } => match data. process ( server) . await {
298
+ Ok ( Some ( GattEvent :: Read ( event) ) ) => {
299
+ let handle = event. handle ( ) ;
300
+ if handle == server. battery . level . handle {
301
+ let value = battery. measure ( ) . await . max ( 100 ) as u8 ;
302
+ if let Err ( _) = server. battery . level . set ( server, & value) {
303
+ warn ! ( "error updating battery level" ) ;
304
+ }
305
+ }
306
+ let reply = unwrap ! ( event. accept( ) ) ;
307
+ reply. send ( ) . await ;
308
+ }
276
309
Ok ( Some ( GattEvent :: Write ( event) ) ) => {
277
310
let handle = event. handle ( ) ;
278
311
let reply = unwrap ! ( event. accept( ) ) ;
0 commit comments