From 6ea01ea9b0334a175419f9d449be25a5838627da Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 29 Jun 2019 00:20:06 -0400 Subject: [PATCH] Central is connecting; characteristics can be read and written --- ports/nrf/Makefile | 2 +- ports/nrf/common-hal/bleio/Central.c | 151 +++++++++++--------- ports/nrf/common-hal/bleio/Central.h | 3 +- ports/nrf/common-hal/bleio/Characteristic.c | 10 +- ports/nrf/common-hal/bleio/Scanner.c | 4 +- shared-bindings/bleio/Central.c | 59 +++++--- shared-bindings/bleio/Central.h | 4 +- shared-bindings/bleio/Characteristic.c | 17 ++- shared-bindings/bleio/Peripheral.c | 4 +- shared-bindings/bleio/Service.c | 17 ++- shared-bindings/bleio/UUID.c | 3 + shared-bindings/bleio/__init__.c | 5 +- 12 files changed, 182 insertions(+), 97 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 18990485b4..83f87536bd 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -91,7 +91,7 @@ INC += -I../../supervisor/shared/usb ifeq ($(DEBUG), 1) CFLAGS += -ggdb # You may want to enable these flags to make setting breakpoints easier. - # CFLAGS += -fno-inline -fno-ipa-sra + CFLAGS += -fno-inline -fno-ipa-sra else CFLAGS += -Os -DNDEBUG # TODO: Test with -flto diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c index 5864a8a56f..0eedd2b568 100644 --- a/ports/nrf/common-hal/bleio/Central.c +++ b/ports/nrf/common-hal/bleio/Central.c @@ -44,11 +44,13 @@ static bleio_service_obj_t *m_char_discovery_service; static volatile bool m_discovery_in_process; static volatile bool m_discovery_successful; -STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle) { +// service_uuid may be NULL, to discover all services. +STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle, ble_uuid_t *service_uuid) { m_discovery_successful = false; m_discovery_in_process = true; - uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, NULL); + uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, service_uuid); + if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg(translate("Failed to discover services")); } @@ -88,15 +90,26 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); service->base.type = &bleio_service_type; + service->device = MP_OBJ_FROM_PTR(central); service->characteristic_list = mp_obj_new_list(0, NULL); service->start_handle = gattc_service->handle_range.start_handle; service->end_handle = gattc_service->handle_range.end_handle; service->handle = gattc_service->handle_range.start_handle; - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); - service->uuid = uuid; + if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known service UUID. + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); + service->uuid = uuid; + service->device = MP_OBJ_FROM_PTR(central); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just set the UUID to NULL. + service->uuid = NULL; + } mp_obj_list_append(central->service_list, service); } @@ -114,10 +127,18 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); characteristic->base.type = &bleio_characteristic_type; - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); - characteristic->uuid = uuid; + if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known characteristic UUID. + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); + characteristic->uuid = uuid; + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just set the UUID to NULL. + characteristic->uuid = NULL; + } characteristic->props.broadcast = gattc_char->char_props.broadcast; characteristic->props.indicate = gattc_char->char_props.indicate; @@ -137,25 +158,18 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio m_discovery_in_process = false; } -STATIC void on_ble_evt(ble_evt_t *ble_evt, void *central_in) { +STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { bleio_central_obj_t *central = (bleio_central_obj_t*)central_in; switch (ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: - { - ble_gap_conn_params_t conn_params; central->conn_handle = ble_evt->evt.gap_evt.conn_handle; - - sd_ble_gap_ppcp_get(&conn_params); - sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); + central->waiting_to_connect = false; break; - } case BLE_GAP_EVT_TIMEOUT: - if (central->attempting_to_connect) { - // Signal that connection attempt has timed out. - central->attempting_to_connect = false; - } + // Handle will be invalid. + central->waiting_to_connect = false; break; case BLE_GAP_EVT_DISCONNECTED: @@ -172,14 +186,6 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *central_in) { on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, central); break; - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - sd_ble_gatts_sys_attr_set(ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); - break; - - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - sd_ble_gatts_exchange_mtu_reply(central->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); - break; - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); break; @@ -193,7 +199,7 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *central_in) { } } -void common_hal_bleio_central_construct(bleio_central_obj_t *self, bleio_address_obj_t *address) { +void common_hal_bleio_central_construct(bleio_central_obj_t *self) { common_hal_bleio_adapter_set_enabled(true); self->service_list = mp_obj_new_list(0, NULL); @@ -201,13 +207,16 @@ void common_hal_bleio_central_construct(bleio_central_obj_t *self, bleio_address self->conn_handle = BLE_CONN_HANDLE_INVALID; } -void common_hal_bleio_central_connect(bleio_central_obj_t *self, mp_float_t timeout) { +void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids) { common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(on_ble_evt, self); + ble_drv_add_event_handler(central_on_ble_evt, self); ble_gap_addr_t addr; - addr.addr_type = self->address.type; - memcpy(addr.addr, self->address.bytes, NUM_BLEIO_ADDRESS_BYTES); + + addr.addr_type = address->type; + mp_buffer_info_t address_buf_info; + mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); + memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); ble_gap_scan_params_t scan_params = { .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), @@ -224,7 +233,7 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, mp_float_t time .slave_latency = 0, // number of conn events }; - self->attempting_to_connect = true; + self->waiting_to_connect = true; uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); @@ -232,50 +241,68 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, mp_float_t time mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code); } - while (self->conn_handle == BLE_CONN_HANDLE_INVALID && self->attempting_to_connect) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif + while (self->waiting_to_connect) { + MICROPY_VM_HOOK_LOOP; } - if (!self->attempting_to_connect) { + if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_OSError_msg(translate("Failed to connect: timeout")); } - // Conenction successful. - // Now discover all services on the remote peripheral. Ask for services repeatedly - // until no more are left. + // Connection successful. + // Now discover services on the remote peripheral. - uint16_t next_start_handle; + if (service_uuids == mp_const_none) { - next_start_handle = BLE_GATT_HANDLE_START; + // List of service UUID's not given, so discover all available services. - while (1) { - if(!discover_next_services(self, next_start_handle)) { - break; + uint16_t next_start_handle = BLE_GATT_HANDLE_START; + + while (discover_next_services(self, next_start_handle, MP_OBJ_NULL)) { + // discover_next_services() appends to service_list. + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); + + // Get the most recently discovered service, and then ask for services + // whose handles start after the last attribute handle inside that service. + const bleio_service_obj_t *service = service_list->items[service_list->len - 1]; + next_start_handle = service->end_handle + 1; } + } else { + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(service_uuids, &iter_buf); + mp_obj_t uuid_obj; + while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { + mp_raise_ValueError(translate("non-UUID found in service_uuids")); + } + bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); - // discover_next_services() appends to service_list. - const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); + ble_uuid_t nrf_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); - // Get the most recently discovered service, and ask for services with handles - // starting after the last attribute handle of t - const bleio_service_obj_t *service = service_list->items[service_list->len - 1]; - next_start_handle = service->end_handle + 1; + // Service might or might not be discovered; that's ok. Caller has to check + // Central.remote_services to find out. + // We only need to call this once for each service to discover. + discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid); + } } - // Now, for each service, discover its characteristics. - // find characteristics in each service + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); for (size_t i = 0; i < service_list->len; ++i) { bleio_service_obj_t *service = service_list->items[i]; - next_start_handle = service->start_handle; + // Skip the service if it had an unknown (unregistered) UUID. + if (service->uuid == NULL) { + continue; + } - while (1) { - if (!discover_next_characteristics(self, service, service->start_handle)) { - break; - } + uint16_t next_start_handle = service->start_handle; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + while (next_start_handle <= service->end_handle && + discover_next_characteristics(self, service, next_start_handle)) { // discover_next_characteristics() appends to the characteristic_list. const mp_obj_list_t *characteristic_list = MP_OBJ_TO_PTR(service->characteristic_list); @@ -284,10 +311,6 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, mp_float_t time const bleio_characteristic_obj_t *characteristic = characteristic_list->items[characteristic_list->len - 1]; next_start_handle = characteristic->handle + 1; - if (next_start_handle >= service->end_handle) { - // Went past the end of the range of handles for this service. - break; - } } } } diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/bleio/Central.h index ba4a92187b..8b38e87ac0 100644 --- a/ports/nrf/common-hal/bleio/Central.h +++ b/ports/nrf/common-hal/bleio/Central.h @@ -36,8 +36,7 @@ typedef struct { mp_obj_base_t base; gatt_role_t gatt_role; - bleio_address_obj_t address; - volatile bool attempting_to_connect; + volatile bool waiting_to_connect; volatile uint16_t conn_handle; mp_obj_t service_list; } bleio_central_obj_t; diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index d2f961fe65..ea43d8a8ab 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -60,7 +60,7 @@ STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) { } STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) { - // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because + // This might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because // we can still read and write the local value. const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); @@ -135,8 +135,15 @@ STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp } +STATIC void check_connected(uint16_t conn_handle) { + if (conn_handle == BLE_CONN_HANDLE_INVALID) { + mp_raise_OSError_msg(translate("Not connected")); + } +} + STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); + check_connected(conn_handle); m_read_characteristic = characteristic; @@ -152,6 +159,7 @@ STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); + check_connected(conn_handle); ble_gattc_write_params_t write_params = { .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL, diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c index 04dc62f956..fa4f3923c8 100644 --- a/ports/nrf/common-hal/bleio/Scanner.c +++ b/ports/nrf/common-hal/bleio/Scanner.c @@ -45,7 +45,7 @@ static ble_data_t m_scan_buffer = { BLE_GAP_SCAN_BUFFER_MIN }; -STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { +STATIC void scanner_on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in; ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; @@ -79,7 +79,7 @@ void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self) { void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window) { common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(on_ble_evt, self); + ble_drv_add_event_handler(scanner_on_ble_evt, self); ble_gap_scan_params_t scan_params = { .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), diff --git a/shared-bindings/bleio/Central.c b/shared-bindings/bleio/Central.c index b3be906067..dd2dd0d50f 100644 --- a/shared-bindings/bleio/Central.c +++ b/shared-bindings/bleio/Central.c @@ -64,43 +64,68 @@ //| central.connect(10.0) # timeout after 10 seconds //| -//| .. class:: Central(address) +//| .. class:: Central() //| //| Create a new Central object. -//| :param bleio.Address address: The address of the central to connect to //| STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 1, 1, false); + mp_arg_check_num(n_args, kw_args, 0, 0, false); bleio_central_obj_t *self = m_new_obj(bleio_central_obj_t); self->base.type = &bleio_central_type; - const mp_obj_t address_obj = pos_args[0]; - if (!MP_OBJ_IS_TYPE(address_obj, &bleio_address_type)) { - mp_raise_ValueError(translate("Expected an Address")); - } - - bleio_address_obj_t *address = MP_OBJ_TO_PTR(address_obj); - common_hal_bleio_central_construct(self, address); + common_hal_bleio_central_construct(self); return MP_OBJ_FROM_PTR(self); } -//| .. method:: connect() -//| +//| .. method:: connect(address, timeout, *, service_uuids=None) //| Attempts a connection to the remote peripheral. If the connection is successful, +//| Do BLE discovery for the listed services, to find their handles and characteristics. +//| The attribute `remote_services` will contain a list of all discovered services. //| -STATIC mp_obj_t bleio_central_connect(mp_obj_t self_in, mp_obj_t timeout_in) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in); +//| :param bleio.Address address: The address of the peripheral to connect to +//| :param float/int timeout: Try to connect for timeout seconds. +//| :param iterable service_uuids: a collection of `UUID` objects for the services +//| provided by the peripheral that you want to use. +//| The peripheral may provide more services, but services not listed are ignored. +//| If a service in `service_uuids` is not found during discovery, it will not +//| appear in `remote_services`. +//| +//| If `services` is None, then all services will undergo discovery, which can be slow. +//| +//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you +//| you must have already created a `UUID` object for that UUID in order for the +//| service or characteristic to be discovered. (This restriction may be lifted in the future.) +//| +STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_float_t timeout = mp_obj_float_get(timeout_in); - common_hal_bleio_central_connect(self, timeout); + enum { ARG_address, ARG_timeout, ARG_service_uuids }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_service_uuids, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { + mp_raise_ValueError(translate("Expected an Address")); + } + + bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); + mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + + // common_hal_bleio_central_connect() will validate that services is an iterable or None. + common_hal_bleio_central_connect(self, address, timeout, args[ARG_service_uuids].u_obj); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_central_connect_obj, bleio_central_connect); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_connect_obj, 3, bleio_central_connect); //| .. method:: disconnect() diff --git a/shared-bindings/bleio/Central.h b/shared-bindings/bleio/Central.h index c6fb50bc0c..542ba8fa2f 100644 --- a/shared-bindings/bleio/Central.h +++ b/shared-bindings/bleio/Central.h @@ -33,8 +33,8 @@ extern const mp_obj_type_t bleio_central_type; -extern void common_hal_bleio_central_construct(bleio_central_obj_t *self, bleio_address_obj_t *address); -extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, mp_float_t timeout); +extern void common_hal_bleio_central_construct(bleio_central_obj_t *self); +extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids); extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self); extern mp_obj_t common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self); diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 050992bb86..ede38c86b3 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -205,11 +205,13 @@ const mp_obj_property_t bleio_characteristic_write_no_response_obj = { //| .. attribute:: uuid //| //| The UUID of this characteristic. (read-only) +//| Will be ``None`` if the 128-bit UUID for this characteristic is not known. //| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_FROM_PTR(common_hal_bleio_characteristic_get_uuid(self)); + bleio_uuid_obj_t *uuid = common_hal_bleio_characteristic_get_uuid(self); + return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid); @@ -262,12 +264,23 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_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); +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("); + if (self->uuid) { + bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind); + } else { + mp_printf(print, "Unregistered uUID"); + } + mp_printf(print, ")"); +} + const mp_obj_type_t bleio_characteristic_type = { { &mp_type_type }, .name = MP_QSTR_Characteristic, .make_new = bleio_characteristic_make_new, + .print = bleio_characteristic_print, .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict }; diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index 002999b5d6..37a765ae9c 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -113,7 +113,7 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar mp_obj_t service; while ((service = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (!MP_OBJ_IS_TYPE(service, &bleio_service_type)) { - mp_raise_ValueError(translate("services includes an object that is not a Service")); + mp_raise_ValueError(translate("non-Service found in services")); } mp_obj_list_append(service_list, service); } @@ -237,7 +237,7 @@ STATIC mp_obj_t bleio_peripheral_start_advertising(mp_uint_t n_args, const mp_ob return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_start_advertising_obj, 0, bleio_peripheral_start_advertising); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_start_advertising_obj, 2, bleio_peripheral_start_advertising); //| .. method:: stop_advertising() //| diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index e687019d14..e6bb7dcc3f 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -140,11 +140,13 @@ const mp_obj_property_t bleio_service_secondary_obj = { //| .. attribute:: uuid //| //| The UUID of this service. (read-only) +//| Will be ``None`` if the 128-bit UUID for this service is not known. //| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_FROM_PTR(common_hal_bleio_service_get_uuid(self)); + bleio_uuid_obj_t *uuid = common_hal_bleio_service_get_uuid(self); + return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_uuid_obj, bleio_service_get_uuid); @@ -160,12 +162,23 @@ STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, }; - STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); +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); + mp_printf(print, "Service("); + if (self->uuid) { + bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind); + } else { + mp_printf(print, "unregistered UUID"); + } + mp_printf(print, ")"); +} + const mp_obj_type_t bleio_service_type = { { &mp_type_type }, .name = MP_QSTR_Service, .make_new = bleio_service_make_new, + .print = bleio_service_print, .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict }; diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/bleio/UUID.c index 0db7435f44..dca7ea0109 100644 --- a/shared-bindings/bleio/UUID.c +++ b/shared-bindings/bleio/UUID.c @@ -50,6 +50,9 @@ //| - a buffer object (bytearray, bytes) of 16 bytes in little-endian order (128-bit UUID) //| - a string of hex digits of the form 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' //| +//| Creating a 128-bit UUID registers the UUID with the onboard BLE software, and provides a +//| temporary 16-bit UUID that can be used in place of the full 128-bit UUID. +//| //| :param value: The uuid value to encapsulate //| :type value: int or typing.ByteString //| diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index ca45a846ec..9e80b49e37 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -28,9 +28,10 @@ #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/Central.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/CharacteristicBuffer.h" -#include "shared-bindings/bleio/Descriptor.h" +// #include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Peripheral.h" #include "shared-bindings/bleio/ScanEntry.h" #include "shared-bindings/bleio/Scanner.h" @@ -74,7 +75,7 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, -// { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, + { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, // { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },