summaryrefslogtreecommitdiff
path: root/shared-bindings/_bleio
diff options
context:
space:
mode:
Diffstat (limited to 'shared-bindings/_bleio')
-rw-r--r--shared-bindings/_bleio/Adapter.c300
-rw-r--r--shared-bindings/_bleio/Adapter.h28
-rw-r--r--shared-bindings/_bleio/Address.c30
-rw-r--r--shared-bindings/_bleio/Central.c207
-rw-r--r--shared-bindings/_bleio/Characteristic.c33
-rw-r--r--shared-bindings/_bleio/Characteristic.h6
-rw-r--r--shared-bindings/_bleio/Connection.c171
-rw-r--r--shared-bindings/_bleio/Connection.h (renamed from shared-bindings/_bleio/Central.h)18
-rw-r--r--shared-bindings/_bleio/Descriptor.c9
-rw-r--r--shared-bindings/_bleio/Descriptor.h2
-rw-r--r--shared-bindings/_bleio/Peripheral.c325
-rw-r--r--shared-bindings/_bleio/Peripheral.h48
-rw-r--r--shared-bindings/_bleio/ScanEntry.c74
-rw-r--r--shared-bindings/_bleio/ScanEntry.h3
-rw-r--r--shared-bindings/_bleio/ScanResults.c72
-rw-r--r--shared-bindings/_bleio/ScanResults.h (renamed from shared-bindings/_bleio/Scanner.h)17
-rw-r--r--shared-bindings/_bleio/Scanner.c129
-rw-r--r--shared-bindings/_bleio/Service.c74
-rw-r--r--shared-bindings/_bleio/Service.h14
-rw-r--r--shared-bindings/_bleio/UUID.c51
-rw-r--r--shared-bindings/_bleio/UUID.h5
-rw-r--r--shared-bindings/_bleio/__init__.c19
-rw-r--r--shared-bindings/_bleio/__init__.h18
23 files changed, 806 insertions, 847 deletions
diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c
index 0caca96b8..01dba0491 100644
--- a/shared-bindings/_bleio/Adapter.c
+++ b/shared-bindings/_bleio/Adapter.c
@@ -25,22 +25,45 @@
* THE SOFTWARE.
*/
+#include <string.h>
+
#include "py/objproperty.h"
+#include "py/runtime.h"
#include "shared-bindings/_bleio/Address.h"
#include "shared-bindings/_bleio/Adapter.h"
+#define ADV_INTERVAL_MIN (0.0020f)
+#define ADV_INTERVAL_MIN_STRING "0.0020"
+#define ADV_INTERVAL_MAX (10.24f)
+#define ADV_INTERVAL_MAX_STRING "10.24"
+// 20ms is recommended by Apple
+#define ADV_INTERVAL_DEFAULT (0.1f)
+
+#define INTERVAL_DEFAULT (0.1f)
+#define INTERVAL_MIN (0.0025f)
+#define INTERVAL_MIN_STRING "0.0025"
+#define INTERVAL_MAX (40.959375f)
+#define INTERVAL_MAX_STRING "40.959375"
+#define WINDOW_DEFAULT (0.1f)
+
//| .. currentmodule:: _bleio
//|
-//| :class:`Adapter` --- BLE adapter information
+//| :class:`Adapter` --- BLE adapter
//| ----------------------------------------------------
//|
-//| Get current status of the BLE adapter
+//| The Adapter manages the discovery and connection to other nearby Bluetooth Low Energy devices.
+//| This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP).
//|
-//| Usage::
+//| Discovery of other devices happens during a scanning process that listens for small packets of
+//| information, known as advertisements, that are broadcast unencrypted. The advertising packets
+//| have two different uses. The first is to broadcast a small piece of data to anyone who cares and
+//| and nothing more. These are known as Beacons. The second class of advertisement is to promote
+//| additional functionality available after the devices establish a connection. For example, a
+//| BLE keyboard may advertise that it can provide key information, but not what the key info is.
//|
-//| import _bleio
-//| _bleio.adapter.enabled = True
-//| print(_bleio.adapter.address)
+//| The built-in BLE adapter can do both parts of this process, it can scan for other device
+//| advertisements and it can advertise it's own data. Furthermore, Adapters can accept incoming
+//| connections and also initiate connections.
//|
//| .. class:: Adapter()
@@ -49,19 +72,19 @@
//| Use `_bleio.adapter` to access the sole instance available.
//|
-//| .. attribute:: adapter.enabled
+//| .. attribute:: enabled
//|
-//| State of the BLE adapter.
+//| State of the BLE adapter.
//|
STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) {
- return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled());
+ return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_enabled_obj, bleio_adapter_get_enabled);
static mp_obj_t bleio_adapter_set_enabled(mp_obj_t self, mp_obj_t value) {
const bool enabled = mp_obj_is_true(value);
- common_hal_bleio_adapter_set_enabled(enabled);
+ common_hal_bleio_adapter_set_enabled(self, enabled);
return mp_const_none;
}
@@ -74,12 +97,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: adapter.address
+//| .. attribute:: address
//|
-//| MAC address of the BLE adapter. (read-only)
+//| MAC address of the BLE adapter. (read-only)
//|
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
- return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address());
+ return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address);
@@ -91,29 +114,260 @@ const mp_obj_property_t bleio_adapter_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: adapter.default_name
+//| .. attribute:: name
+//|
+//| name of the BLE adapter used once connected. Not used in advertisements.
+//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
+//| to make it easy to distinguish multiple CircuitPython boards.
+//|
+STATIC mp_obj_t bleio_adapter_get_name(mp_obj_t self) {
+ return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_name_obj, bleio_adapter_get_name);
+
+
+STATIC mp_obj_t bleio_adapter_set_name(mp_obj_t self, mp_obj_t new_name) {
+ common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(new_name));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(bleio_adapter_set_name_obj, bleio_adapter_set_name);
+
+const mp_obj_property_t bleio_adapter_name_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_name_obj,
+ (mp_obj_t)&bleio_adapter_set_name_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1)
+//|
+//| Starts advertising until `stop_advertising` is called or if connectable, another device
+//| connects to us.
+//|
+//| :param buf data: advertising data packet bytes
+//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
+//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
+//| :param float interval: advertising interval, in seconds
+//|
+STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ };
+
+ 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);
+
+ mp_buffer_info_t data_bufinfo;
+ mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ);
+
+ // Pass an empty buffer if scan_response not provided.
+ mp_buffer_info_t scan_response_bufinfo = { 0 };
+ if (args[ARG_scan_response].u_obj != mp_const_none) {
+ mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ);
+ }
+
+ if (args[ARG_interval].u_obj == MP_OBJ_NULL) {
+ args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT);
+ }
+
+ const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj);
+ if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) {
+ mp_raise_ValueError_varg(translate("interval must be in range %s-%s"),
+ ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING);
+ }
+
+ common_hal_bleio_adapter_start_advertising(self, args[ARG_connectable].u_bool, interval,
+ &data_bufinfo, &scan_response_bufinfo);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 2, bleio_adapter_start_advertising);
+
+//| .. method:: stop_advertising()
+//|
+//| Stop sending advertising packets.
+STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) {
+ bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_adapter_stop_advertising(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapter_stop_advertising);
+
+//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80)
+//|
+//| Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are
+//| filtered and returned separately.
+//|
+//| :param sequence prefixes: Sequence of byte string prefixes to filter advertising packets
+//| with. A packets without an advertising structure that matches one of the prefixes are
+//| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated.
+//| :param int buffer_size: the maximum number of advertising bytes to buffer.
+//| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set.
+//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called.
+//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows
+//| Must be in the range 0.0025 - 40.959375 seconds.
+//| :param float window: the duration (in seconds) to scan a single BLE channel.
+//| window must be <= interval.
+//| :param int minimum_rssi: the minimum rssi of entries to return.
+//| :param bool active: retrieve scan responses for scannable advertisements.
+//| :returns: an iterable of `_bleio.ScanEntry` objects
+//| :rtype: iterable
+//|
+STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_prefixes, ARG_buffer_size, ARG_extended, ARG_timeout, ARG_interval, ARG_window, ARG_minimum_rssi, ARG_active };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_prefixes, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} },
+ { MP_QSTR_extended, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_minimum_rssi, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -80} },
+ { MP_QSTR_active, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ };
+
+ bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ 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);
+
+ mp_float_t timeout = 0;
+ if (args[ARG_timeout].u_obj != MP_OBJ_NULL) {
+ timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
+ }
+
+ if (args[ARG_interval].u_obj == MP_OBJ_NULL) {
+ args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT);
+ }
+
+ if (args[ARG_window].u_obj == MP_OBJ_NULL) {
+ args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT);
+ }
+
+ const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj);
+ if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
+ mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING);
+ }
+
+ const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj);
+ if (window > interval) {
+ mp_raise_ValueError(translate("window must be <= interval"));
+ }
+
+ mp_buffer_info_t prefix_bufinfo;
+ prefix_bufinfo.len = 0;
+ if (args[ARG_prefixes].u_obj != MP_OBJ_NULL) {
+ mp_get_buffer_raise(args[ARG_prefixes].u_obj, &prefix_bufinfo, MP_BUFFER_READ);
+ if (gc_nbytes(prefix_bufinfo.buf) == 0) {
+ mp_raise_ValueError(translate("Prefix buffer must be on the heap"));
+ }
+ }
+
+ return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan);
+
+//| .. method:: stop_scan()
+//|
+//| Stop the current scan.
+STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) {
+ bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_adapter_stop_scan(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_scan_obj, bleio_adapter_stop_scan);
+
+//| .. attribute:: connected
//|
-//| default_name of the BLE adapter. (read-only)
-//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
-//| to make it easy to distinguish multiple CircuitPython boards.
+//| True when the adapter is connected to another device regardless of who initiated the
+//| connection. (read-only)
//|
-STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) {
- return common_hal_bleio_adapter_get_default_name();
+STATIC mp_obj_t bleio_adapter_get_connected(mp_obj_t self) {
+ return mp_obj_new_bool(common_hal_bleio_adapter_get_connected(self));
}
-MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name);
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connected_obj, bleio_adapter_get_connected);
-const mp_obj_property_t bleio_adapter_default_name_obj = {
+const mp_obj_property_t bleio_adapter_connected_obj = {
.base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_connected_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: connections
+//|
+//| Tuple of active connections including those initiated through
+//| :py:meth:`_bleio.Adapter.connect`. (read-only)
+//|
+STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) {
+ return common_hal_bleio_adapter_get_connections(self);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connections_obj, bleio_adapter_get_connections);
+
+const mp_obj_property_t bleio_adapter_connections_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_connections_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. method:: connect(address, *, timeout, pair=False)
+//|
+//| Attempts a connection to the device with the given address.
+//|
+//| :param Address address: The address of the peripheral to connect to
+//| :param float/int timeout: Try to connect for timeout seconds.
+//|
+STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_address, ARG_timeout, ARG_pair };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_pair, 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);
+
+ 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);
+
+ return common_hal_bleio_adapter_connect(self, address, timeout, args[ARG_pair].u_bool);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect);
+
+
STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) },
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) },
- { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_adapter_name_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_adapter_start_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_adapter_stop_advertising_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_start_scan), MP_ROM_PTR(&bleio_adapter_start_scan_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_scan), MP_ROM_PTR(&bleio_adapter_stop_scan_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_adapter_connect_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_adapter_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&bleio_adapter_connections_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table);
diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h
index 932fc9c95..95d19cb31 100644
--- a/shared-bindings/_bleio/Adapter.h
+++ b/shared-bindings/_bleio/Adapter.h
@@ -28,13 +28,33 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
+#include <stdint.h>
+
+#include "common-hal/_bleio/Adapter.h"
+
+#include "py/objstr.h"
#include "shared-module/_bleio/Address.h"
const mp_obj_type_t bleio_adapter_type;
-extern bool common_hal_bleio_adapter_get_enabled(void);
-extern void common_hal_bleio_adapter_set_enabled(bool enabled);
-extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(void);
-extern mp_obj_t common_hal_bleio_adapter_get_default_name(void);
+extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self);
+extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled);
+extern bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self);
+extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self);
+
+extern mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self);
+extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name);
+
+extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len);
+
+extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
+void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self);
+
+mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, uint8_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active);
+void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self);
+
+bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self);
+mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self);
+mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c
index cdee02b5d..c31eb604b 100644
--- a/shared-bindings/_bleio/Address.c
+++ b/shared-bindings/_bleio/Address.c
@@ -114,10 +114,11 @@ const mp_obj_property_t bleio_address_address_bytes_obj = {
};
//| .. attribute:: type
-//|
+//|
//| The address type (read-only).
-//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`,
-//| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`.
+//|
+//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, `RANDOM_PRIVATE_RESOLVABLE`,
+//| or `RANDOM_PRIVATE_NON_RESOLVABLE`.
//|
STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -159,6 +160,28 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o
}
}
+//| .. method:: __hash__()
+//|
+//| Returns a hash for the Address data.
+//|
+STATIC mp_obj_t bleio_address_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ switch (op) {
+ // Two Addresses are equal if their address bytes and address_type are equal
+ case MP_UNARY_OP_HASH: {
+ mp_obj_t bytes = common_hal_bleio_address_get_address_bytes(MP_OBJ_TO_PTR(self_in));
+ GET_STR_HASH(bytes, h);
+ if (h == 0) {
+ GET_STR_DATA_LEN(bytes, data, len);
+ h = qstr_compute_hash(data, len);
+ }
+ h ^= common_hal_bleio_address_get_type(MP_OBJ_TO_PTR(self_in));
+ return MP_OBJ_NEW_SMALL_INT(h);
+ }
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t buf_info;
@@ -205,6 +228,7 @@ const mp_obj_type_t bleio_address_type = {
.name = MP_QSTR_Address,
.make_new = bleio_address_make_new,
.print = bleio_address_print,
+ .unary_op = bleio_address_unary_op,
.binary_op = bleio_address_binary_op,
.locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict
};
diff --git a/shared-bindings/_bleio/Central.c b/shared-bindings/_bleio/Central.c
deleted file mode 100644
index 084f40cd6..000000000
--- a/shared-bindings/_bleio/Central.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2016 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <string.h>
-#include <stdio.h>
-
-#include "ble_drv.h"
-#include "py/objarray.h"
-#include "py/objproperty.h"
-#include "py/objstr.h"
-#include "py/runtime.h"
-#include "shared-bindings/_bleio/Adapter.h"
-#include "shared-bindings/_bleio/Address.h"
-#include "shared-bindings/_bleio/Characteristic.h"
-#include "shared-bindings/_bleio/Central.h"
-#include "shared-bindings/_bleio/Service.h"
-
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Central` -- A BLE central device
-//| =========================================================
-//|
-//| Implement a BLE central, which runs locally. Can connect to a given address.
-//|
-//| Usage::
-//|
-//| import _bleio
-//|
-//| scanner = _bleio.Scanner()
-//| entries = scanner.scan(2.5)
-//|
-//| my_entry = None
-//| for entry in entries:
-//| if entry.name is not None and entry.name == 'InterestingPeripheral':
-//| my_entry = entry
-//| break
-//|
-//| if not my_entry:
-//| raise Exception("'InterestingPeripheral' not found")
-//|
-//| central = _bleio.Central()
-//| central.connect(my_entry.address, 10) # timeout after 10 seconds
-//| remote_services = central.discover_remote_services()
-//|
-
-//| .. class:: Central()
-//|
-//| Create a new Central object.
-//|
-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, 0, 0, false);
-
- bleio_central_obj_t *self = m_new_obj(bleio_central_obj_t);
- self->base.type = &bleio_central_type;
-
- common_hal_bleio_central_construct(self);
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None)
-//| Attempts a connection to the remote peripheral.
-//|
-//| :param Address address: The address of the peripheral to connect to
-//| :param float/int timeout: Try to connect for timeout seconds.
-//|
-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]);
-
- enum { ARG_address, ARG_timeout, ARG_service_uuids_whitelist };
- 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_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);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_connect_obj, 3, bleio_central_connect);
-
-
-//| .. method:: disconnect()
-//|
-//| Disconnects from the remote peripheral.
-//|
-STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) {
- bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- common_hal_bleio_central_disconnect(self);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect);
-
-//| .. method:: discover_remote_services(service_uuids_whitelist=None)
-//| Do BLE discovery for all services or for the given service UUIDS,
-//| to find their handles and characteristics, and return the discovered services.
-//| `Peripheral.connected` must be True.
-//|
-//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`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
-//| and will not be returned.
-//|
-//| If service_uuids_whitelist 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 :py:class:~`UUID` object for that UUID in order for the
-//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
-//| for use. (This restriction may be lifted in the future.)
-//|
-//| :return: A tuple of services provided by the remote peripheral.
-//|
-STATIC mp_obj_t bleio_central_discover_remote_services(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]);
-
- enum { ARG_service_uuids_whitelist };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_service_uuids_whitelist, 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 (!common_hal_bleio_central_get_connected(self)) {
- mp_raise_ValueError(translate("Not connected"));
- }
-
- return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services(
- MP_OBJ_FROM_PTR(self),
- args[ARG_service_uuids_whitelist].u_obj));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services);
-
-//| .. attribute:: connected
-//|
-//| True if connected to a remove peripheral.
-//|
-STATIC mp_obj_t bleio_central_get_connected(mp_obj_t self_in) {
- bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_central_get_connected(self));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_connected_obj, bleio_central_get_connected);
-
-const mp_obj_property_t bleio_central_connected_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_central_get_connected_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = {
- // Methods
- { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) },
- { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) },
-
- // Properties
- { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table);
-
-const mp_obj_type_t bleio_central_type = {
- { &mp_type_type },
- .name = MP_QSTR_Central,
- .make_new = bleio_central_make_new,
- .locals_dict = (mp_obj_dict_t*)&bleio_central_locals_dict
-};
diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c
index 198155589..d89da2a2f 100644
--- a/shared-bindings/_bleio/Characteristic.c
+++ b/shared-bindings/_bleio/Characteristic.c
@@ -45,8 +45,8 @@
//|
//| There is no regular constructor for a Characteristic. A new local Characteristic can be created
//| and attached to a Service by calling `add_to_service()`.
-//| Remote Characteristic objects are created by `Central.discover_remote_services()`
-//| or `Peripheral.discover_remote_services()` as part of remote Services.
+//| Remote Characteristic objects are created by `Connection.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)
@@ -134,12 +134,10 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_
// 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),
+ characteristic, MP_OBJ_TO_PTR(service_obj), 0, 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);
@@ -170,7 +168,8 @@ const mp_obj_property_t bleio_characteristic_properties_obj = {
//| .. attribute:: uuid
//|
//| The UUID of this characteristic. (read-only)
-//| Will be ``None`` if the 128-bit UUID for this characteristic is not known.
+//|
+//| 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);
@@ -194,7 +193,9 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = {
STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return common_hal_bleio_characteristic_get_value(self);
+ uint8_t temp[512];
+ size_t actual_len = common_hal_bleio_characteristic_get_value(self, temp, sizeof(temp));
+ return mp_obj_new_bytearray(actual_len, temp);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value);
@@ -224,8 +225,20 @@ const mp_obj_property_t bleio_characteristic_value_obj = {
STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self);
- return mp_obj_new_tuple(char_list->len, char_list->items);
+ bleio_descriptor_obj_t *descriptors = common_hal_bleio_characteristic_get_descriptor_list(self);
+ bleio_descriptor_obj_t *head = descriptors;
+ size_t len = 0;
+ while (head != NULL) {
+ len++;
+ head = head->next;
+ }
+ mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL));
+ head = descriptors;
+ for (size_t i = len - 1; i >= 0; i--) {
+ t->items[i] = MP_OBJ_FROM_PTR(head);
+ head = head->next;
+ }
+ return MP_OBJ_FROM_PTR(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors);
@@ -282,7 +295,7 @@ 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[] = {
{ 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_properties), MP_ROM_PTR(&bleio_characteristic_properties_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_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h
index a816c6050..c4356fd4b 100644
--- a/shared-bindings/_bleio/Characteristic.h
+++ b/shared-bindings/_bleio/Characteristic.h
@@ -36,12 +36,12 @@
extern const mp_obj_type_t bleio_characteristic_type;
-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 void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, 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 size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len);
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_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self);
-extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self);
+extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self);
extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self);
extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor);
extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate);
diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c
new file mode 100644
index 000000000..1c6931b29
--- /dev/null
+++ b/shared-bindings/_bleio/Connection.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/_bleio/Connection.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include "ble_drv.h"
+#include "py/objarray.h"
+#include "py/objproperty.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Service.h"
+
+//| .. currentmodule:: _bleio
+//|
+//| :class:`Connection` -- A BLE connection
+//| =========================================================
+//|
+//| A BLE connection to another device. Used to discover and interact with services on the other
+//| device.
+//|
+//| Usage::
+//|
+//| import _bleio
+//|
+//| my_entry = None
+//| for entry in _bleio.adapter.scan(2.5):
+//| if entry.name is not None and entry.name == 'InterestingPeripheral':
+//| my_entry = entry
+//| break
+//|
+//| if not my_entry:
+//| raise Exception("'InterestingPeripheral' not found")
+//|
+//| connection = _bleio.adapter.connect(my_entry.address, timeout=10)
+//|
+
+STATIC void ensure_connected(bleio_connection_obj_t *self) {
+ if (!common_hal_bleio_connection_get_connected(self)) {
+ mp_raise_ValueError(translate("Connection has been disconnected and can no longer be used. Create a new connection."));
+ }
+}
+
+//| .. class:: Connection()
+//|
+//| Connections cannot be made directly. Instead, to initiate a connection use `Adapter.connect`.
+//| Connections may also be made when another device initiates a connection. To use a Connection
+//| created by a peer, read the `Adapter.connections` property.
+//|
+//| .. method:: disconnect()
+//|
+//| Disconnects from the remote peripheral.
+//|
+STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ ensure_connected(self);
+
+ common_hal_bleio_connection_disconnect(self->connection);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect);
+
+//| .. method:: discover_remote_services(service_uuids_whitelist=None)
+//|
+//| Do BLE discovery for all services or for the given service UUIDS,
+//| to find their handles and characteristics, and return the discovered services.
+//| `Connection.connected` must be True.
+//|
+//| :param iterable service_uuids_whitelist:
+//|
+//| an iterable of :py:class:~`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
+//| and will not be returned.
+//|
+//| If service_uuids_whitelist 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 :py:class:~`UUID` object for that UUID in order for the
+//| service or characteristic to be discovered. Creating the UUID causes the UUID to be
+//| registered for use. (This restriction may be lifted in the future.)
+//|
+//| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral.
+//|
+STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_service_uuids_whitelist };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service_uuids_whitelist, 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);
+
+ ensure_connected(self);
+
+ return MP_OBJ_FROM_PTR(common_hal_bleio_connection_discover_remote_services(
+ self,
+ args[ARG_service_uuids_whitelist].u_obj));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_discover_remote_services_obj, 1, bleio_connection_discover_remote_services);
+
+//| .. attribute:: connected
+//|
+//| True if connected to a remote peer.
+//|
+STATIC mp_obj_t bleio_connection_get_connected(mp_obj_t self_in) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(common_hal_bleio_connection_get_connected(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connected_obj, bleio_connection_get_connected);
+
+const mp_obj_property_t bleio_connection_connected_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_connection_get_connected_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_connection_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_connection_discover_remote_services_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table);
+
+const mp_obj_type_t bleio_connection_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Connection,
+ .locals_dict = (mp_obj_dict_t*)&bleio_connection_locals_dict,
+ .unary_op = mp_generic_unary_op,
+};
diff --git a/shared-bindings/_bleio/Central.h b/shared-bindings/_bleio/Connection.h
index 85d788654..5de6730c9 100644
--- a/shared-bindings/_bleio/Central.h
+++ b/shared-bindings/_bleio/Connection.h
@@ -25,19 +25,17 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H
#include "py/objtuple.h"
-#include "common-hal/_bleio/Central.h"
+#include "common-hal/_bleio/Connection.h"
#include "common-hal/_bleio/Service.h"
-extern const mp_obj_type_t bleio_central_type;
+extern const mp_obj_type_t bleio_connection_type;
-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);
-extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self);
-extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self);
-extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist);
+extern void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self);
+extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self);
+extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H
diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c
index 0ab9fe8e9..45a95903e 100644
--- a/shared-bindings/_bleio/Descriptor.c
+++ b/shared-bindings/_bleio/Descriptor.c
@@ -46,9 +46,8 @@
//|
//| There is no regular constructor for a Descriptor. A new local Descriptor can be created
//| and attached to a Characteristic by calling `add_to_characteristic()`.
-//| Remote Descriptor objects are created by `Central.discover_remote_services()`
-//| or `Peripheral.discover_remote_services()` as part of remote Characteristics
-//| in the remote Services that are discovered.
+//| Remote Descriptor objects are created by `Connection.discover_remote_services()`
+//| as part of remote Characteristics in the remote Services that are discovered.
//|
//| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
//|
@@ -180,7 +179,9 @@ const mp_obj_property_t bleio_descriptor_characteristic_obj = {
STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) {
bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return common_hal_bleio_descriptor_get_value(self);
+ uint8_t temp[512];
+ size_t actual_len = common_hal_bleio_descriptor_get_value(self, temp, sizeof(temp));
+ return mp_obj_new_bytearray(actual_len, temp);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value);
diff --git a/shared-bindings/_bleio/Descriptor.h b/shared-bindings/_bleio/Descriptor.h
index 7544bdb17..273cb1c1e 100644
--- a/shared-bindings/_bleio/Descriptor.h
+++ b/shared-bindings/_bleio/Descriptor.h
@@ -38,7 +38,7 @@ extern const mp_obj_type_t bleio_descriptor_type;
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_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 size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len);
extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
diff --git a/shared-bindings/_bleio/Peripheral.c b/shared-bindings/_bleio/Peripheral.c
deleted file mode 100644
index 0bf292744..000000000
--- a/shared-bindings/_bleio/Peripheral.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2016 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <string.h>
-#include <stdio.h>
-
-#include "ble_drv.h"
-#include "py/objarray.h"
-#include "py/objproperty.h"
-#include "py/objstr.h"
-#include "py/runtime.h"
-
-#include "shared-bindings/_bleio/Adapter.h"
-#include "shared-bindings/_bleio/Characteristic.h"
-#include "shared-bindings/_bleio/Peripheral.h"
-#include "shared-bindings/_bleio/Service.h"
-#include "shared-bindings/_bleio/UUID.h"
-#include "shared-module/_bleio/ScanEntry.h"
-
-#include "common-hal/_bleio/Peripheral.h"
-
-#define ADV_INTERVAL_MIN (0.0020f)
-#define ADV_INTERVAL_MIN_STRING "0.0020"
-#define ADV_INTERVAL_MAX (10.24f)
-#define ADV_INTERVAL_MAX_STRING "10.24"
-// 20ms is recommended by Apple
-#define ADV_INTERVAL_DEFAULT (0.1f)
-
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Peripheral` -- A BLE peripheral device
-//| =========================================================
-//|
-//| Implement a BLE peripheral which runs locally.
-//| Set up using the supplied services, and then allow advertising to be started and stopped.
-//|
-//| Usage::
-//|
-//| from _bleio import Characteristic, Peripheral, Service
-//| from adafruit_ble.advertising import ServerAdvertisement
-//|
-//| # Create a peripheral and start it up.
-//| peripheral = _bleio.Peripheral()
-//|
-//| # Create a Service and add it to this Peripheral.
-//| service = Service.add_to_peripheral(peripheral, _bleio.UUID(0x180f))
-//|
-//| # Create a Characteristic and add it to the Service.
-//| characteristic = Characteristic.add_to_service(service,
-//| _bleio.UUID(0x2919), properties=Characteristic.READ | Characteristic.NOTIFY)
-//|
-//| adv = ServerAdvertisement(peripheral)
-//| peripheral.start_advertising(adv.advertising_data_bytes, scan_response=adv.scan_response_bytes)
-//|
-//| while not peripheral.connected:
-//| # Wait for connection.
-//| pass
-//|
-//| .. class:: Peripheral(name=None)
-//|
-//| Create a new Peripheral object.
-//|
-//| :param str name: The name used when advertising this peripheral. If name is None,
-//| _bleio.adapter.default_name will be used.
-//|
-STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_name };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_name, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- };
-
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- bleio_peripheral_obj_t *self = m_new_obj(bleio_peripheral_obj_t);
- self->base.type = &bleio_peripheral_type;
-
- mp_obj_t name = args[ARG_name].u_obj;
- if (name == mp_const_none) {
- name = common_hal_bleio_adapter_get_default_name();
- } else if (!MP_OBJ_IS_STR(name)) {
- mp_raise_ValueError(translate("name must be a string"));
- }
-
- common_hal_bleio_peripheral_construct(self, name);
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-//| .. attribute:: connected (read-only)
-//|
-//| True if connected to a BLE Central device.
-//|
-STATIC mp_obj_t bleio_peripheral_get_connected(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_peripheral_get_connected(self));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_connected_obj, bleio_peripheral_get_connected);
-
-const mp_obj_property_t bleio_peripheral_connected_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_peripheral_get_connected_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: services
-//|
-//| A tuple of :py:class:`Service` objects offered by this peripheral. (read-only)
-//|
-STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
- // Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self);
- return mp_obj_new_tuple(services_list->len, services_list->items);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services);
-
-const mp_obj_property_t bleio_peripheral_services_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_peripheral_get_services_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: name
-//|
-//| The peripheral's name, included when advertising. (read-only)
-//|
-STATIC mp_obj_t bleio_peripheral_get_name(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return common_hal_bleio_peripheral_get_name(self);
-}
-MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_name_obj, bleio_peripheral_get_name);
-
-const mp_obj_property_t bleio_peripheral_name_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_peripheral_get_name_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1)
-//|
-//| Starts advertising the peripheral. The peripheral's name and
-//| services are included in the advertisement packets.
-//|
-//| :param buf data: advertising data packet bytes
-//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
-//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
-//| :param float interval: advertising interval, in seconds
-//|
-STATIC mp_obj_t bleio_peripheral_start_advertising(mp_uint_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_data, ARG_scan_response, ARG_connectable, ARG_interval };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
- { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- };
-
- 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);
-
- mp_buffer_info_t data_bufinfo;
- mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ);
-
- // Pass an empty buffer if scan_response not provided.
- mp_buffer_info_t scan_response_bufinfo = { 0 };
- if (args[ARG_scan_response].u_obj != mp_const_none) {
- mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ);
- }
-
- if (args[ARG_interval].u_obj == MP_OBJ_NULL) {
- args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT);
- }
-
- const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj);
- if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) {
- mp_raise_ValueError_varg(translate("interval must be in range %s-%s"),
- ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING);
- }
-
- common_hal_bleio_peripheral_start_advertising(self, args[ARG_connectable].u_bool, interval,
- &data_bufinfo, &scan_response_bufinfo);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_start_advertising_obj, 2, bleio_peripheral_start_advertising);
-
-//| .. method:: stop_advertising()
-//|
-//| Stop sending advertising packets.
-STATIC mp_obj_t bleio_peripheral_stop_advertising(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- common_hal_bleio_peripheral_stop_advertising(self);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_stop_advertising_obj, bleio_peripheral_stop_advertising);
-
-//| .. method:: disconnect()
-//|
-//| Disconnects from the remote central.
-//| Normally the central initiates a disconnection. Use this only
-//| if necessary for your application.
-//|
-STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- common_hal_bleio_peripheral_disconnect(self);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect);
-
-//| .. method:: discover_remote_services(service_uuids_whitelist=None)
-//| Do BLE discovery for all services or for the given service UUIDS,
-//| to find their handles and characteristics, and return the discovered services.
-//| `Peripheral.connected` must be True.
-//|
-//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`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
-//| and will not be returned.
-//|
-//| If service_uuids_whitelist 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 :py:class:~`UUID` object for that UUID in order for the
-//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
-//| for use. (This restriction may be lifted in the future.)
-//|
-//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and
-//| needs to be able to do discovery on its peer (a central).
-//| Examples include a peripheral accessing a central that provides Current Time Service,
-//| Apple Notification Center Service, or Battery Service.
-//|
-//| :return: A tuple of services provided by the remote central.
-//|
-STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_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_service_uuids_whitelist };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_service_uuids_whitelist, 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 (!common_hal_bleio_peripheral_get_connected(self)) {
- mp_raise_ValueError(translate("Not connected"));
- }
-
- return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services(
- MP_OBJ_FROM_PTR(self),
- args[ARG_service_uuids_whitelist].u_obj));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services);
-
-//| .. method:: pair()
-//|
-//| Request pairing with connected central.
-STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) {
- bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- common_hal_bleio_peripheral_pair(self);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair);
-
-STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = {
- // Methods
- { 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_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
- { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) },
- { MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_peripheral_pair_obj) },
-
- // Properties
- { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) },
- { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table);
-
-const mp_obj_type_t bleio_peripheral_type = {
- { &mp_type_type },
- .name = MP_QSTR_Peripheral,
- .make_new = bleio_peripheral_make_new,
- .locals_dict = (mp_obj_dict_t*)&bleio_peripheral_locals_dict
-};
diff --git a/shared-bindings/_bleio/Peripheral.h b/shared-bindings/_bleio/Peripheral.h
deleted file mode 100644
index bc56a9338..000000000
--- a/shared-bindings/_bleio/Peripheral.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
-
-#include "py/objtuple.h"
-#include "common-hal/_bleio/Peripheral.h"
-#include "common-hal/_bleio/Service.h"
-
-extern const mp_obj_type_t bleio_peripheral_type;
-
-extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name);
-extern void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service);
-extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self);
-extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self);
-extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self);
-extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
-extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device);
-extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device);
-extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist);
-extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device);
-
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c
index bec380d03..d03cd6fb5 100644
--- a/shared-bindings/_bleio/ScanEntry.c
+++ b/shared-bindings/_bleio/ScanEntry.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "py/objproperty.h"
+#include "py/runtime.h"
#include "shared-bindings/_bleio/Address.h"
#include "shared-bindings/_bleio/ScanEntry.h"
#include "shared-bindings/_bleio/UUID.h"
@@ -36,14 +37,43 @@
//| .. currentmodule:: _bleio
//|
-//| :class:`ScanEntry` -- BLE scan response entry
+//| :class:`ScanEntry` -- BLE scan data
//| =========================================================
//|
-//| Encapsulates information about a device that was received as a
-//| response to a BLE scan request. This object may only be created
-//| by a `_bleio.Scanner`: it has no user-visible constructor.
+//| Encapsulates information about a device that was received during scanning. It can be
+//| advertisement or scan response data. This object may only be created by a `_bleio.ScanResults`:
+//| it has no user-visible constructor.
//|
+//| .. class:: ScanEntry()
+//|
+//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`.
+//|
+//| .. method:: matches(prefixes, *, all=True)
+//|
+//| Returns True if the ScanEntry matches all prefixes when ``all`` is True. This is stricter
+//| than the scan filtering which accepts any advertisements that match any of the prefixes
+//| where all is False.
+//|
+STATIC mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_prefixes, ARG_all };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_prefixes, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_all, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ };
+
+ 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);
+
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[ARG_prefixes].u_obj, &bufinfo, MP_BUFFER_READ);
+ return mp_obj_new_bool(common_hal_bleio_scanentry_matches(self, bufinfo.buf, bufinfo.len, args[ARG_all].u_bool));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanentry_matches_obj, 2, bleio_scanentry_matches);
+
//| .. attribute:: address
//|
//| The address of the device (read-only), of type `_bleio.Address`.
@@ -95,11 +125,47 @@ const mp_obj_property_t bleio_scanentry_rssi_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: connectable
+//|
+//| True if the device can be connected to. (read-only)
+//|
+STATIC mp_obj_t scanentry_get_connectable(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(common_hal_bleio_scanentry_get_connectable(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_connectable_obj, scanentry_get_connectable);
+
+const mp_obj_property_t bleio_scanentry_connectable_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_scanentry_get_connectable_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: scan_response
+//|
+//| True if the entry was a scan response. (read-only)
+//|
+STATIC mp_obj_t scanentry_get_scan_response(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(common_hal_bleio_scanentry_get_scan_response(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_scan_response_obj, scanentry_get_scan_response);
+
+const mp_obj_property_t bleio_scanentry_scan_response_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_scanentry_get_scan_response_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) },
{ MP_ROM_QSTR(MP_QSTR_advertisement_bytes), MP_ROM_PTR(&bleio_scanentry_advertisement_bytes_obj) },
{ MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connectable), MP_ROM_PTR(&bleio_scanentry_connectable_obj) },
+ { MP_ROM_QSTR(MP_QSTR_scan_response), MP_ROM_PTR(&bleio_scanentry_scan_response_obj) },
+ { MP_ROM_QSTR(MP_QSTR_matches), MP_ROM_PTR(&bleio_scanentry_matches_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table);
diff --git a/shared-bindings/_bleio/ScanEntry.h b/shared-bindings/_bleio/ScanEntry.h
index 8af1f050a..9aeaf20d3 100644
--- a/shared-bindings/_bleio/ScanEntry.h
+++ b/shared-bindings/_bleio/ScanEntry.h
@@ -37,5 +37,8 @@ extern const mp_obj_type_t bleio_scanentry_type;
mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self);
mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self);
mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self);
+bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self);
+bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self);
+bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, uint8_t* prefixes, size_t prefixes_len, bool all);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H
diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c
new file mode 100644
index 000000000..dcece3d5d
--- /dev/null
+++ b/shared-bindings/_bleio/ScanResults.c
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/ScanResults.h"
+
+//| .. currentmodule:: _bleio
+//|
+//| :class:`ScanResults` -- An Iterator over BLE scanning results
+//| ===============================================================
+//|
+//| Iterates over advertising data received while scanning. This object is always created
+//| by a `_bleio.Adapter`: it has no user-visible constructor.
+//|
+STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &bleio_scanresults_type));
+ bleio_scanresults_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t scan_entry = common_hal_bleio_scanresults_next(self);
+ if (scan_entry != mp_const_none) {
+ return scan_entry;
+ }
+ return MP_OBJ_STOP_ITERATION;
+}
+
+//| .. class:: ScanResults()
+//|
+//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`.
+//|
+//| .. method:: __iter__()
+//|
+//| Returns itself since it is the iterator.
+//|
+//| .. method:: __next__()
+//|
+//| Returns the next `_bleio.ScanEntry`. Blocks if none have been received and scanning is still
+//| active. Raises `StopIteration` if scanning is finished and no other results are available.
+//|
+
+const mp_obj_type_t bleio_scanresults_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ScanResults,
+ .getiter = mp_identity_getiter,
+ .iternext = scanresults_iternext,
+};
diff --git a/shared-bindings/_bleio/Scanner.h b/shared-bindings/_bleio/ScanResults.h
index cbaa77866..a8c88c215 100644
--- a/shared-bindings/_bleio/Scanner.h
+++ b/shared-bindings/_bleio/ScanResults.h
@@ -5,6 +5,7 @@
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,16 +26,14 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H
-#include "py/objtype.h"
-#include "common-hal/_bleio/Scanner.h"
+#include "py/obj.h"
+#include "shared-module/_bleio/ScanResults.h"
-extern const mp_obj_type_t bleio_scanner_type;
+extern const mp_obj_type_t bleio_scanresults_type;
-extern void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self);
-extern mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window);
-extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self);
+mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H
diff --git a/shared-bindings/_bleio/Scanner.c b/shared-bindings/_bleio/Scanner.c
deleted file mode 100644
index 94cec9752..000000000
--- a/shared-bindings/_bleio/Scanner.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "py/objproperty.h"
-#include "py/runtime.h"
-#include "shared-bindings/_bleio/ScanEntry.h"
-#include "shared-bindings/_bleio/Scanner.h"
-
-#define INTERVAL_DEFAULT (0.1f)
-#define INTERVAL_MIN (0.0025f)
-#define INTERVAL_MIN_STRING "0.0025"
-#define INTERVAL_MAX (40.959375f)
-#define INTERVAL_MAX_STRING "40.959375"
-#define WINDOW_DEFAULT (0.1f)
-
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Scanner` -- scan for nearby BLE devices
-//| =========================================================
-//|
-//| Scan for nearby BLE devices.
-//|
-//| Usage::
-//|
-//| import _bleio
-//| scanner = _bleio.Scanner()
-//| entries = scanner.scan(2.5) # Scan for 2.5 seconds
-//|
-
-//| .. class:: Scanner()
-//|
-//| Create a new Scanner object.
-//|
-STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) {
- mp_arg_check_num(n_args, kw_args, 0, 0, false);
-
- bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t);
- self->base.type = type;
-
- common_hal_bleio_scanner_construct(self);
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-//| .. method:: scan(timeout, \*, interval=0.1, window=0.1)
-//|
-//| Performs a BLE scan.
-//|
-//| :param float timeout: the scan timeout in seconds
-//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows
-//| Must be in the range 0.0025 - 40.959375 seconds.
-//| :param float window: the duration (in seconds) to scan a single BLE channel.
-//| window must be <= interval.
-//| :returns: an iterable of `ScanEntry` objects
-//| :rtype: iterable
-//|
-STATIC mp_obj_t bleio_scanner_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_timeout, ARG_interval, ARG_window };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- };
-
- bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- 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_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
-
- if (args[ARG_interval].u_obj == MP_OBJ_NULL) {
- args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT);
- }
-
- if (args[ARG_window].u_obj == MP_OBJ_NULL) {
- args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT);
- }
-
- const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj);
- if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
- mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING);
- }
-
- const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj);
- if (window > interval) {
- mp_raise_ValueError(translate("window must be <= interval"));
- }
-
- return common_hal_bleio_scanner_scan(self, timeout, interval, window);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanner_scan_obj, 2, bleio_scanner_scan);
-
-
-STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(bleio_scanner_locals_dict, bleio_scanner_locals_dict_table);
-
-const mp_obj_type_t bleio_scanner_type = {
- { &mp_type_type },
- .name = MP_QSTR_Scanner,
- .make_new = bleio_scanner_make_new,
- .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict
-};
diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c
index da5633f2a..68605cec0 100644
--- a/shared-bindings/_bleio/Service.c
+++ b/shared-bindings/_bleio/Service.c
@@ -29,54 +29,38 @@
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/_bleio/Characteristic.h"
-#include "shared-bindings/_bleio/Peripheral.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
//| .. currentmodule:: _bleio
//|
-//| :class:`Service` -- BLE service
+//| :class:`Service` -- BLE GATT Service
//| =========================================================
//|
//| Stores information about a BLE service and its characteristics.
//|
-//| .. class:: Service
+//| .. class:: Service(uuid, *, secondary=False)
//|
-//| There is no regular constructor for a Service. A new local Service can be created
-//| and attached to a Peripheral by calling `add_to_peripheral()`.
-//| Remote Service objects are created by `Central.discover_remote_services()`
-//| or `Peripheral.discover_remote_services()`.
+//| Create a new Service identitied by the specified UUID. It can be accessed by all
+//| connections. This is known as a Service server. Client Service objects are created via
+//| `Connection.discover_remote_services`.
//|
-//| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False)
+//| To mark the Server as secondary, pass `True` as :py:data:`secondary`.
//|
-//| 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 Peripheral peripheral: The peripheral that will provide this service
-//| :param UUID uuid: The uuid of the service
-//| :param bool secondary: If the service is a secondary one
+//| :param UUID uuid: The uuid of the server
+//| :param bool secondary: If the server is a secondary one
//
-//| :return: the new Service
+//| :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 mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { 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"));
- }
+ mp_arg_parse_all(n_args, pos_args, 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)) {
@@ -88,19 +72,15 @@ STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *p
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);
+ common_hal_bleio_service_construct(service, MP_OBJ_TO_PTR(uuid_obj), is_secondary);
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
//|
-//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by this service. (read-only)
+//| A tuple of :py:class:`Characteristic` designating the characteristics 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);
@@ -156,7 +136,8 @@ 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.
+//|
+//| 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);
@@ -175,10 +156,10 @@ 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_to_peripheral), MP_ROM_PTR(&bleio_service_add_to_peripheral_obj) },
{ MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
{ 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) },
+ { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table);
@@ -196,6 +177,25 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
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
};
+
+// Helper for classes that store lists of services.
+mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services) {
+ // Return list as a tuple so user won't be able to change it.
+ bleio_service_obj_t *head = services;
+ size_t len = 0;
+ while (head != NULL) {
+ len++;
+ head = head->next;
+ }
+ mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL));
+ head = services;
+ for (int32_t i = len - 1; i >= 0; i--) {
+ t->items[i] = MP_OBJ_FROM_PTR(head);
+ head = head->next;
+ }
+ return t;
+}
diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h
index e061bcffc..273c6bd98 100644
--- a/shared-bindings/_bleio/Service.h
+++ b/shared-bindings/_bleio/Service.h
@@ -28,16 +28,24 @@
#ifndef 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/Characteristic.h"
+#include "common-hal/_bleio/Connection.h"
#include "common-hal/_bleio/Service.h"
+#include "py/objtuple.h"
+
const mp_obj_type_t bleio_service_type;
-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);
+// Private version that doesn't allocate on the heap
+extern uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list);
+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_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t* connection, 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 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_secondary(bleio_service_obj_t *self);
-extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic);
+extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo);
+
+mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c
index 3c0889aad..dd3415902 100644
--- a/shared-bindings/_bleio/UUID.c
+++ b/shared-bindings/_bleio/UUID.c
@@ -156,9 +156,10 @@ STATIC mp_obj_t bleio_uuid_get_uuid128(mp_obj_t self_in) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint8_t uuid128[16];
- if (!common_hal_bleio_uuid_get_uuid128(self, uuid128)) {
+ if (common_hal_bleio_uuid_get_size(self) != 128) {
mp_raise_AttributeError(translate("not a 128-bit UUID"));
}
+ common_hal_bleio_uuid_get_uuid128(self, uuid128);
return mp_obj_new_bytes(uuid128, 16);
}
@@ -192,10 +193,42 @@ const mp_obj_property_t bleio_uuid_size_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+
+//| .. method:: pack_into(buffer, offset=0)
+//|
+//| Packs the UUID into the given buffer at the given offset.
+//|
+STATIC mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_buffer, ARG_offset };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ };
+
+ 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);
+
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
+
+ size_t offset = args[ARG_offset].u_int;
+ if (offset + common_hal_bleio_uuid_get_size(self) / 8 > bufinfo.len) {
+ mp_raise_ValueError(translate("Buffer + offset too small %d %d %d"));
+ }
+
+ common_hal_bleio_uuid_pack_into(self, bufinfo.buf + offset);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_uuid_pack_into_obj, 2, bleio_uuid_pack_into);
+
STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_uuid16), MP_ROM_PTR(&bleio_uuid_uuid16_obj) },
{ MP_ROM_QSTR(MP_QSTR_uuid128), MP_ROM_PTR(&bleio_uuid_uuid128_obj) },
{ MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&bleio_uuid_size_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pack_into), MP_ROM_PTR(&bleio_uuid_pack_into_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table);
@@ -231,13 +264,19 @@ STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
//|
STATIC mp_obj_t bleio_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
switch (op) {
- // Two UUID's are equal if their uuid16 values and uuid128 references match.
+ // Two UUID's are equal if their uuid16 values match or their uuid128 values match.
case MP_BINARY_OP_EQUAL:
if (MP_OBJ_IS_TYPE(rhs_in, &bleio_uuid_type)) {
- return mp_obj_new_bool(
- common_hal_bleio_uuid_get_uuid16(lhs_in) == common_hal_bleio_uuid_get_uuid16(rhs_in) &&
- common_hal_bleio_uuid_get_uuid128_reference(lhs_in) ==
- common_hal_bleio_uuid_get_uuid128_reference(rhs_in));
+ if (common_hal_bleio_uuid_get_size(lhs_in) == 16 &&
+ common_hal_bleio_uuid_get_size(rhs_in) == 16) {
+ return mp_obj_new_bool(common_hal_bleio_uuid_get_uuid16(lhs_in) ==
+ common_hal_bleio_uuid_get_uuid16(rhs_in));
+ }
+ uint8_t lhs[16];
+ uint8_t rhs[16];
+ common_hal_bleio_uuid_get_uuid128(lhs_in, lhs);
+ common_hal_bleio_uuid_get_uuid128(rhs_in, rhs);
+ return mp_obj_new_bool(memcmp(lhs, rhs, sizeof(lhs)) == 0);
} else {
return mp_const_false;
}
diff --git a/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h
index 46ac54ff3..1490737a7 100644
--- a/shared-bindings/_bleio/UUID.h
+++ b/shared-bindings/_bleio/UUID.h
@@ -34,10 +34,11 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
extern const mp_obj_type_t bleio_uuid_type;
-extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, uint8_t uuid128[]);
+extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[]);
extern uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self);
extern bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]);
-extern uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self);
extern uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self);
+void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c
index f207be8cf..0c6ebb973 100644
--- a/shared-bindings/_bleio/__init__.c
+++ b/shared-bindings/_bleio/__init__.c
@@ -29,13 +29,12 @@
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Address.h"
#include "shared-bindings/_bleio/Attribute.h"
-#include "shared-bindings/_bleio/Central.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
+#include "shared-bindings/_bleio/Connection.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"
+#include "shared-bindings/_bleio/ScanResults.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
@@ -64,34 +63,32 @@
//| Address
//| Adapter
//| Attribute
-//| Central
//| Characteristic
//| CharacteristicBuffer
+//| Connection
//| Descriptor
-//| Peripheral
//| ScanEntry
-//| Scanner
+//| ScanResults
//| Service
//| UUID
//|
//| .. attribute:: adapter
//|
-//| BLE Adapter information, such as enabled state as well as MAC
-//| address.
+//| BLE Adapter used to manage device discovery and connections.
//| This object is the sole instance of `_bleio.Adapter`.
//|
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_Adapter), MP_ROM_PTR(&bleio_adapter_type) },
{ MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
{ MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) },
- { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) },
+ { MP_ROM_QSTR(MP_QSTR_Connection), MP_ROM_PTR(&bleio_connection_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) },
- { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
{ MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
- { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanResults), MP_ROM_PTR(&bleio_scanresults_type) },
{ MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
{ MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h
index 67379ae2e..92c695fa6 100644
--- a/shared-bindings/_bleio/__init__.h
+++ b/shared-bindings/_bleio/__init__.h
@@ -36,17 +36,19 @@
#include "common-hal/_bleio/__init__.h"
#include "common-hal/_bleio/Adapter.h"
-extern const super_adapter_obj_t common_hal_bleio_adapter_obj;
+extern bleio_adapter_obj_t common_hal_bleio_adapter_obj;
-extern void common_hal_bleio_check_connected(uint16_t conn_handle);
+void common_hal_bleio_check_connected(uint16_t conn_handle);
-extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
-extern mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device);
-extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist);
+uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
+mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device);
+void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist);
-extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle);
-extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo);
-extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response);
+size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len);
+void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo);
+size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len);
+void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response);
+void common_hal_bleio_gc_collect(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H