diff options
| author | Dan Halbert <halbert@halwitz.org> | 2018-12-07 16:52:47 -0500 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2018-12-07 16:52:47 -0500 |
| commit | a7a24096f469b1ee95242d4e7f58929cad3699ed (patch) | |
| tree | f2f98994844c47d837fcdf8eeb4ca8c9696d34bb /shared-bindings | |
| parent | 125901e4e20cfbdef8b8a0a71b424d1545b203b1 (diff) | |
bleio WIP: redo for more immutability; use sd_* routines for internal flash write
Diffstat (limited to 'shared-bindings')
| -rw-r--r-- | shared-bindings/bleio/Characteristic.c | 191 | ||||
| -rw-r--r-- | shared-bindings/bleio/Service.c | 88 |
2 files changed, 111 insertions, 168 deletions
diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 68d70700f..4fb71de47 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -38,63 +38,13 @@ //| Stores information about a BLE service characteristic and allows to read //| and write the characteristic's value. //| - -//| .. class:: Characteristic(uuid) -//| -//| Create a new Characteristic object identified by the specified UUID. -//| -//| :param bleio.UUID uuid: The uuid of the characteristic -//| - -//| .. attribute:: broadcast -//| -//| A `bool` specifying if the characteristic allows broadcasting its value. -//| - -//| .. attribute:: indicate -//| -//| A `bool` specifying if the characteristic allows indicating its value. -//| - -//| .. attribute:: notify -//| -//| A `bool` specifying if the characteristic allows notifying its value. -//| - -//| .. attribute:: read -//| -//| A `bool` specifying if the characteristic allows reading its value. -//| - -//| .. attribute:: uuid -//| -//| The UUID of this characteristic. (read-only) -//| - -//| .. attribute:: value -//| -//| The value of this characteristic. The value can be written to if the `write` property allows it. -//| If the `read` property allows it, the value can be read. If the `notify` property is set, writting -//| to the value will generate a BLE notification. -//| - -//| .. attribute:: write //| -//| A `bool` specifying if the characteristic allows writing to its value. +//| .. class:: Characteristic(uuid, *, broadcast=False, indicate=False, notify=False, read=False, write=False, write_no_response=False) //| - -//| .. attribute:: write_no_resp +//| Create a new Characteristic object identified by the specified UUID. //| -//| A `bool` specifying if the characteristic allows writing to its value without response. +//| :param bleio.UUID uuid: The uuid of the characteristic (read_only) //| -STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - mp_printf(print, "Characteristic("); - bleio_uuid_print(print, self->uuid, kind); - mp_printf(print, ")"); -} - STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { mp_arg_check_num(n_args, n_kw, 1, 1, true); bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); @@ -105,9 +55,15 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_uuid }; + enum { ARG_uuid, ARG_broadcast, ARG_indicate, ARG_notify, ARG_read, ARG_write, ARG_write_no_response }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_uuid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_broadcast, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_indicate, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_notify, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_read, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_write, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_write_no_response, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -120,34 +76,49 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t } self->uuid = MP_OBJ_TO_PTR(uuid); + + self->props.broadcast = args[ARG_broadcast].u_bool; + self->props.indicate = args[ARG_indicate].u_bool; + self->props.notify = args[ARG_notify].u_bool; + self->props.read = args[ARG_read].u_bool; + self->props.write = args[ARG_write].u_bool; + self->props.write_no_response = args[ARG_write_no_response].u_bool; + common_hal_bleio_characteristic_construct(self); return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { +STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool(self->props.broadcast); + mp_printf(print, "Characteristic("); + bleio_uuid_print(print, self->uuid, kind); + mp_printf(print, ")"); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); -STATIC mp_obj_t bleio_characteristic_set_broadcast(mp_obj_t self_in, mp_obj_t broadcast_in) { +//| .. attribute:: broadcast +//| +//| A `bool` specifying if the characteristic allows broadcasting its value. (read-only) +//| +STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->props.broadcast = mp_obj_is_true(broadcast_in); - - return mp_const_none; + return mp_obj_new_bool(self->props.broadcast); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_broadcast_obj, bleio_characteristic_set_broadcast); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); const mp_obj_property_t bleio_characteristic_broadcast_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj, - (mp_obj_t)&bleio_characteristic_set_broadcast_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: indicate +//| +//| A `bool` specifying if the characteristic allows indicating its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -155,22 +126,18 @@ STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate); -STATIC mp_obj_t bleio_characteristic_set_indicate(mp_obj_t self_in, mp_obj_t indicate_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.indicate = mp_obj_is_true(indicate_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_indicate_obj, bleio_characteristic_set_indicate); const mp_obj_property_t bleio_characteristic_indicate_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj, - (mp_obj_t)&bleio_characteristic_set_indicate_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: notify +//| +//| A `bool` specifying if the characteristic allows notifying its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -178,22 +145,17 @@ STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify); -STATIC mp_obj_t bleio_characteristic_set_notify(mp_obj_t self_in, mp_obj_t notify_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.notify = mp_obj_is_true(notify_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_notify_obj, bleio_characteristic_set_notify); - const mp_obj_property_t bleio_characteristic_notify_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj, - (mp_obj_t)&bleio_characteristic_set_notify_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: read +//| +//| A `bool` specifying if the characteristic allows reading its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -201,22 +163,17 @@ STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read); -STATIC mp_obj_t bleio_characteristic_set_read(mp_obj_t self_in, mp_obj_t read_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.read = mp_obj_is_true(read_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_read_obj, bleio_characteristic_set_read); - const mp_obj_property_t bleio_characteristic_read_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj, - (mp_obj_t)&bleio_characteristic_set_read_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: write +//| +//| A `bool` specifying if the characteristic allows writing to its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -224,45 +181,35 @@ STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write); -STATIC mp_obj_t bleio_characteristic_set_write(mp_obj_t self_in, mp_obj_t write_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.write = mp_obj_is_true(write_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_obj, bleio_characteristic_set_write); - const mp_obj_property_t bleio_characteristic_write_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj, - (mp_obj_t)&bleio_characteristic_set_write_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; -STATIC mp_obj_t bleio_characteristic_get_write_wo_resp(mp_obj_t self_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_bool(self->props.write_wo_resp); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_wo_resp_obj, bleio_characteristic_get_write_wo_resp); - -STATIC mp_obj_t bleio_characteristic_set_write_wo_resp(mp_obj_t self_in, mp_obj_t write_wo_resp_in) { +//| .. attribute:: write_no_response +//| +//| A `bool` specifying if the characteristic allows writing to its value without response. (read-only) +//| +STATIC mp_obj_t bleio_characteristic_get_write_no_response(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->props.write_wo_resp = mp_obj_is_true(write_wo_resp_in); - - return mp_const_none; + return mp_obj_new_bool(self->props.write_no_response); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_wo_resp_obj, bleio_characteristic_set_write_wo_resp); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_no_response_obj, bleio_characteristic_get_write_no_response); -const mp_obj_property_t bleio_characteristic_write_wo_resp_obj = { +const mp_obj_property_t bleio_characteristic_write_no_response_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_characteristic_get_write_wo_resp_obj, - (mp_obj_t)&bleio_characteristic_set_write_wo_resp_obj, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_no_response_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: uuid +//| +//| The UUID of this characteristic. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -277,6 +224,12 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: value +//| +//| The value of this characteristic. The value can be written to if the `write` property allows it. +//| If the `read` property allows it, the value can be read. If the `notify` property is set, writing +//| to the value will generate a BLE notification. +//| STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -313,7 +266,7 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_write_wo_resp), MP_ROM_PTR(&bleio_characteristic_write_wo_resp_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_no_response), MP_ROM_PTR(&bleio_characteristic_write_no_response_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table); diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index 0326d6ba7..129a1d0b7 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -27,6 +27,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" @@ -38,7 +39,7 @@ //| Stores information about a BLE service and its characteristics. //| -//| .. class:: Service(uuid, secondary=False) +//| .. class:: Service(uuid, characteristics, *, secondary=False) //| //| Create a new Service object identified by the specified UUID. //| To mark the service as secondary, pass `True` as :py:data:`secondary`. @@ -47,22 +48,6 @@ //| :param bool secondary: If the service is a secondary one //| -//| .. method:: add_characteristic(characteristic) -//| -//| Appends the :py:data:`characteristic` to the list of this service's characteristics. -//| -//| :param bleio.Characteristic characteristic: the characteristic to append -//| - -//| .. attribute:: characteristics -//| -//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) -//| - -//| .. attribute:: uuid -//| -//| The UUID of this service. (read-only) -//| STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -72,19 +57,20 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr } STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 1, 1, true); + mp_arg_check_num(n_args, n_kw, 2, 3, true); bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t); + self->char_list = mp_obj_new_list(0, NULL); self->base.type = &bleio_service_type; self->device = NULL; - self->char_list = mp_obj_new_list(0, NULL); self->handle = 0xFFFF; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_uuid, ARG_secondary }; + enum { ARG_uuid, ARG_characteristics, ARG_secondary }; static const mp_arg_t allowed_args[] = { - { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_characteristics, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; @@ -95,41 +81,42 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t uuid = args[ARG_uuid].u_obj; - if (uuid == mp_const_none) { - return MP_OBJ_FROM_PTR(self); + if (!MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + mp_raise_ValueError(translate("Expected a UUID")); } - if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { - self->uuid = MP_OBJ_TO_PTR(uuid); - } else { - mp_raise_ValueError(translate("Expected a UUID or None")); + self->uuid = MP_OBJ_TO_PTR(uuid); + + // If characteristics is not an iterable, an exception will be thrown. + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(args[ARG_characteristics].u_obj, &iter_buf); + mp_obj_t characteristic; + + while ((characteristic = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(characteristic, &bleio_characteristic_type)) { + mp_raise_ValueError(translate("characteristics includes an object that is not a Characteristic")); + } + bleio_characteristic_obj_t *characteristic_ptr = MP_OBJ_TO_PTR(characteristic); + if (common_hal_bleio_uuid_get_uuid128_reference(uuid) != + common_hal_bleio_uuid_get_uuid128_reference(characteristic_ptr->uuid)) { + // The descriptor base UUID doesn't match the characteristic base UUID. + mp_raise_ValueError(translate("Characteristic UUID doesn't match Service UUID")); + } + characteristic_ptr->service = self; + mp_obj_list_append(self->char_list, characteristic); } - return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t bleio_service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic_in) { - bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_in); - - if (common_hal_bleio_uuid_get_uuid128_reference(self->uuid) != - common_hal_bleio_uuid_get_uuid128_reference(characteristic->uuid)) { - // The descriptor base UUID doesn't match the characteristic base UUID. - mp_raise_ValueError(translate("Characteristic UUID doesn't match Descriptor UUID")); - } - - characteristic->service = self; - - mp_obj_list_append(self->char_list, characteristic); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_service_add_characteristic_obj, bleio_service_add_characteristic); - +//| .. attribute:: characteristics +//| +//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) +//| STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return self->char_list; + // Return list as a tuple so user won't be able to change it. + mp_obj_list_t *char_list = MP_OBJ_TO_PTR(self->char_list); + return mp_obj_new_tuple(char_list->len, char_list->items); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics); @@ -140,6 +127,10 @@ const mp_obj_property_t bleio_service_characteristics_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: uuid +//| +//| The UUID of this service. (read-only) +//| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -155,7 +146,6 @@ const mp_obj_property_t bleio_service_uuid_obj = { }; STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_obj) }, { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, }; |
