another API rework: less abstraction leakage
This commit is contained in:
parent
19c59b41ed
commit
f17059b10b
12 changed files with 270 additions and 252 deletions
|
|
@ -124,8 +124,8 @@ STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic
|
||||||
ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
|
ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
self->service = MP_OBJ_NULL;
|
self->service = service;
|
||||||
self->uuid = uuid;
|
self->uuid = uuid;
|
||||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
self->props = props;
|
self->props = props;
|
||||||
|
|
@ -222,9 +222,6 @@ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
||||||
// Connect descriptor to parent characteristic.
|
|
||||||
descriptor->characteristic = self;
|
|
||||||
|
|
||||||
ble_uuid_t desc_uuid;
|
ble_uuid_t desc_uuid;
|
||||||
bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
|
bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@
|
||||||
|
|
||||||
static volatile bleio_descriptor_obj_t *m_read_descriptor;
|
static volatile bleio_descriptor_obj_t *m_read_descriptor;
|
||||||
|
|
||||||
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
self->characteristic = MP_OBJ_NULL;
|
self->characteristic = characteristic;
|
||||||
self->uuid = uuid;
|
self->uuid = uuid;
|
||||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
|
|
|
||||||
|
|
@ -223,8 +223,6 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service) {
|
void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service) {
|
||||||
service->device = MP_OBJ_FROM_PTR(self);
|
|
||||||
|
|
||||||
ble_uuid_t uuid;
|
ble_uuid_t uuid;
|
||||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||||
|
|
||||||
|
|
@ -241,7 +239,6 @@ void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio
|
||||||
mp_obj_list_append(self->service_list, MP_OBJ_FROM_PTR(service));
|
mp_obj_list_append(self->service_list, MP_OBJ_FROM_PTR(service));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) {
|
mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) {
|
||||||
return self->service_list;
|
return self->service_list;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,17 @@
|
||||||
#include "common-hal/bleio/__init__.h"
|
#include "common-hal/bleio/__init__.h"
|
||||||
#include "shared-bindings/bleio/Characteristic.h"
|
#include "shared-bindings/bleio/Characteristic.h"
|
||||||
#include "shared-bindings/bleio/Descriptor.h"
|
#include "shared-bindings/bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/bleio/Peripheral.h"
|
||||||
#include "shared-bindings/bleio/Service.h"
|
#include "shared-bindings/bleio/Service.h"
|
||||||
#include "shared-bindings/bleio/Adapter.h"
|
#include "shared-bindings/bleio/Adapter.h"
|
||||||
|
|
||||||
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
||||||
|
self->device = MP_OBJ_FROM_PTR(peripheral);
|
||||||
self->handle = 0xFFFF;
|
self->handle = 0xFFFF;
|
||||||
self->uuid = uuid;
|
self->uuid = uuid;
|
||||||
self->characteristic_list = mp_obj_new_list(0, NULL);
|
self->characteristic_list = mp_obj_new_list(0, NULL);
|
||||||
self->is_remote = false;
|
self->is_remote = false;
|
||||||
self->is_secondary = is_secondary;
|
self->is_secondary = is_secondary;
|
||||||
self->device = mp_const_none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
|
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
|
||||||
|
|
@ -59,11 +60,7 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
|
||||||
return self->is_secondary;
|
return self->is_secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) {
|
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) {
|
||||||
// Connect characteristic to parent service.
|
|
||||||
characteristic->service = self;
|
|
||||||
|
|
||||||
ble_gatts_char_md_t char_md = {
|
ble_gatts_char_md_t char_md = {
|
||||||
.char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
|
.char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
|
||||||
.char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
|
.char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
|
||||||
|
|
|
||||||
|
|
@ -158,9 +158,8 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
|
||||||
service->base.type = &bleio_service_type;
|
service->base.type = &bleio_service_type;
|
||||||
|
|
||||||
// Initialize several fields at once.
|
// Initialize several fields at once.
|
||||||
common_hal_bleio_service_construct(service, NULL, false);
|
common_hal_bleio_service_construct(service, device, NULL, false);
|
||||||
|
|
||||||
service->device = device;
|
|
||||||
service->is_remote = true;
|
service->is_remote = true;
|
||||||
service->start_handle = gattc_service->handle_range.start_handle;
|
service->start_handle = gattc_service->handle_range.start_handle;
|
||||||
service->end_handle = gattc_service->handle_range.end_handle;
|
service->end_handle = gattc_service->handle_range.end_handle;
|
||||||
|
|
@ -218,11 +217,10 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob
|
||||||
|
|
||||||
// Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
|
// Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
|
||||||
common_hal_bleio_characteristic_construct(
|
common_hal_bleio_characteristic_construct(
|
||||||
characteristic, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
characteristic, m_char_discovery_service, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||||
GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
||||||
mp_obj_new_list(0, NULL));
|
mp_obj_new_list(0, NULL));
|
||||||
characteristic->handle = gattc_char->handle_value;
|
characteristic->handle = gattc_char->handle_value;
|
||||||
characteristic->service = m_char_discovery_service;
|
|
||||||
|
|
||||||
mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
||||||
}
|
}
|
||||||
|
|
@ -274,10 +272,11 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob
|
||||||
// For now, just leave the UUID as NULL.
|
// For now, just leave the UUID as NULL.
|
||||||
}
|
}
|
||||||
|
|
||||||
common_hal_bleio_descriptor_construct(descriptor, uuid, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
common_hal_bleio_descriptor_construct(
|
||||||
GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
descriptor, m_desc_discovery_characteristic, uuid,
|
||||||
|
SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||||
|
GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
||||||
descriptor->handle = gattc_desc->handle;
|
descriptor->handle = gattc_desc->handle;
|
||||||
descriptor->characteristic = m_desc_discovery_characteristic;
|
|
||||||
|
|
||||||
mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
|
mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared-bindings/bleio/Attribute.h"
|
#include "shared-bindings/bleio/Attribute.h"
|
||||||
#include "shared-bindings/bleio/Characteristic.h"
|
#include "shared-bindings/bleio/Characteristic.h"
|
||||||
#include "shared-bindings/bleio/Descriptor.h"
|
#include "shared-bindings/bleio/Service.h"
|
||||||
#include "shared-bindings/bleio/UUID.h"
|
#include "shared-bindings/bleio/UUID.h"
|
||||||
|
|
||||||
//| .. currentmodule:: bleio
|
//| .. currentmodule:: bleio
|
||||||
|
|
@ -41,12 +41,111 @@
|
||||||
//| Stores information about a BLE service characteristic and allows reading
|
//| Stores information about a BLE service characteristic and allows reading
|
||||||
//| and writing of the characteristic's value.
|
//| and writing of the characteristic's value.
|
||||||
//|
|
//|
|
||||||
//| A Characteristic cannot be created directly. A new local Characteristic can be created
|
//| There is no regular constructor for a Characteristic. A new local Characteristic can be created
|
||||||
//| and attached to a Service by calling `Service.add_characteristic()`.
|
//| and attached to a Service by calling `Characteristic.add_to_service()`.
|
||||||
//| Remote Characteristic objects are created by `Central.discover_remote_services()`
|
//| Remote Characteristic objects are created by `Central.discover_remote_services()`
|
||||||
//| or `Peripheral.discover_remote_services()` as part of remote Services.
|
//| or `Peripheral.discover_remote_services()` as part of remote Services.
|
||||||
//|
|
//|
|
||||||
|
|
||||||
|
//| .. method:: add_to_service(service, uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=None)
|
||||||
|
//|
|
||||||
|
//| Create a new `Characteristic` object, and add it to this Service.
|
||||||
|
//|
|
||||||
|
//| :param bleio.Service service: The service that will provide this characteristic
|
||||||
|
//| :param bleio.UUID uuid: The uuid of the characteristic
|
||||||
|
//| :param int properties: The properties of the characteristic,
|
||||||
|
//| specified as a bitmask of these values bitwise-or'd together:
|
||||||
|
//| `Characteristic.BROADCAST`, `Characteristic.INDICATE`, `Characteristic.NOTIFY`,
|
||||||
|
//| `Characteristic.READ`, `Characteristic.WRITE`, `Characteristic.WRITE_NO_RESPONSE`.
|
||||||
|
//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
|
||||||
|
//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
|
||||||
|
//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
|
||||||
|
//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
|
||||||
|
//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
|
||||||
|
//| security mode is required. Values allowed are the same as ``read_perm``.
|
||||||
|
//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
|
||||||
|
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
|
||||||
|
//| number of data bytes that fit in a single BLE 4.x ATT packet.
|
||||||
|
//| :param bool fixed_length: True if the characteristic value is of fixed length.
|
||||||
|
//| :param buf initial_value: The initial value for this characteristic. If not given, will be
|
||||||
|
//| filled with zeros.
|
||||||
|
//|
|
||||||
|
//| :return: the new `Characteristic`.
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
// class is arg[0], which we can ignore.
|
||||||
|
|
||||||
|
enum { ARG_service, ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm,
|
||||||
|
ARG_max_length, ARG_fixed_length, ARG_initial_value };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_service, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} },
|
||||||
|
{ MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
||||||
|
{ MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
||||||
|
{ MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
|
||||||
|
{ MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
{ MP_QSTR_initial_value, 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);
|
||||||
|
|
||||||
|
const mp_obj_t service_obj = args[ARG_service].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(service_obj, &bleio_service_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a Service"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a UUID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bleio_characteristic_properties_t properties = args[ARG_properties].u_int;
|
||||||
|
if (properties & ~CHAR_PROP_ALL) {
|
||||||
|
mp_raise_ValueError(translate("Invalid properties"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
|
||||||
|
common_hal_bleio_attribute_security_mode_check_valid(read_perm);
|
||||||
|
|
||||||
|
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
|
||||||
|
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
|
||||||
|
|
||||||
|
const mp_int_t max_length = args[ARG_max_length].u_int;
|
||||||
|
const bool fixed_length = args[ARG_fixed_length].u_bool;
|
||||||
|
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
|
||||||
|
|
||||||
|
// Length will be validated in common_hal.
|
||||||
|
mp_buffer_info_t initial_value_bufinfo;
|
||||||
|
if (initial_value == mp_const_none) {
|
||||||
|
if (fixed_length && max_length > 0) {
|
||||||
|
initial_value = mp_obj_new_bytes_of_zeros(max_length);
|
||||||
|
} else {
|
||||||
|
initial_value = mp_const_empty_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
|
||||||
|
|
||||||
|
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||||
|
characteristic->base.type = &bleio_characteristic_type;
|
||||||
|
|
||||||
|
// Range checking on max_length arg is done by the common_hal layer, because
|
||||||
|
// it may vary depending on underlying BLE implementation.
|
||||||
|
common_hal_bleio_characteristic_construct(
|
||||||
|
characteristic, MP_OBJ_TO_PTR(service_obj), MP_OBJ_TO_PTR(uuid_obj),
|
||||||
|
properties, read_perm, write_perm,
|
||||||
|
max_length, fixed_length, &initial_value_bufinfo);
|
||||||
|
|
||||||
|
common_hal_bleio_service_add_characteristic(service_obj, characteristic);
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(characteristic);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 3, bleio_characteristic_add_to_service);
|
||||||
|
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, MP_ROM_PTR(&bleio_characteristic_add_to_service_fun_obj));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//| .. attribute:: properties
|
//| .. attribute:: properties
|
||||||
//|
|
//|
|
||||||
//| An int bitmask representing which properties are set, specified as bitwise or'ing of
|
//| An int bitmask representing which properties are set, specified as bitwise or'ing of
|
||||||
|
|
@ -155,84 +254,6 @@ const mp_obj_property_t bleio_characteristic_service_obj = {
|
||||||
(mp_obj_t)&mp_const_none_obj },
|
(mp_obj_t)&mp_const_none_obj },
|
||||||
};
|
};
|
||||||
|
|
||||||
//| .. method:: add_descriptor(uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
|
|
||||||
//|
|
|
||||||
//| Create a new `Descriptor` object, and add it to this Service.
|
|
||||||
//|
|
|
||||||
//| :param bleio.UUID uuid: The uuid of the descriptor
|
|
||||||
//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
|
|
||||||
//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
|
|
||||||
//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
|
|
||||||
//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
|
|
||||||
//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
|
|
||||||
//| security mode is required. Values allowed are the same as ``read_perm``.
|
|
||||||
//| :param int max_length: Maximum length in bytes of the descriptor value. The maximum allowed is
|
|
||||||
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
|
|
||||||
//| number of data bytes that fit in a single BLE 4.x ATT packet.
|
|
||||||
//| :param bool fixed_length: True if the descriptor value is of fixed length.
|
|
||||||
//| :param buf initial_value: The initial value for this descriptor.
|
|
||||||
//|
|
|
||||||
//| :return: the new `Descriptor`.
|
|
||||||
//|
|
|
||||||
STATIC mp_obj_t bleio_characteristic_add_descriptor(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
||||||
|
|
||||||
enum { ARG_uuid, ARG_read_perm, ARG_write_perm,
|
|
||||||
ARG_max_length, ARG_fixed_length, ARG_initial_value };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
|
||||||
{ MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
|
||||||
{ MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
|
||||||
{ MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
|
|
||||||
{ MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
|
|
||||||
{ MP_QSTR_initial_value, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} },
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
|
||||||
|
|
||||||
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
|
||||||
mp_raise_ValueError(translate("Expected a UUID"));
|
|
||||||
}
|
|
||||||
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
|
|
||||||
|
|
||||||
const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
|
|
||||||
common_hal_bleio_attribute_security_mode_check_valid(read_perm);
|
|
||||||
|
|
||||||
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
|
|
||||||
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
|
|
||||||
|
|
||||||
const mp_int_t max_length = args[ARG_max_length].u_int;
|
|
||||||
const bool fixed_length = args[ARG_fixed_length].u_bool;
|
|
||||||
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
|
|
||||||
|
|
||||||
// Length will be validated in common_hal.
|
|
||||||
mp_buffer_info_t initial_value_bufinfo;
|
|
||||||
if (initial_value == mp_const_none) {
|
|
||||||
if (fixed_length && max_length > 0) {
|
|
||||||
initial_value = mp_obj_new_bytes_of_zeros(max_length);
|
|
||||||
} else {
|
|
||||||
initial_value = mp_const_empty_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
|
|
||||||
|
|
||||||
bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
|
|
||||||
descriptor->base.type = &bleio_descriptor_type;
|
|
||||||
|
|
||||||
// Range checking on max_length arg is done by the common_hal layer, because
|
|
||||||
// it may vary depending on underlying BLE implementation.
|
|
||||||
common_hal_bleio_descriptor_construct(
|
|
||||||
descriptor, uuid, read_perm, write_perm, max_length, fixed_length, &initial_value_bufinfo);
|
|
||||||
|
|
||||||
common_hal_bleio_characteristic_add_descriptor(self, descriptor);
|
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(descriptor);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_descriptor_obj, 2, bleio_characteristic_add_descriptor);
|
|
||||||
|
|
||||||
//| .. method:: set_cccd(*, notify=False, indicate=False)
|
//| .. method:: set_cccd(*, notify=False, indicate=False)
|
||||||
//|
|
//|
|
||||||
//| Set the remote characteristic's CCCD to enable or disable notification and indication.
|
//| Set the remote characteristic's CCCD to enable or disable notification and indication.
|
||||||
|
|
@ -260,10 +281,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_ch
|
||||||
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties) },
|
{ MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
|
{ 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_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_add_descriptor), MP_ROM_PTR(&bleio_characteristic_add_descriptor_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
|
||||||
|
|
||||||
// Bitmask constants to represent properties
|
// Bitmask constants to represent properties
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,11 @@
|
||||||
#include "shared-bindings/bleio/Descriptor.h"
|
#include "shared-bindings/bleio/Descriptor.h"
|
||||||
#include "shared-module/bleio/Characteristic.h"
|
#include "shared-module/bleio/Characteristic.h"
|
||||||
#include "common-hal/bleio/Characteristic.h"
|
#include "common-hal/bleio/Characteristic.h"
|
||||||
|
#include "common-hal/bleio/Service.h"
|
||||||
|
|
||||||
extern const mp_obj_type_t bleio_characteristic_type;
|
extern const mp_obj_type_t bleio_characteristic_type;
|
||||||
|
|
||||||
extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
|
extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
|
||||||
extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self);
|
extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self);
|
||||||
extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
|
extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self);
|
extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "py/objproperty.h"
|
#include "py/objproperty.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared-bindings/bleio/Attribute.h"
|
#include "shared-bindings/bleio/Attribute.h"
|
||||||
|
#include "shared-bindings/bleio/Characteristic.h"
|
||||||
#include "shared-bindings/bleio/Descriptor.h"
|
#include "shared-bindings/bleio/Descriptor.h"
|
||||||
#include "shared-bindings/bleio/UUID.h"
|
#include "shared-bindings/bleio/UUID.h"
|
||||||
|
|
||||||
|
|
@ -41,12 +42,98 @@
|
||||||
//| Descriptors are attached to BLE characteristics and provide contextual
|
//| Descriptors are attached to BLE characteristics and provide contextual
|
||||||
//| information about the characteristic.
|
//| information about the characteristic.
|
||||||
//|
|
//|
|
||||||
//| A Descriptors cannot be created directly. A new local Descriptors can be created
|
//| There is no regular constructor for a Descriptor. A new local Descriptor can be created
|
||||||
//| and attached to a Descriptors by calling `Service.add_characteristic()`.
|
//| and attached to a Characteristic by calling `Descriptor.add_to_characteristic()`.
|
||||||
//| Remote Descriptor objects are created by `Central.discover_remote_services()`
|
//| Remote Descriptor objects are created by `Central.discover_remote_services()`
|
||||||
//| or `Peripheral.discover_remote_services()` as part of remote Characteristics
|
//| or `Peripheral.discover_remote_services()` as part of remote Characteristics
|
||||||
//| in the remote Services that are discovered.
|
//| in the remote Services that are discovered.
|
||||||
|
|
||||||
|
//| .. method:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
|
||||||
|
//|
|
||||||
|
//| Create a new `Descriptor` object, and add it to this Service.
|
||||||
|
//|
|
||||||
|
//| :param bleio.Characteristic characteristic: The characteristic that will hold this descriptor
|
||||||
|
//| :param bleio.UUID uuid: The uuid of the descriptor
|
||||||
|
//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
|
||||||
|
//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
|
||||||
|
//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
|
||||||
|
//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
|
||||||
|
//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
|
||||||
|
//| security mode is required. Values allowed are the same as ``read_perm``.
|
||||||
|
//| :param int max_length: Maximum length in bytes of the descriptor value. The maximum allowed is
|
||||||
|
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
|
||||||
|
//| number of data bytes that fit in a single BLE 4.x ATT packet.
|
||||||
|
//| :param bool fixed_length: True if the descriptor value is of fixed length.
|
||||||
|
//| :param buf initial_value: The initial value for this descriptor.
|
||||||
|
//|
|
||||||
|
//| :return: the new `Descriptor`.
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
// class is arg[0], which we can ignore.
|
||||||
|
|
||||||
|
enum { ARG_characteristic, ARG_uuid, ARG_read_perm, ARG_write_perm,
|
||||||
|
ARG_max_length, ARG_fixed_length, ARG_initial_value };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_characteristic, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
||||||
|
{ MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
||||||
|
{ MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
|
||||||
|
{ MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
{ MP_QSTR_initial_value, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} },
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const mp_obj_t characteristic_obj = args[ARG_characteristic].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(characteristic_obj, &bleio_characteristic_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a Characteristic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a UUID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
|
||||||
|
common_hal_bleio_attribute_security_mode_check_valid(read_perm);
|
||||||
|
|
||||||
|
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
|
||||||
|
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
|
||||||
|
|
||||||
|
const mp_int_t max_length = args[ARG_max_length].u_int;
|
||||||
|
const bool fixed_length = args[ARG_fixed_length].u_bool;
|
||||||
|
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
|
||||||
|
|
||||||
|
// Length will be validated in common_hal.
|
||||||
|
mp_buffer_info_t initial_value_bufinfo;
|
||||||
|
if (initial_value == mp_const_none) {
|
||||||
|
if (fixed_length && max_length > 0) {
|
||||||
|
initial_value = mp_obj_new_bytes_of_zeros(max_length);
|
||||||
|
} else {
|
||||||
|
initial_value = mp_const_empty_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
|
||||||
|
|
||||||
|
bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
|
||||||
|
descriptor->base.type = &bleio_descriptor_type;
|
||||||
|
|
||||||
|
// Range checking on max_length arg is done by the common_hal layer, because
|
||||||
|
// it may vary depending on underlying BLE implementation.
|
||||||
|
common_hal_bleio_descriptor_construct(
|
||||||
|
descriptor, MP_OBJ_TO_PTR(characteristic_obj), MP_OBJ_TO_PTR(uuid_obj),
|
||||||
|
read_perm, write_perm,
|
||||||
|
max_length, fixed_length, &initial_value_bufinfo);
|
||||||
|
|
||||||
|
common_hal_bleio_characteristic_add_descriptor(characteristic_obj, descriptor);
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(descriptor);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_descriptor_add_to_characteristic_fun_obj, 3, bleio_descriptor_add_to_characteristic);
|
||||||
|
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_descriptor_add_to_characteristic_obj, MP_ROM_PTR(&bleio_descriptor_add_to_characteristic_fun_obj));
|
||||||
|
|
||||||
//| .. attribute:: uuid
|
//| .. attribute:: uuid
|
||||||
//|
|
//|
|
||||||
//| The descriptor uuid. (read-only)
|
//| The descriptor uuid. (read-only)
|
||||||
|
|
@ -115,7 +202,7 @@ const mp_obj_property_t bleio_descriptor_value_obj = {
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
|
||||||
// Properties
|
{ MP_ROM_QSTR(MP_QSTR_add_to_characteristic), MP_ROM_PTR(&bleio_descriptor_add_to_characteristic_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_characteristic), MP_ROM_PTR(&bleio_descriptor_characteristic_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_characteristic), MP_ROM_PTR(&bleio_descriptor_characteristic_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_descriptor_value_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_descriptor_value_obj) },
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
extern const mp_obj_type_t bleio_descriptor_type;
|
extern const mp_obj_type_t bleio_descriptor_type;
|
||||||
|
|
||||||
extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
|
extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
|
||||||
extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
|
extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
|
||||||
extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self);
|
extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self);
|
||||||
extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self);
|
extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self);
|
||||||
|
|
|
||||||
|
|
@ -112,50 +112,6 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
//| .. method:: add_service(uuid, *, secondary=False)
|
|
||||||
//|
|
|
||||||
//| Create a new `Service` object, identitied by the specified UUID, and add it to this ``Peripheral``.
|
|
||||||
//|
|
|
||||||
//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
|
|
||||||
//|
|
|
||||||
//| :param bleio.UUID uuid: The uuid of the service
|
|
||||||
//| :param bool secondary: If the service is a secondary one
|
|
||||||
//
|
|
||||||
//| :return: the new `Service`
|
|
||||||
//|
|
|
||||||
STATIC mp_obj_t bleio_peripheral_add_service(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
||||||
|
|
||||||
enum { ARG_uuid, ARG_secondary };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
|
||||||
{ MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
|
||||||
|
|
||||||
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
|
||||||
mp_raise_ValueError(translate("Expected a UUID"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool is_secondary = args[ARG_secondary].u_bool;
|
|
||||||
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
|
|
||||||
|
|
||||||
bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
|
|
||||||
service->base.type = &bleio_service_type;
|
|
||||||
|
|
||||||
common_hal_bleio_service_construct(service, uuid, is_secondary);
|
|
||||||
|
|
||||||
common_hal_bleio_peripheral_add_service(self, service);
|
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(service);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_add_service_obj, 2, bleio_peripheral_add_service);
|
|
||||||
|
|
||||||
|
|
||||||
//| .. attribute:: connected (read-only)
|
//| .. attribute:: connected (read-only)
|
||||||
//|
|
//|
|
||||||
//| True if connected to a BLE Central device.
|
//| True if connected to a BLE Central device.
|
||||||
|
|
@ -347,7 +303,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pai
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = {
|
||||||
// Methods
|
// Methods
|
||||||
{ MP_ROM_QSTR(MP_QSTR_add_service), MP_ROM_PTR(&bleio_peripheral_add_service_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "py/objproperty.h"
|
#include "py/objproperty.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared-bindings/bleio/Characteristic.h"
|
#include "shared-bindings/bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/bleio/Peripheral.h"
|
||||||
#include "shared-bindings/bleio/Service.h"
|
#include "shared-bindings/bleio/Service.h"
|
||||||
#include "shared-bindings/bleio/UUID.h"
|
#include "shared-bindings/bleio/UUID.h"
|
||||||
|
|
||||||
|
|
@ -39,12 +40,63 @@
|
||||||
//|
|
//|
|
||||||
//| Stores information about a BLE service and its characteristics.
|
//| Stores information about a BLE service and its characteristics.
|
||||||
//|
|
//|
|
||||||
//| A Service cannot be created directly. A new local Service can be created
|
//| There is no regular constructor for a Service. A new local Service can be created
|
||||||
//| and attached to a Peripheral by calling `Peripheral.add_service()`.
|
//| and attached to a Peripheral by calling `Service.add_to_peripheral()`.
|
||||||
//| Remote Service objects are created by `Central.discover_remote_services()`
|
//| Remote Service objects are created by `Central.discover_remote_services()`
|
||||||
//| or `Peripheral.discover_remote_services()`.
|
//| or `Peripheral.discover_remote_services()`.
|
||||||
//|
|
//|
|
||||||
|
|
||||||
|
//| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False)
|
||||||
|
//|
|
||||||
|
//| Create a new `Service` object, identitied by the specified UUID, and add it
|
||||||
|
//| to the given Peripheral.
|
||||||
|
//|
|
||||||
|
//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
|
||||||
|
//|
|
||||||
|
//| :param bleio.Peripheral peripheral: The peripheral that will provide this service
|
||||||
|
//| :param bleio.UUID uuid: The uuid of the service
|
||||||
|
//| :param bool secondary: If the service is a secondary one
|
||||||
|
//
|
||||||
|
//| :return: the new `Service`
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
// class is arg[0], which we can ignore.
|
||||||
|
|
||||||
|
enum { ARG_peripheral, ARG_uuid, ARG_secondary };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_peripheral, MP_ARG_REQUIRED | MP_ARG_OBJ,},
|
||||||
|
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const mp_obj_t peripheral_obj = args[ARG_peripheral].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(peripheral_obj, &bleio_peripheral_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a Peripheral"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
||||||
|
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
||||||
|
mp_raise_ValueError(translate("Expected a UUID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_secondary = args[ARG_secondary].u_bool;
|
||||||
|
|
||||||
|
bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
|
||||||
|
service->base.type = &bleio_service_type;
|
||||||
|
|
||||||
|
common_hal_bleio_service_construct(
|
||||||
|
service, MP_OBJ_TO_PTR(peripheral_obj), MP_OBJ_TO_PTR(uuid_obj), is_secondary);
|
||||||
|
|
||||||
|
common_hal_bleio_peripheral_add_service(peripheral_obj, service);
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(service);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_service_add_to_peripheral_fun_obj, 3, bleio_service_add_to_peripheral);
|
||||||
|
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_service_add_to_peripheral_obj, MP_ROM_PTR(&bleio_service_add_to_peripheral_fun_obj));
|
||||||
|
|
||||||
//| .. attribute:: characteristics
|
//| .. attribute:: characteristics
|
||||||
//|
|
//|
|
||||||
//| A tuple of `bleio.Characteristic` that are offered by this service. (read-only)
|
//| A tuple of `bleio.Characteristic` that are offered by this service. (read-only)
|
||||||
|
|
@ -120,101 +172,12 @@ const mp_obj_property_t bleio_service_uuid_obj = {
|
||||||
(mp_obj_t)&mp_const_none_obj },
|
(mp_obj_t)&mp_const_none_obj },
|
||||||
};
|
};
|
||||||
|
|
||||||
//| .. method:: add_characteristic(uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=None)
|
|
||||||
//|
|
|
||||||
//| Create a new `Characteristic` object, and add it to this Service.
|
|
||||||
//|
|
|
||||||
//| :param bleio.UUID uuid: The uuid of the characteristic
|
|
||||||
//| :param int properties: The properties of the characteristic,
|
|
||||||
//| specified as a bitmask of these values bitwise-or'd together:
|
|
||||||
//| `Characteristic.BROADCAST`, `Characteristic.INDICATE`, `Characteristic.NOTIFY`,
|
|
||||||
//| `Characteristic.READ`, `Characteristic.WRITE`, `Characteristic.WRITE_NO_RESPONSE`.
|
|
||||||
//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
|
|
||||||
//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
|
|
||||||
//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
|
|
||||||
//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
|
|
||||||
//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
|
|
||||||
//| security mode is required. Values allowed are the same as ``read_perm``.
|
|
||||||
//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
|
|
||||||
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
|
|
||||||
//| number of data bytes that fit in a single BLE 4.x ATT packet.
|
|
||||||
//| :param bool fixed_length: True if the characteristic value is of fixed length.
|
|
||||||
//| :param buf initial_value: The initial value for this characteristic. If not given, will be
|
|
||||||
//| filled with zeros.
|
|
||||||
//|
|
|
||||||
//| :return: the new `Characteristic`.
|
|
||||||
//|
|
|
||||||
STATIC mp_obj_t bleio_service_add_characteristic(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
bleio_service_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
||||||
|
|
||||||
enum { ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm,
|
|
||||||
ARG_max_length, ARG_fixed_length, ARG_initial_value };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
|
||||||
{ MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} },
|
|
||||||
{ MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
|
||||||
{ MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
|
|
||||||
{ MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
|
|
||||||
{ MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
|
|
||||||
{ MP_QSTR_initial_value, 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);
|
|
||||||
|
|
||||||
const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
|
|
||||||
|
|
||||||
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
|
||||||
mp_raise_ValueError(translate("Expected a UUID"));
|
|
||||||
}
|
|
||||||
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
|
|
||||||
|
|
||||||
const bleio_characteristic_properties_t properties = args[ARG_properties].u_int;
|
|
||||||
if (properties & ~CHAR_PROP_ALL) {
|
|
||||||
mp_raise_ValueError(translate("Invalid properties"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
|
|
||||||
common_hal_bleio_attribute_security_mode_check_valid(read_perm);
|
|
||||||
|
|
||||||
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
|
|
||||||
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
|
|
||||||
|
|
||||||
const mp_int_t max_length = args[ARG_max_length].u_int;
|
|
||||||
const bool fixed_length = args[ARG_fixed_length].u_bool;
|
|
||||||
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
|
|
||||||
|
|
||||||
// Length will be validated in common_hal.
|
|
||||||
mp_buffer_info_t initial_value_bufinfo;
|
|
||||||
if (initial_value == mp_const_none) {
|
|
||||||
if (fixed_length && max_length > 0) {
|
|
||||||
initial_value = mp_obj_new_bytes_of_zeros(max_length);
|
|
||||||
} else {
|
|
||||||
initial_value = mp_const_empty_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
|
|
||||||
|
|
||||||
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
|
||||||
characteristic->base.type = &bleio_characteristic_type;
|
|
||||||
|
|
||||||
// Range checking on max_length arg is done by the common_hal layer, because
|
|
||||||
// it may vary depending on underlying BLE implementation.
|
|
||||||
common_hal_bleio_characteristic_construct(
|
|
||||||
characteristic, uuid, properties, read_perm, write_perm,
|
|
||||||
max_length, fixed_length, &initial_value_bufinfo);
|
|
||||||
|
|
||||||
common_hal_bleio_service_add_characteristic(self, characteristic);
|
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(characteristic);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_service_add_characteristic_obj, 2, bleio_service_add_characteristic);
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_add_to_peripheral), MP_ROM_PTR(&bleio_service_add_to_peripheral_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_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) },
|
{ MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_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 MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,12 @@
|
||||||
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
|
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
|
||||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
|
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
|
||||||
|
|
||||||
|
#include "common-hal/bleio/Peripheral.h"
|
||||||
#include "common-hal/bleio/Service.h"
|
#include "common-hal/bleio/Service.h"
|
||||||
|
|
||||||
const mp_obj_type_t bleio_service_type;
|
const mp_obj_type_t bleio_service_type;
|
||||||
|
|
||||||
extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary);
|
extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary);
|
||||||
extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self);
|
extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self);
|
||||||
extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self);
|
extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self);
|
||||||
extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self);
|
extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue