33
33
34
34
STATIC const mp_obj_type_t bluetooth_type ;
35
35
STATIC const mp_obj_type_t service_type ;
36
+ STATIC const mp_obj_type_t characteristic_type ;
36
37
37
38
typedef struct _mp_obj_bluetooth_t {
38
39
mp_obj_base_t base ;
@@ -53,7 +54,7 @@ STATIC mp_obj_t bluetooth_handle_errno(int errno_) {
53
54
}
54
55
55
56
// Parse string UUIDs, which are probably 128-bit UUIDs.
56
- void bluetooth_parse_uuid_str (mp_obj_t obj , uint8_t * uuid ) {
57
+ void mp_bt_parse_uuid_str (mp_obj_t obj , uint8_t * uuid ) {
57
58
GET_STR_DATA_LEN (obj , str_data , str_len );
58
59
int uuid_i = 32 ;
59
60
for (int i = 0 ; i < str_len ; i ++ ) {
@@ -87,7 +88,36 @@ void bluetooth_parse_uuid_str(mp_obj_t obj, uint8_t *uuid) {
87
88
}
88
89
}
89
90
90
- STATIC mp_obj_t bluetooth_make_new () {
91
+ // Format string UUID. Example output:
92
+ // '6e400001-b5a3-f393-e0a9-e50e24dcca9e'
93
+ mp_obj_t mp_bt_format_uuid_str (uint8_t * uuid ) {
94
+ char str [36 ];
95
+ char * s = str ;
96
+ for (int i = 15 ; i >= 0 ; i -- ) {
97
+ char nibble = uuid [i ] >> 4 ;
98
+ if (nibble >= 10 ) {
99
+ nibble += 'a' - 10 ;
100
+ } else {
101
+ nibble += '0' ;
102
+ }
103
+ * (s ++ ) = nibble ;
104
+
105
+ nibble = uuid [i ] & 0xf ;
106
+ if (nibble >= 10 ) {
107
+ nibble += 'a' - 10 ;
108
+ } else {
109
+ nibble += '0' ;
110
+ }
111
+ * (s ++ ) = nibble ;
112
+
113
+ if (i == 12 || i == 10 || i == 8 || i == 6 ) {
114
+ * (s ++ ) = '-' ;
115
+ }
116
+ }
117
+ return mp_obj_new_str (str , MP_ARRAY_SIZE (str ));
118
+ }
119
+
120
+ STATIC mp_obj_t bluetooth_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
91
121
return MP_OBJ_FROM_PTR (& bluetooth_obj );
92
122
}
93
123
@@ -204,32 +234,130 @@ STATIC mp_obj_t bluetooth_advertise_raw(size_t n_args, const mp_obj_t *pos_args,
204
234
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (bluetooth_advertise_raw_obj , 1 , bluetooth_advertise_raw );
205
235
206
236
STATIC mp_obj_t bluetooth_add_service (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
207
- enum { ARG_interval , ARG_adv_data , ARG_sr_data , ARG_connectable };
237
+ enum { ARG_uuid , ARG_characteristics };
208
238
static const mp_arg_t allowed_args [] = {
209
- { MP_QSTR_uuid , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = mp_const_none } },
239
+ { MP_QSTR_uuid , MP_ARG_OBJ | MP_ARG_REQUIRED },
240
+ { MP_QSTR_characteristics , MP_ARG_OBJ | MP_ARG_REQUIRED },
210
241
};
211
242
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
212
243
mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
213
244
245
+ mp_obj_list_t * characteristics = args [ARG_characteristics ].u_obj ;
246
+ if (characteristics == NULL || !mp_obj_is_type (args [ARG_characteristics ].u_obj , & mp_type_list )) {
247
+ mp_raise_ValueError ("characteristics must be a list" );
248
+ }
249
+ for (int i = 0 ; i < characteristics -> len ; i ++ ) {
250
+ mp_obj_t characteristic = characteristics -> items [i ];
251
+ if (characteristic == NULL || !mp_obj_is_type (characteristic , & characteristic_type )) {
252
+ mp_raise_ValueError ("not a Characteristic" );
253
+ }
254
+ if (((mp_bt_characteristic_t * )characteristic )-> service != NULL ) {
255
+ mp_raise_ValueError ("Characteristic already added to Service" );
256
+ }
257
+ }
258
+
214
259
mp_bt_service_t * service = m_new_obj (mp_bt_service_t );
215
260
service -> base .type = & service_type ;
216
- bluetooth_parse_uuid (args [0 ].u_obj , & service -> uuid );
217
- int errno_ = mp_bt_add_service (service );
261
+ mp_bt_parse_uuid (args [ARG_uuid ].u_obj , & service -> uuid );
262
+ int errno_ = mp_bt_add_service (service , characteristics -> len , ( mp_bt_characteristic_t * * ) characteristics -> items );
218
263
bluetooth_handle_errno (errno_ );
219
264
return service ;
220
265
}
221
266
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (bluetooth_add_service_obj , 1 , bluetooth_add_service );
222
267
268
+ STATIC mp_obj_t service_uuid (mp_obj_t self_in ) {
269
+ mp_bt_service_t * service = self_in ;
270
+ return mp_bt_format_uuid (& service -> uuid );
271
+ }
272
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (service_uuid_obj , service_uuid );
273
+
274
+ STATIC const mp_rom_map_elem_t service_locals_dict_table [] = {
275
+ { MP_ROM_QSTR (MP_QSTR_uuid ), MP_ROM_PTR (& service_uuid_obj ) },
276
+ };
277
+ STATIC MP_DEFINE_CONST_DICT (service_locals_dict , service_locals_dict_table );
278
+
223
279
STATIC const mp_obj_type_t service_type = {
224
280
{ & mp_type_type },
225
281
.name = MP_QSTR_Service ,
282
+ .locals_dict = (void * )& service_locals_dict ,
283
+ };
284
+
285
+ STATIC mp_obj_t characteristic_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
286
+ enum { ARG_uuid , ARG_flags };
287
+ static const mp_arg_t allowed_args [] = {
288
+ { MP_QSTR_uuid , MP_ARG_OBJ | MP_ARG_REQUIRED },
289
+ { MP_QSTR_flags , MP_ARG_INT | MP_ARG_REQUIRED },
290
+ };
291
+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
292
+ mp_arg_parse_all_kw_array (n_args , n_kw , all_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
293
+
294
+ if ((uint8_t )(args [ARG_flags ].u_int ) != args [ARG_flags ].u_int ) {
295
+ // Flags don't fit in 8 bits.
296
+ mp_raise_ValueError ("invalid flags" );
297
+ }
298
+
299
+ mp_bt_characteristic_t * characteristic = m_new_obj (mp_bt_characteristic_t );
300
+ characteristic -> base .type = & characteristic_type ;
301
+ mp_bt_parse_uuid (args [0 ].u_obj , & characteristic -> uuid );
302
+ characteristic -> flags = (uint8_t )(args [ARG_flags ].u_int );
303
+ return characteristic ;
304
+ }
305
+
306
+ STATIC mp_obj_t characteristic_service (mp_obj_t self_in ) {
307
+ mp_bt_characteristic_t * characteristic = self_in ;
308
+ if (characteristic -> service == NULL ) {
309
+ return mp_const_none ;
310
+ }
311
+ return characteristic -> service ;
312
+ }
313
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (characteristic_service_obj , characteristic_service );
314
+
315
+ STATIC mp_obj_t characteristic_uuid (mp_obj_t self_in ) {
316
+ mp_bt_characteristic_t * characteristic = self_in ;
317
+ return mp_bt_format_uuid (& characteristic -> uuid );
318
+ }
319
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (characteristic_uuid_obj , characteristic_uuid );
320
+
321
+ STATIC mp_obj_t characteristic_write (mp_obj_t self_in , mp_obj_t value_in ) {
322
+ mp_bt_characteristic_t * characteristic = self_in ;
323
+ GET_STR_DATA_LEN (value_in , str_data , str_len );
324
+ int errno_ = mp_bt_characteristic_value_set (characteristic -> value_handle , str_data , str_len );
325
+ return bluetooth_handle_errno (errno_ );
326
+ }
327
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (characteristic_write_obj , characteristic_write );
328
+
329
+ STATIC mp_obj_t characteristic_read (mp_obj_t self_in ) {
330
+ mp_bt_characteristic_t * characteristic = self_in ;
331
+ uint8_t data [MP_BT_MAX_ATTR_SIZE ];
332
+ size_t value_len = MP_BT_MAX_ATTR_SIZE ;
333
+ int errno_ = mp_bt_characteristic_value_get (characteristic -> value_handle , data , & value_len );
334
+ if (errno_ != 0 ) {
335
+ mp_raise_OSError (errno_ );
336
+ }
337
+ return mp_obj_new_bytes (data , value_len );
338
+ }
339
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (characteristic_read_obj , characteristic_read );
340
+
341
+ STATIC const mp_rom_map_elem_t characteristic_locals_dict_table [] = {
342
+ { MP_ROM_QSTR (MP_QSTR_service ), MP_ROM_PTR (& characteristic_service_obj ) },
343
+ { MP_ROM_QSTR (MP_QSTR_uuid ), MP_ROM_PTR (& characteristic_uuid_obj ) },
344
+ { MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& characteristic_write_obj ) },
345
+ { MP_ROM_QSTR (MP_QSTR_read ), MP_ROM_PTR (& characteristic_read_obj ) },
346
+ };
347
+ STATIC MP_DEFINE_CONST_DICT (characteristic_locals_dict , characteristic_locals_dict_table );
348
+
349
+ STATIC const mp_obj_type_t characteristic_type = {
350
+ { & mp_type_type },
351
+ .name = MP_QSTR_Characteristic ,
352
+ .make_new = characteristic_make_new ,
353
+ .locals_dict = (void * )& characteristic_locals_dict ,
226
354
};
227
355
228
356
STATIC const mp_rom_map_elem_t bluetooth_locals_dict_table [] = {
229
- { MP_ROM_QSTR (MP_QSTR_active ), MP_ROM_PTR (& bluetooth_active_obj ) },
230
- { MP_ROM_QSTR (MP_QSTR_advertise ), MP_ROM_PTR (& bluetooth_advertise_obj ) },
357
+ { MP_ROM_QSTR (MP_QSTR_active ), MP_ROM_PTR (& bluetooth_active_obj ) },
358
+ { MP_ROM_QSTR (MP_QSTR_advertise ), MP_ROM_PTR (& bluetooth_advertise_obj ) },
231
359
{ MP_ROM_QSTR (MP_QSTR_advertise_raw ), MP_ROM_PTR (& bluetooth_advertise_raw_obj ) },
232
- { MP_ROM_QSTR (MP_QSTR_add_service ), MP_ROM_PTR (& bluetooth_add_service_obj ) },
360
+ { MP_ROM_QSTR (MP_QSTR_add_service ), MP_ROM_PTR (& bluetooth_add_service_obj ) },
233
361
};
234
362
STATIC MP_DEFINE_CONST_DICT (bluetooth_locals_dict , bluetooth_locals_dict_table );
235
363
@@ -241,9 +369,13 @@ STATIC const mp_obj_type_t bluetooth_type = {
241
369
};
242
370
243
371
STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table [] = {
244
- { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_bluetooth ) },
245
- { MP_ROM_QSTR (MP_QSTR_Bluetooth ), MP_ROM_PTR (& bluetooth_type ) },
246
- { MP_ROM_QSTR (MP_QSTR_Service ), MP_ROM_PTR (& service_type ) },
372
+ { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_bluetooth ) },
373
+ { MP_ROM_QSTR (MP_QSTR_Bluetooth ), MP_ROM_PTR (& bluetooth_type ) },
374
+ { MP_ROM_QSTR (MP_QSTR_Service ), MP_ROM_PTR (& service_type ) },
375
+ { MP_ROM_QSTR (MP_QSTR_Characteristic ), MP_ROM_PTR (& characteristic_type ) },
376
+ { MP_ROM_QSTR (MP_QSTR_FLAG_READ ), MP_ROM_INT (MP_BLE_FLAG_READ ) },
377
+ { MP_ROM_QSTR (MP_QSTR_FLAG_WRITE ), MP_ROM_INT (MP_BLE_FLAG_WRITE ) },
378
+ { MP_ROM_QSTR (MP_QSTR_FLAG_NOTIFY ), MP_ROM_INT (MP_BLE_FLAG_NOTIFY ) },
247
379
};
248
380
STATIC MP_DEFINE_CONST_DICT (mp_module_bluetooth_globals , mp_module_bluetooth_globals_table );
249
381
0 commit comments