diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2018-11-07 12:03:46 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-07 12:03:46 -0800 |
| commit | d08747d374057b24803b429bbf6474a2e4dcea5c (patch) | |
| tree | c3bfee81668dbd842039c178222fda9df77a9b76 /shared-bindings | |
| parent | 283e07254e9eb50e52d6f07b7ac177feeef02d83 (diff) | |
| parent | 64d457dad9bb3843ee468136022996ecb91a98df (diff) | |
Merge pull request #1319 from dhalbert/origin/arturo182_bleio_pr_1289
Resubmit PR #1289, "WIP: bleio rewrite" by @arturo182
Diffstat (limited to 'shared-bindings')
25 files changed, 2557 insertions, 15 deletions
diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/bleio/Adapter.c index bfe87071d..d9449d3ab 100644 --- a/shared-bindings/bleio/Adapter.c +++ b/shared-bindings/bleio/Adapter.c @@ -25,6 +25,7 @@ */ #include "py/objproperty.h" +#include "shared-bindings/bleio/Address.h" #include "shared-bindings/bleio/Adapter.h" //| .. currentmodule:: bleio @@ -57,8 +58,6 @@ //| MAC address of the BLE adapter. (read-only) //| -#define BLE_ADDRESS_LEN 17 - STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) { return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled()); } @@ -81,16 +80,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = { }; STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) { - vstr_t vstr; - vstr_init(&vstr, BLE_ADDRESS_LEN); - - common_hal_bleio_adapter_get_address(&vstr); - - const mp_obj_t mac_str = mp_obj_new_str(vstr.buf, vstr.len); + mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none); + bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj); - vstr_clear(&vstr); + common_hal_bleio_adapter_get_address(address); - return mac_str; + return obj; } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address); diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/bleio/Adapter.h index 6c5d56948..fe3886e59 100644 --- a/shared-bindings/bleio/Adapter.h +++ b/shared-bindings/bleio/Adapter.h @@ -27,12 +27,12 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H -#include "py/obj.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 void common_hal_bleio_adapter_get_address(vstr_t *address); +extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c new file mode 100644 index 000000000..ec23ff207 --- /dev/null +++ b/shared-bindings/bleio/Address.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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 <string.h> +#include <stdio.h> + +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-module/bleio/Address.h" + +#define ADDRESS_LONG_LEN 17 // XX:XX:XX:XX:XX:XX +#define ADDRESS_SHORT_LEN 12 // XXXXXXXXXXXX + +//| .. currentmodule:: bleio +//| +//| :class:`Address` -- BLE address +//| ========================================================= +//| +//| Encapsulates the address of a BLE device. +//| + +//| .. class:: Address(address) +//| +//| Create a new Address object encapsulating the address value. +//| The value itself can be one of: +//| +//| - a `str` value in the format of 'XXXXXXXXXXXX' or 'XX:XX:XX:XX:XX' +//| - a `bytes` or `bytearray` containing 6 bytes +//| - another Address object +//| +//| :param address: The address to encapsulate +//| + +//| .. attribute:: type +//| +//| The address type. One of: +//| +//| - `bleio.AddressType.PUBLIC` +//| - `bleio.AddressType.RANDOM_STATIC` +//| - `bleio.AddressType.RANDOM_PRIVATE_RESOLVABLE` +//| - `bleio.AddressType.RANDOM_PRIVATE_NON_RESOLVABLE` +//| +STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_address_obj_t *self = m_new_obj(bleio_address_obj_t); + self->base.type = &bleio_address_type; + self->type = ADDRESS_PUBLIC; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_address }; + static const mp_arg_t allowed_args[] = { + { ARG_address, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t address = args[ARG_address].u_obj; + + if (MP_OBJ_IS_STR(address)) { + GET_STR_DATA_LEN(address, str_data, str_len); + const bool is_long = (str_len == ADDRESS_LONG_LEN); + const bool is_short = (str_len == ADDRESS_SHORT_LEN); + + if (is_long || is_short) { + size_t i = str_len - 1; + for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) { + self->value[b] = unichar_xdigit_value(str_data[i]) | + unichar_xdigit_value(str_data[i - 1]) << 4; + + i -= is_long ? 3 : 2; + } + } else { + mp_raise_ValueError(translate("Wrong address length")); + } + } else if (MP_OBJ_IS_TYPE(address, &mp_type_bytearray) || MP_OBJ_IS_TYPE(address, &mp_type_bytes)) { + mp_buffer_info_t buf_info; + mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); + if (buf_info.len != BLEIO_ADDRESS_BYTES) { + mp_raise_ValueError(translate("Wrong number of bytes provided")); + } + + for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) { + self->value[BLEIO_ADDRESS_BYTES - b - 1] = ((uint8_t*)buf_info.buf)[b]; + } + } else if (MP_OBJ_IS_TYPE(address, &bleio_address_type)) { + // deep copy + bleio_address_obj_t *other = MP_OBJ_TO_PTR(address); + self->type = other->type; + memcpy(self->value, other->value, BLEIO_ADDRESS_BYTES); + } + + return MP_OBJ_FROM_PTR(self); +} + +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_printf(print, "Address('"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"')", + self->value[5], self->value[4], self->value[3], + self->value[2], self->value[1], self->value[0]); +} + +STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) { + bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->type == ADDRESS_PUBLIC) { + return (mp_obj_t)&bleio_addresstype_public_obj; + } else if (self->type == ADDRESS_RANDOM_STATIC) { + return (mp_obj_t)&bleio_addresstype_random_static_obj; + } else if (self->type == ADDRESS_RANDOM_PRIVATE_RESOLVABLE) { + return (mp_obj_t)&bleio_addresstype_random_private_resolvable_obj; + } else if (self->type == ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE) { + return (mp_obj_t)&bleio_addresstype_random_private_non_resolvable_obj; + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_address_get_type_obj, bleio_address_get_type); + +const mp_obj_property_t bleio_address_type_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_address_get_type_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict_table); + +const mp_obj_type_t bleio_address_type = { + { &mp_type_type }, + .name = MP_QSTR_Address, + .print = bleio_address_print, + .make_new = bleio_address_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict +}; diff --git a/shared-bindings/bleio/Address.h b/shared-bindings/bleio/Address.h new file mode 100644 index 000000000..9c9e20968 --- /dev/null +++ b/shared-bindings/bleio/Address.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_ADDRESS_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H + +#include "py/objtype.h" + +extern const mp_obj_type_t bleio_address_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H diff --git a/shared-bindings/bleio/AddressType.c b/shared-bindings/bleio/AddressType.c new file mode 100644 index 000000000..cf2151c94 --- /dev/null +++ b/shared-bindings/bleio/AddressType.c @@ -0,0 +1,99 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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 "shared-bindings/bleio/AddressType.h" + +//| .. currentmodule:: bleio +//| +//| :class:`AddressType` -- defines the type of a BLE address +//| ============================================================= +//| +//| .. class:: bleio.AddressType +//| +//| Enum-like class to define the type of a BLE address, see also `bleio.Address`. +//| +//| .. data:: PUBLIC +//| +//| The address is public +//| +//| .. data:: RANDOM_STATIC +//| +//| The address is random static +//| +//| .. data:: RANDOM_PRIVATE_RESOLVABLE +//| +//| The address is random private resolvable +//| +//| .. data:: RANDOM_PRIVATE_NON_RESOLVABLE +//| +//| The address is private non-resolvable +//| +const mp_obj_type_t bleio_addresstype_type; + +const bleio_addresstype_obj_t bleio_addresstype_public_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_static_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj = { + { &bleio_addresstype_type }, +}; + +STATIC const mp_rom_map_elem_t bleio_addresstype_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_PTR(&bleio_addresstype_public_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_PTR(&bleio_addresstype_random_static_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bleio_addresstype_locals_dict, bleio_addresstype_locals_dict_table); + +STATIC void bleio_addresstype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + qstr type = MP_QSTR_PUBLIC; + + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_static_obj)) { + type = MP_QSTR_RANDOM_STATIC; + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj)) { + type = MP_QSTR_RANDOM_PRIVATE_RESOLVABLE; + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj)) { + type = MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE; + } + + mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_AddressType, type); +} + +const mp_obj_type_t bleio_addresstype_type = { + { &mp_type_type }, + .name = MP_QSTR_AddressType, + .print = bleio_addresstype_print, + .locals_dict = (mp_obj_t)&bleio_addresstype_locals_dict, +}; diff --git a/shared-bindings/bleio/AddressType.h b/shared-bindings/bleio/AddressType.h new file mode 100644 index 000000000..e69caffab --- /dev/null +++ b/shared-bindings/bleio/AddressType.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_ADDRESSTYPE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H + +#include "py/obj.h" + +typedef enum { + ADDRESS_PUBLIC, + ADDRESS_RANDOM_STATIC, + ADDRESS_RANDOM_PRIVATE_RESOLVABLE, + ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE +} bleio_address_type_t; + +extern const mp_obj_type_t bleio_addresstype_type; + +typedef struct { + mp_obj_base_t base; +} bleio_addresstype_obj_t; + +extern const bleio_addresstype_obj_t bleio_addresstype_public_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_static_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H diff --git a/shared-bindings/bleio/AdvertisementData.c b/shared-bindings/bleio/AdvertisementData.c new file mode 100644 index 000000000..9cfdd74e9 --- /dev/null +++ b/shared-bindings/bleio/AdvertisementData.c @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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/obj.h" +#include "shared-module/bleio/AdvertisementData.h" + +//| .. currentmodule:: bleio +//| +//| :class:`AdvertisementData` -- data used during BLE advertising +//| ============================================================== +//| +//| Represents the data to be broadcast during BLE advertising. +//| + +STATIC const mp_rom_map_elem_t bleio_advertisementdata_locals_dict_table[] = { + // Static variables + { MP_ROM_QSTR(MP_QSTR_FLAGS), MP_ROM_INT(AdFlags) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf16BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf16BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf32BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf32BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf128BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf128BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SHORTENED_LOCAL_NAME), MP_ROM_INT(AdShortenedLocalName) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LOCAL_NAME), MP_ROM_INT(AdCompleteLocalName) }, + { MP_ROM_QSTR(MP_QSTR_TX_POWER_LEVEL), MP_ROM_INT(AdTxPowerLevel) }, + { MP_ROM_QSTR(MP_QSTR_CLASS_OF_DEVICE), MP_ROM_INT(AdClassOfDevice) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C), MP_ROM_INT(AdSimplePairingHashC) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R), MP_ROM_INT(AdSimplePairingRandomizerR) }, + { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_TK_VALUE), MP_ROM_INT(AdSecurityManagerTKValue) }, + { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_OOB_FLAGS), MP_ROM_INT(AdSecurityManagerOOBFlags) }, + { MP_ROM_QSTR(MP_QSTR_SLAVE_CONNECTION_INTERVAL_RANGE), MP_ROM_INT(AdSlaveConnectionIntervalRange) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_16BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf16BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_128BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf128BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA), MP_ROM_INT(AdServiceData) }, + { MP_ROM_QSTR(MP_QSTR_PUBLIC_TARGET_ADDRESS), MP_ROM_INT(AdPublicTargetAddress) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_TARGET_ADDRESS), MP_ROM_INT(AdRandomTargetAddress) }, + { MP_ROM_QSTR(MP_QSTR_APPEARANCE), MP_ROM_INT(AdAppearance) }, + { MP_ROM_QSTR(MP_QSTR_ADVERTISING_INTERNAL), MP_ROM_INT(AdAdvertisingInterval) }, + { MP_ROM_QSTR(MP_QSTR_LE_BLUETOOTH_DEVICE_ADDRESS), MP_ROM_INT(AdLEBluetoothDeviceAddress) }, + { MP_ROM_QSTR(MP_QSTR_LE_ROLE), MP_ROM_INT(AdLERole) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C256), MP_ROM_INT(AdSimplePairingHashC256) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R256), MP_ROM_INT(AdSimplePairingRandomizerR256) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_32BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf32BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_32BIT_UUID), MP_ROM_INT(AdServiceData32BitUUID) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_128BIT_UUID), MP_ROM_INT(AdServiceData128BitUUID) }, + { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE), MP_ROM_INT(AdLESecureConnectionsConfirmationValue) }, + { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_RANDOM_VALUE), MP_ROM_INT(AdLESecureConnectionsRandomValue) }, + { MP_ROM_QSTR(MP_QSTR_URI), MP_ROM_INT(AdURI) }, + { MP_ROM_QSTR(MP_QSTR_INDOOR_POSITIONING), MP_ROM_INT(AdIndoorPositioning) }, + { MP_ROM_QSTR(MP_QSTR_TRANSPORT_DISCOVERY_DATA), MP_ROM_INT(AdTransportDiscoveryData) }, + { MP_ROM_QSTR(MP_QSTR_LE_SUPPORTED_FEATURES), MP_ROM_INT(AdLESupportedFeatures) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_MAP_UPDATE_INDICATION), MP_ROM_INT(AdChannelMapUpdateIndication) }, + { MP_ROM_QSTR(MP_QSTR_PB_ADV), MP_ROM_INT(AdPBADV) }, + { MP_ROM_QSTR(MP_QSTR_MESH_MESSAGE), MP_ROM_INT(AdMeshMessage) }, + { MP_ROM_QSTR(MP_QSTR_MESH_BEACON), MP_ROM_INT(AdMeshBeacon) }, + { MP_ROM_QSTR(MP_QSTR_3D_INFORMATION_DATA), MP_ROM_INT(Ad3DInformationData) }, + { MP_ROM_QSTR(MP_QSTR_MANUFACTURER_SPECIFIC_DATA), MP_ROM_INT(AdManufacturerSpecificData) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_advertisementdata_locals_dict, bleio_advertisementdata_locals_dict_table); + +const mp_obj_type_t bleio_advertisementdata_type = { + { &mp_type_type }, + .name = MP_QSTR_AdvertisementData, + .locals_dict = (mp_obj_dict_t*)&bleio_advertisementdata_locals_dict +}; diff --git a/shared-bindings/bleio/AdvertisementData.h b/shared-bindings/bleio/AdvertisementData.h new file mode 100644 index 000000000..05b5a2c8d --- /dev/null +++ b/shared-bindings/bleio/AdvertisementData.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_ADVERTISEMENTDATA_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H + +#include "py/obj.h" + +extern const mp_obj_type_t bleio_advertisementdata_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c new file mode 100644 index 000000000..369f3f991 --- /dev/null +++ b/shared-bindings/bleio/Characteristic.c @@ -0,0 +1,332 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * 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/Characteristic.h" +#include "shared-bindings/bleio/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Characteristic` -- BLE service characteristic +//| ========================================================= +//| +//| Stores information about a BLE service characteristic and allows to read +//| and write the characteristic's value. +//| + +//| .. class:: Characteristic(uuid) +//| +//| Create a new Characteristic object identified by the specified UUID. +//| +//| :param bleio.UUID uuid: The uuid of the characteristic +//| + +//| .. attribute:: broadcast +//| +//| A `bool` specifying if the characteristic allows broadcasting its value. +//| + +//| .. attribute:: indicate +//| +//| A `bool` specifying if the characteristic allows indicating its value. +//| + +//| .. attribute:: notify +//| +//| A `bool` specifying if the characteristic allows notifying its value. +//| + +//| .. attribute:: read +//| +//| A `bool` specifying if the characteristic allows reading its value. +//| + +//| .. attribute:: uuid +//| +//| The UUID of this characteristic. (read-only) +//| + +//| .. attribute:: value +//| +//| The value of this characteristic. The value can be written to if the `write` property allows it. +//| If the `read` property allows it, the value can be read. If the `notify` property is set, writting +//| to the value will generate a BLE notification. +//| + +//| .. attribute:: write +//| +//| A `bool` specifying if the characteristic allows writting to its value. +//| + +//| .. attribute:: write_no_resp +//| +//| A `bool` specifying if the characteristic allows writting to its value without response. +//| +STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Characteristic(uuid: 0x"HEX2_FMT""HEX2_FMT" handle: 0x" HEX2_FMT ")", + self->uuid->value[1], self->uuid->value[0], self->handle); +} + +STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); + self->base.type = &bleio_characteristic_type; + self->service = NULL; + self->value_data = NULL; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_uuid, MP_ARG_REQUIRED| 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); + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + if (uuid == mp_const_none) { + return MP_OBJ_FROM_PTR(self); + } + + if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + self->uuid = MP_OBJ_TO_PTR(uuid); + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID parameter"))); + } + + common_hal_bleio_characteristic_construct(self); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.broadcast); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); + +STATIC mp_obj_t bleio_characteristic_set_broadcast(mp_obj_t self_in, mp_obj_t broadcast_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.broadcast = mp_obj_is_true(broadcast_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_broadcast_obj, bleio_characteristic_set_broadcast); + +const mp_obj_property_t bleio_characteristic_broadcast_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj, + (mp_obj_t)&bleio_characteristic_set_broadcast_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.indicate); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate); + +STATIC mp_obj_t bleio_characteristic_set_indicate(mp_obj_t self_in, mp_obj_t indicate_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.indicate = mp_obj_is_true(indicate_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_indicate_obj, bleio_characteristic_set_indicate); + +const mp_obj_property_t bleio_characteristic_indicate_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj, + (mp_obj_t)&bleio_characteristic_set_indicate_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.notify); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify); + +STATIC mp_obj_t bleio_characteristic_set_notify(mp_obj_t self_in, mp_obj_t notify_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.notify = mp_obj_is_true(notify_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_notify_obj, bleio_characteristic_set_notify); + +const mp_obj_property_t bleio_characteristic_notify_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj, + (mp_obj_t)&bleio_characteristic_set_notify_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.read); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read); + +STATIC mp_obj_t bleio_characteristic_set_read(mp_obj_t self_in, mp_obj_t read_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.read = mp_obj_is_true(read_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_read_obj, bleio_characteristic_set_read); + +const mp_obj_property_t bleio_characteristic_read_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj, + (mp_obj_t)&bleio_characteristic_set_read_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.write); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write); + +STATIC mp_obj_t bleio_characteristic_set_write(mp_obj_t self_in, mp_obj_t write_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.write = mp_obj_is_true(write_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_obj, bleio_characteristic_set_write); + +const mp_obj_property_t bleio_characteristic_write_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj, + (mp_obj_t)&bleio_characteristic_set_write_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_write_wo_resp(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.write_wo_resp); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_wo_resp_obj, bleio_characteristic_get_write_wo_resp); + +STATIC mp_obj_t bleio_characteristic_set_write_wo_resp(mp_obj_t self_in, mp_obj_t write_wo_resp_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.write_wo_resp = mp_obj_is_true(write_wo_resp_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_wo_resp_obj, bleio_characteristic_set_write_wo_resp); + +const mp_obj_property_t bleio_characteristic_write_wo_resp_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_wo_resp_obj, + (mp_obj_t)&bleio_characteristic_set_write_wo_resp_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_FROM_PTR(self->uuid); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid); + +const mp_obj_property_t bleio_characteristic_uuid_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_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); + + common_hal_bleio_characteristic_read_value(self); + + return self->value_data; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value); + +STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ); + + common_hal_bleio_characteristic_write_value(self, &bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_value_obj, bleio_characteristic_set_value); + +const mp_obj_property_t bleio_characteristic_value_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_value_obj, + (mp_obj_t)&bleio_characteristic_set_value_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) }, + { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) }, + { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_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_write), MP_ROM_PTR(&bleio_characteristic_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_wo_resp), MP_ROM_PTR(&bleio_characteristic_write_wo_resp_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table); + +const mp_obj_type_t bleio_characteristic_type = { + { &mp_type_type }, + .name = MP_QSTR_Characteristic, + .print = bleio_characteristic_print, + .make_new = bleio_characteristic_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict +}; diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h new file mode 100644 index 000000000..0e99e97cc --- /dev/null +++ b/shared-bindings/bleio/Characteristic.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_CHARACTERISTIC_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H + +#include "shared-module/bleio/Characteristic.h" + +extern const mp_obj_type_t bleio_characteristic_type; + +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c new file mode 100644 index 000000000..df32a00e7 --- /dev/null +++ b/shared-bindings/bleio/Descriptor.c @@ -0,0 +1,171 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * 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/Descriptor.h" +#include "shared-bindings/bleio/UUID.h" + +enum { + DescriptorUuidCharacteristicExtendedProperties = 0x2900, + DescriptorUuidCharacteristicUserDescription = 0x2901, + DescriptorUuidClientCharacteristicConfiguration = 0x2902, + DescriptorUuidServerCharacteristicConfiguration = 0x2903, + DescriptorUuidCharacteristicPresentationFormat = 0x2904, + DescriptorUuidCharacteristicAggregateFormat = 0x2905, + DescriptorUuidValidRange = 0x2906, + DescriptorUuidExternalReportReference = 0x2907, + DescriptorUuidReportReference = 0x2908, + DescriptorUuidNumberOfDigitals = 0x2909, + DescriptorUuidValueTriggerSetting = 0x290A, + DescriptorUuidEnvironmentalSensingConfiguration = 0x290B, + DescriptorUuidEnvironmentalSensingMeasurement = 0x290C, + DescriptorUuidEnvironmentalSensingTriggerSetting = 0x290D, + DescriptorUuidTimeTriggerSetting = 0x290E, +}; + +//| .. currentmodule:: bleio +//| +//| :class:`Descriptor` -- BLE descriptor +//| ========================================================= +//| +//| Stores information about a BLE descriptor. +//| Descriptors are encapsulated by BLE characteristics and provide contextual +//| information about the characteristic. +//| + +//| .. class:: Descriptor(uuid) +//| +//| Create a new descriptor object with the UUID uuid. +//| The value can be either of type `bleio.UUID` or any value allowed by the `bleio.UUID` constructor. + +//| .. attribute:: handle +//| +//| The descriptor handle. (read-only) +//| + +//| .. attribute:: uuid +//| +//| The descriptor uuid. (read-only) +//| +STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t); + self->base.type = type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t uuid_arg = args[ARG_uuid].u_obj; + + bleio_uuid_obj_t *uuid; + if (MP_OBJ_IS_TYPE(uuid_arg, &bleio_uuid_type)) { + uuid = MP_OBJ_TO_PTR(uuid_arg); + } else { + uuid = MP_OBJ_TO_PTR(bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_arg)); + } + + common_hal_bleio_descriptor_construct(self, uuid); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_descriptor_print(self, print); +} + +STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle); + +const mp_obj_property_t bleio_descriptor_handle_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + const mp_obj_t uuid = mp_obj_new_int(common_hal_bleio_descriptor_get_uuid(self)); + + return bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid); + +const mp_obj_property_t bleio_descriptor_uuid_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_descriptor_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { + // Properties + { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) }, + + // Static variables + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES), MP_ROM_INT(DescriptorUuidCharacteristicExtendedProperties) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION), MP_ROM_INT(DescriptorUuidCharacteristicUserDescription) }, + { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidClientCharacteristicConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidServerCharacteristicConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicPresentationFormat) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicAggregateFormat) }, + { MP_ROM_QSTR(MP_QSTR_VALID_RANGE), MP_ROM_INT(DescriptorUuidValidRange) }, + { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidExternalReportReference) }, + { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidReportReference) }, + { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS), MP_ROM_INT(DescriptorUuidNumberOfDigitals) }, + { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidValueTriggerSetting) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION), MP_ROM_INT(DescriptorUuidEnvironmentalSensingConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ), MP_ROM_INT(DescriptorUuidEnvironmentalSensingMeasurement) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidEnvironmentalSensingTriggerSetting) }, + { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidTimeTriggerSetting) } +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table); + +const mp_obj_type_t bleio_descriptor_type = { + { &mp_type_type }, + .name = MP_QSTR_Descriptor, + .print = bleio_descriptor_print, + .make_new = bleio_descriptor_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict +}; diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h new file mode 100644 index 000000000..85310d304 --- /dev/null +++ b/shared-bindings/bleio/Descriptor.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_DESCRIPTOR_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H + +#include "common-hal/bleio/Descriptor.h" +#include "common-hal/bleio/UUID.h" + +extern const mp_obj_type_t bleio_descriptor_type; + +extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid); +extern void common_hal_bleio_descriptor_print(bleio_descriptor_obj_t *self, const mp_print_t *print); +extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self); +extern mp_int_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/bleio/Device.c b/shared-bindings/bleio/Device.c new file mode 100644 index 000000000..94834ef7c --- /dev/null +++ b/shared-bindings/bleio/Device.c @@ -0,0 +1,357 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * 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 <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/AddressType.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" +#include "shared-module/bleio/ScanEntry.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Device` -- BLE device +//| ========================================================= +//| +//| Provides access a to BLE device, either in a Peripheral or Central role. +//| When a device is created without any parameter passed to the constructor, +//| it will be set to the Peripheral role. If a address is passed, the device +//| will be a Central. For a Peripheral you can set the `name`, add services +//| via `add_service` and then start and stop advertising via `start_advertising` +//| and `stop_advertising`. For the Central, you can `bleio.Device.connect` and `bleio.Device.disconnect` +//| to the device, once a connection is established, the device's services can +//| be accessed using `services`. +//| +//| Usage:: +//| +//| import bleio +//| +//| # Peripheral +//| periph = bleio.Device() +//| +//| serv = bleio.Service(bleio.UUID(0x180f)) +//| p.add_service(serv) +//| +//| chara = bleio.Characteristic(bleio.UUID(0x2919)) +//| chara.read = True +//| chara.notify = True +//| serv.add_characteristic(chara) +//| +//| periph.start_advertising() +//| +//| # Central +//| scanner = bleio.Scanner() +//| entries = scanner.scan(2500) +//| +//| my_entry = None +//| for entry in entries: +//| if entry.name is not None and entry.name == 'MyDevice': +//| my_entry = entry +//| break +//| +//| central = bleio.Device(my_entry.address) +//| central.connect() +//| + +//| .. class:: Device(address=None, scan_entry=None) +//| +//| Create a new Device object. If the `address` or :py:data:`scan_entry` parameters are not `None`, +//| the role is set to Central, otherwise it's set to Peripheral. +//| +//| :param bleio.Address address: The address of the device to connect to +//| :param bleio.ScanEntry scan_entry: The scan entry returned from `bleio.Scanner` +//| + +//| .. attribute:: name +//| +//| For the Peripheral role, this property can be used to read and write the device's name. +//| For the Central role, this property will equal the name of the remote device, if one was +//| advertised by the device. In the Central role this property is read-only. +//| + +//| .. attribute:: services +//| +//| A `list` of `bleio.Service` that are offered by this device. (read-only) +//| For a Peripheral device, this list will contain services added using `add_service`, +//| for a Central, this list will be empty until a connection is established, at which point +//| it will be filled with the remote device's services. +//| + +//| .. method:: add_service(service) +//| +//| Appends the :py:data:`service` to the list of this devices's services. +//| This method can only be called for Peripheral devices. +//| +//| :param bleio.Service service: the service to append +//| + +//| .. method:: connect() +//| +//| Attempts a connection to the remote device. If the connection is successful, +//| the device's services are available via `services`. +//| This method can only be called for Central devices. +//| + +//| .. method:: disconnect() +//| +//| Disconnects from the remote device. +//| This method can only be called for Central devices. +//| + +//| .. method:: start_advertising(connectable=True) +//| +//| Starts advertising the device. The device's name and +//| services are put into the advertisement packets. +//| If :py:data:`connectable` is `True` then other devices are allowed to conncet to this device. +//| This method can only be called for Peripheral devices. +//| + +//| .. method:: stop_advertising() +//| +//| Disconnects from the remote device. +//| This method can only be called for Peripheral devices. +//| + +// TODO: Add unique MAC address part to name +static const char default_name[] = "CIRCUITPY"; + +STATIC void bleio_device_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Device(role: %s)", self->is_peripheral ? "Peripheral" : "Central"); +} + +STATIC mp_obj_t bleio_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + bleio_device_obj_t *self = m_new_obj(bleio_device_obj_t); + self->base.type = &bleio_device_type; + self->service_list = mp_obj_new_list(0, NULL); + self->notif_handler = mp_const_none; + self->conn_handler = mp_const_none; + self->conn_handle = 0xFFFF; + self->is_peripheral = true; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_address, ARG_scan_entry }; + static const mp_arg_t allowed_args[] = { + { ARG_address, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_scan_entry, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.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); + + const mp_obj_t address_obj = args[ARG_address].u_obj; + const mp_obj_t scan_entry_obj = args[ARG_scan_entry].u_obj; + + if (address_obj != mp_const_none) { + bleio_address_obj_t *address = MP_OBJ_TO_PTR(address_obj); + + self->is_peripheral = false; + self->address.type = address->type; + memcpy(self->address.value, address->value, BLEIO_ADDRESS_BYTES); + } else if (scan_entry_obj != mp_const_none) { + bleio_scanentry_obj_t *scan_entry = MP_OBJ_TO_PTR(scan_entry_obj); + + self->is_peripheral = false; + self->address.type = scan_entry->address.type; + memcpy(self->address.value, scan_entry->address.value, BLEIO_ADDRESS_BYTES); + } else { + self->name = mp_obj_new_str(default_name, strlen(default_name)); + common_hal_bleio_adapter_get_address(&self->address); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_device_add_service(mp_obj_t self_in, mp_obj_t service_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't add services in Central mode"))); + } + + service->device = self; + + mp_obj_list_append(self->service_list, service); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_add_service_obj, bleio_device_add_service); + +STATIC mp_obj_t bleio_device_connect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't connect in Peripheral mode"))); + } + + common_hal_bleio_device_connect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_connect_obj, bleio_device_connect); + +STATIC mp_obj_t bleio_device_disconnect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_device_disconnect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_disconnect_obj, bleio_device_disconnect); + +STATIC mp_obj_t bleio_device_get_name(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->name; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_name_obj, bleio_device_get_name); + +static mp_obj_t bleio_device_set_name(mp_obj_t self_in, mp_obj_t value) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't change the name in Central mode"))); + } + + self->name = value; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_set_name_obj, bleio_device_set_name); + +const mp_obj_property_t bleio_device_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_name_obj, + (mp_obj_t)&bleio_device_set_name_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_device_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't advertise in Central mode"))); + } + + enum { ARG_connectable, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t bufinfo = { 0 }; + if (args[ARG_data].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); + } + + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); + for (size_t i = 0; i < service_list->len; ++i) { + bleio_service_obj_t *service = service_list->items[i]; + if (service->handle == 0xFFFF) { + common_hal_bleio_device_add_service(self, service); + } + } + + common_hal_bleio_device_start_advertising(self, args[ARG_connectable].u_bool, &bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_device_start_advertising_obj, 0, bleio_device_start_advertising); + +STATIC mp_obj_t bleio_device_stop_advertising(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't advertise in Central mode"))); + } + + common_hal_bleio_device_stop_advertising(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_stop_advertising_obj, bleio_device_stop_advertising); + +STATIC mp_obj_t bleio_device_get_services(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->service_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_services_obj, bleio_device_get_services); + +const mp_obj_property_t bleio_device_services_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_services_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_device_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_add_service), MP_ROM_PTR(&bleio_device_add_service_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_device_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_device_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_device_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_device_stop_advertising_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_device_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_device_services_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_device_locals_dict, bleio_device_locals_dict_table); + +const mp_obj_type_t bleio_device_type = { + { &mp_type_type }, + .name = MP_QSTR_Device, + .print = bleio_device_print, + .make_new = bleio_device_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_device_locals_dict +}; diff --git a/shared-bindings/bleio/Device.h b/shared-bindings/bleio/Device.h new file mode 100644 index 000000000..aebf1d639 --- /dev/null +++ b/shared-bindings/bleio/Device.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_DEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H + +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" +#include "shared-module/bleio/Service.h" + +extern const mp_obj_type_t bleio_device_type; + +extern void common_hal_bleio_device_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service); +extern void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data); +extern void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device); +extern void common_hal_bleio_device_connect(bleio_device_obj_t *device); +extern void common_hal_bleio_device_disconnect(bleio_device_obj_t *device); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/bleio/ScanEntry.c new file mode 100644 index 000000000..e452c7267 --- /dev/null +++ b/shared-bindings/bleio/ScanEntry.c @@ -0,0 +1,308 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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/objarray.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/objtuple.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/ScanEntry.h" + +//| .. currentmodule:: bleio +//| +//| :class:`ScanEntry` -- BLE scan response entry +//| ========================================================= +//| +//| Encapsulates information about a device that was received as a +//| response to a BLE scan request. +//| + +//| .. attribute:: address +//| +//| The address of the device. (read-only) +//| This attribute is of type `bleio.Address`. +//| + +//| .. attribute:: manufacturer_specific_data +//| +//| The manufacturer-specific data present in the advertisement packet. (read-only) +//| + +//| .. attribute:: name +//| +//| The name of the device. (read-only) +//| This attribute might be `None` if the data was missing from the advertisement packet. +//| + +//| .. attribute:: raw_data +//| +//| All the advertisement data present in the packet. (read-only) +//| + +//| .. attribute:: rssi +//| +//| The signal strength of the device at the time of the scan. (read-only) +//| + +//| .. attribute:: service_uuids +//| +//| The address of the device. (read-only) +//| This attribute is a list of `bleio.UUID`. +//| This attribute might be empty or incomplete, depending on the advertisement packet. +//| Currently only 16-bit UUIDS are listed. +//| + +//| .. attribute:: tx_power_level +//| +//| The transmit power level of the device. (read-only) +//| This attribute might be `None` if the data was missing from the advertisement packet. +//| +static uint8_t find_data_item(mp_obj_array_t *data_in, uint8_t type, uint8_t **data_out) { + uint16_t i = 0; + while (i < data_in->len) { + const uint8_t item_len = ((uint8_t*)data_in->items)[i]; + const uint8_t item_type = ((uint8_t*)data_in->items)[i + 1]; + if (item_type != type) { + i += (item_len + 1); + continue; + } + + *data_out = &((uint8_t*)data_in->items)[i + 2]; + + return item_len; + } + + return 0; +} + +STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in); + +STATIC void bleio_scanentry_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_scanentry_obj_t *self = (bleio_scanentry_obj_t *)self_in; + mp_printf(print, "ScanEntry(address: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", + self->address.value[5], self->address.value[4], self->address.value[3], + self->address.value[1], self->address.value[1], self->address.value[0]); + + const mp_obj_t name_obj = scanentry_get_name(self_in); + if (name_obj != mp_const_none) { + mp_obj_str_t *str = MP_OBJ_TO_PTR(name_obj); + mp_printf(print, " name: %s", str->data); + } + + mp_print_str(print, ")"); +} + +STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, (mp_obj_t)&mp_const_none_obj); + bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj); + + address->type = self->address.type; + memcpy(address->value, self->address.value, BLEIO_ADDRESS_BYTES); + + return obj; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_address_obj, bleio_scanentry_get_address); + +const mp_obj_property_t bleio_scanentry_address_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_address_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_manufacturer_specific_data(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *manuf_data; + + const uint8_t manuf_data_len = find_data_item(data, AdManufacturerSpecificData, &manuf_data); + if (manuf_data_len == 0) { + return mp_const_none; + } + + return mp_obj_new_bytearray_by_ref(manuf_data_len, manuf_data); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_manufacturer_specific_data_obj, scanentry_get_manufacturer_specific_data); + +const mp_obj_property_t bleio_scanentry_manufacturer_specific_data_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_manufacturer_specific_data_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *name; + + // Try for Complete but settle for Shortened + uint8_t name_len = find_data_item(data, AdCompleteLocalName, &name); + if (name_len == 0) { + name_len = find_data_item(data, AdShortenedLocalName, &name); + } + + if (name_len == 0) { + return mp_const_none; + } + + return mp_obj_new_str((const char*)name, name_len - 1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_name_obj, scanentry_get_name); + +const mp_obj_property_t bleio_scanentry_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_name_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_raw_data(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t entries = mp_obj_new_list(0, NULL); + + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + + uint16_t i = 0; + while (i < data->len) { + mp_obj_tuple_t *entry = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + + const uint8_t item_len = ((uint8_t*)data->items)[i]; + const uint8_t item_type = ((uint8_t*)data->items)[i + 1]; + + entry->items[0] = MP_OBJ_NEW_SMALL_INT(item_type); + entry->items[1] = mp_obj_new_bytearray(item_len - 1, &((uint8_t*)data->items)[i + 2]); + mp_obj_list_append(entries, MP_OBJ_FROM_PTR(entry)); + + i += (item_len + 1); + } + + return entries; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_raw_data_obj, scanentry_get_raw_data); + +const mp_obj_property_t bleio_scanentry_raw_data_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_raw_data_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_rssi(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->rssi); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_rssi_obj, scanentry_get_rssi); + +const mp_obj_property_t bleio_scanentry_rssi_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_rssi_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_service_uuids(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *uuids; + + // Try for Complete but settle for Incomplete + uint8_t uuids_len = find_data_item(data, AdCompleteListOf16BitServiceClassUUIDs, &uuids); + if (uuids_len == 0) { + uuids_len = find_data_item(data, AdIncompleteListOf16BitServiceClassUUIDs, &uuids); + } + + mp_obj_t entries = mp_obj_new_list(0, NULL); + for (size_t i = 0; i < uuids_len / sizeof(uint16_t); ++i) { + const mp_obj_t uuid_int = mp_obj_new_int(uuids[sizeof(uint16_t) * i] | (uuids[sizeof(uint16_t) * i + 1] << 8)); + const mp_obj_t uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_int); + + mp_obj_list_append(entries, uuid_obj); + } + + // TODO: 32-bit UUIDs + // TODO: 128-bit UUIDs + + return entries; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_service_uuids_obj, scanentry_get_service_uuids); + +const mp_obj_property_t bleio_scanentry_service_uuids_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_service_uuids_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_tx_power_level(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *tx_power; + + const uint8_t tx_power_len = find_data_item(data, AdTxPowerLevel, &tx_power); + if (tx_power_len == 0) { + return mp_const_none; + } + + return mp_obj_new_int((int8_t)(*tx_power)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_tx_power_level_obj, scanentry_get_tx_power_level); + +const mp_obj_property_t bleio_scanentry_tx_power_level_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_tx_power_level_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_manufacturer_specific_data), MP_ROM_PTR(&bleio_scanentry_manufacturer_specific_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_scanentry_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_raw_data), MP_ROM_PTR(&bleio_scanentry_raw_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) }, + { MP_ROM_QSTR(MP_QSTR_service_uuids), MP_ROM_PTR(&bleio_scanentry_service_uuids_obj) }, + { MP_ROM_QSTR(MP_QSTR_tx_power_level), MP_ROM_PTR(&bleio_scanentry_tx_power_level_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table); + +const mp_obj_type_t bleio_scanentry_type = { + { &mp_type_type }, + .name = MP_QSTR_ScanEntry, + .print = bleio_scanentry_print, + .locals_dict = (mp_obj_dict_t*)&bleio_scanentry_locals_dict +}; diff --git a/shared-bindings/bleio/ScanEntry.h b/shared-bindings/bleio/ScanEntry.h new file mode 100644 index 000000000..2b44ba3f4 --- /dev/null +++ b/shared-bindings/bleio/ScanEntry.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H + +#include "py/obj.h" + +extern const mp_obj_type_t bleio_scanentry_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H diff --git a/shared-bindings/bleio/Scanner.c b/shared-bindings/bleio/Scanner.c new file mode 100644 index 000000000..5d19778f6 --- /dev/null +++ b/shared-bindings/bleio/Scanner.c @@ -0,0 +1,162 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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 "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/Scanner.h" + +#define DEFAULT_INTERVAL 100 +#define DEFAULT_WINDOW 100 + +//| .. currentmodule:: bleio +//| +//| :class:`Scanner` -- scan for nearby BLE devices +//| ========================================================= +//| +//| Allows scanning for nearby BLE devices. +//| +//| Usage:: +//| +//| import bleio +//| scanner = bleio.Scanner() +//| entries = scanner.scan(2500) +//| print(entries) +//| + +//| .. class:: Scanner() +//| +//| Create a new Scanner object. +//| + +//| .. attribute:: interval +//| +//| The interval (in ms) between the start of two consecutive scan windows. +//| Allowed values are between 10ms and 10.24 sec. +//| + +//| .. attribute:: window +//| +//| The duration (in ms) in which a single BLE channel is scanned. +//| Allowed values are between 10ms and 10.24 sec. +//| + +//| .. method:: scan(timeout) +//| +//| Performs a BLE scan. +//| +//| :param int timeout: the scan timeout in ms +//| :returns: advertising packets found +//| :rtype: list of :py:class:`bleio.ScanEntry` +//| +STATIC void bleio_scanner_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Scanner(interval: %d window: %d)", self->interval, self->window); +} + +STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t); + self->base.type = type; + + self->interval = DEFAULT_INTERVAL; + self->window = DEFAULT_WINDOW; + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_scanner_get_interval(mp_obj_t self_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->interval); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_interval_obj, bleio_scanner_get_interval); + +static mp_obj_t bleio_scanner_set_interval(mp_obj_t self_in, mp_obj_t value) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->interval = mp_obj_get_int(value); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_interval_obj, bleio_scanner_set_interval); + +const mp_obj_property_t bleio_scanner_interval_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanner_get_interval_obj, + (mp_obj_t)&bleio_scanner_set_interval_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + const mp_int_t timeout = mp_obj_get_int(timeout_in); + + self->adv_reports = mp_obj_new_list(0, NULL); + + common_hal_bleio_scanner_scan(self, timeout); + + return self->adv_reports; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_scan_obj, scanner_scan); + +STATIC mp_obj_t bleio_scanner_get_window(mp_obj_t self_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->window); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_window_obj, bleio_scanner_get_window); + +static mp_obj_t bleio_scanner_set_window(mp_obj_t self_in, mp_obj_t value) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->window = mp_obj_get_int(value); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_window_obj, bleio_scanner_set_window); + +const mp_obj_property_t bleio_scanner_window_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanner_get_window_obj, + (mp_obj_t)&bleio_scanner_set_window_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_interval), MP_ROM_PTR(&bleio_scanner_interval_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_window), MP_ROM_PTR(&bleio_scanner_window_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, + .print = bleio_scanner_print, + .make_new = bleio_scanner_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict +}; diff --git a/shared-bindings/bleio/Scanner.h b/shared-bindings/bleio/Scanner.h new file mode 100644 index 000000000..9bd071747 --- /dev/null +++ b/shared-bindings/bleio/Scanner.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * 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_SCANNER_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H + +#include "py/objtype.h" +#include "shared-module/bleio/Scanner.h" + +extern const mp_obj_type_t bleio_scanner_type; + +extern void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout); +extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c new file mode 100644 index 000000000..2d09cbc3c --- /dev/null +++ b/shared-bindings/bleio/Service.c @@ -0,0 +1,170 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * 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/Service.h" +#include "shared-bindings/bleio/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Service` -- BLE service +//| ========================================================= +//| +//| Stores information about a BLE service and its characteristics. +//| + +//| .. class:: Service(uuid, secondary=False) +//| +//| Create a new Service object identified by the specified UUID. +//| To mark the service as secondary, pass `True` as :py:data:`secondary`. +//| +//| :param bleio.UUID uuid: The uuid of the service +//| :param bool secondary: If the service is a secondary one +//| + +//| .. method:: add_characteristic(characteristic) +//| +//| Appends the :py:data:`characteristic` to the list of this service's characteristics. +//| +//| :param bleio.Characteristic characteristic: the characteristic to append +//| + +//| .. attribute:: characteristics +//| +//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) +//| + +//| .. attribute:: uuid +//| +//| The UUID of this service. (read-only) +//| +STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Service(uuid: 0x"HEX2_FMT""HEX2_FMT")", + self->uuid->value[1], self->uuid->value[0]); +} + +STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t); + self->base.type = &bleio_service_type; + self->device = NULL; + self->char_list = mp_obj_new_list(0, NULL); + self->handle = 0xFFFF; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid, ARG_secondary }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->is_secondary = args[ARG_secondary].u_bool; + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + if (uuid == mp_const_none) { + return MP_OBJ_FROM_PTR(self); + } + + if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + self->uuid = MP_OBJ_TO_PTR(uuid); + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID parameter"))); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_in); + + if (self->uuid->type == UUID_TYPE_128BIT) { + characteristic->uuid->type = UUID_TYPE_128BIT; + characteristic->uuid->uuid_vs_idx = self->uuid->uuid_vs_idx; + } + + characteristic->service = self; + + mp_obj_list_append(self->char_list, characteristic); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_service_add_characteristic_obj, bleio_service_add_characteristic); + +STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->char_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics); + +const mp_obj_property_t bleio_service_characteristics_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_service_get_characteristics_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_FROM_PTR(self->uuid); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_uuid_obj, bleio_service_get_uuid); + +const mp_obj_property_t bleio_service_uuid_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_service_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_obj) }, + { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); + +const mp_obj_type_t bleio_service_type = { + { &mp_type_type }, + .name = MP_QSTR_Service, + .print = bleio_service_print, + .make_new = bleio_service_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict +}; diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h new file mode 100644 index 000000000..77c751829 --- /dev/null +++ b/shared-bindings/bleio/Service.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_SERVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H + +#include "shared-module/bleio/Characteristic.h" +#include "shared-module/bleio/Service.h" + +const mp_obj_type_t bleio_service_type; + +extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/bleio/UUID.c new file mode 100644 index 000000000..7cef9a26f --- /dev/null +++ b/shared-bindings/bleio/UUID.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * 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/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`UUID` -- BLE UUID +//| ========================================================= +//| +//| Encapsulates both 16-bit and 128-bit UUIDs. Can be used for services, +//| characteristics, descriptors and more. +//| + +//| .. class:: UUID(uuid) +//| +//| Create a new UUID object encapsulating the uuid value. +//| The value itself can be one of: +//| +//| - a `int` value in range of 0 to 0xFFFF +//| - a `str` value in the format of '0xXXXX' for 16-bit or 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' for 128-bit +//| +//| :param int/str uuid: The uuid to encapsulate +//| + +//| .. method:: __len__() +//| +//| Returns the uuid length in bits +//| +//| This allows you to: +//| +//| uuid = bleio.UUID(0x1801) +//| print(len(uuid)) +//| + +//| .. attribute:: type +//| +//| The UUID type. One of: +//| +//| - `bleio.UUIDType.TYPE_16BIT` +//| - `bleio.UUIDType.TYPE_128BIT` +//| +STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_uuid_obj_t *self = m_new_obj(bleio_uuid_obj_t); + self->base.type = &bleio_uuid_type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + common_hal_bleio_uuid_construct(self, &uuid); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self); + const uint8_t len = (type == UUID_TYPE_16BIT) ? 16 : 128; + switch (op) { + case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0); + case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len); + default: return MP_OBJ_NULL; // op not supported + } +} + +STATIC void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_uuid_print(self, print); +} + +STATIC mp_obj_t bleio_uuid_get_type(mp_obj_t self_in) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self); + if (type == UUID_TYPE_16BIT) { + return (mp_obj_t)&bleio_uuidtype_16bit_obj; + } + + if (type == UUID_TYPE_128BIT) { + return (mp_obj_t)&bleio_uuidtype_128bit_obj; + } + + return (mp_obj_t)&mp_const_none_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_uuid_get_type_obj, bleio_uuid_get_type); + +const mp_obj_property_t bleio_uuid_type_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_uuid_get_type_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_uuid_type_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table); + +const mp_obj_type_t bleio_uuid_type = { + { &mp_type_type }, + .name = MP_QSTR_UUID, + .print = bleio_uuid_print, + .make_new = bleio_uuid_make_new, + .unary_op = bleio_uuid_unary_op, + .locals_dict = (mp_obj_dict_t*)&bleio_uuid_locals_dict +}; diff --git a/shared-bindings/bleio/UUID.h b/shared-bindings/bleio/UUID.h new file mode 100644 index 000000000..d6fcbac1b --- /dev/null +++ b/shared-bindings/bleio/UUID.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_UUID_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H + +#include "common-hal/bleio/UUID.h" +#include "shared-bindings/bleio/UUIDType.h" + +extern const mp_obj_type_t bleio_uuid_type; + +extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uuid); +extern void common_hal_bleio_uuid_print(bleio_uuid_obj_t *self, const mp_print_t *print); +extern bleio_uuid_type_t common_hal_bleio_uuid_get_type(bleio_uuid_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H diff --git a/shared-bindings/bleio/UUIDType.c b/shared-bindings/bleio/UUIDType.c new file mode 100644 index 000000000..e36d1f06d --- /dev/null +++ b/shared-bindings/bleio/UUIDType.c @@ -0,0 +1,75 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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 "shared-bindings/bleio/UUIDType.h" + +//| .. currentmodule:: bleio +//| +//| :class:`UUIDType` -- defines the type of a BLE UUID +//| ============================================================= +//| +//| .. class:: bleio.UUIDType +//| +//| Enum-like class to define the type of a BLE UUID. +//| +//| .. data:: TYPE_16BIT +//| +//| The UUID is 16-bit +//| +//| .. data:: TYPE_128BIT +//| +//| The UUID is 128-bit +//| +const mp_obj_type_t bleio_uuidtype_type; + +const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj = { + { &bleio_uuidtype_type }, +}; + +const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj = { + { &bleio_uuidtype_type }, +}; + +STATIC const mp_rom_map_elem_t bleio_uuidtype_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_TYPE_16BIT), MP_ROM_PTR(&bleio_uuidtype_16bit_obj) }, + { MP_ROM_QSTR(MP_QSTR_TYPE_128BIT), MP_ROM_PTR(&bleio_uuidtype_128bit_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bleio_uuidtype_locals_dict, bleio_uuidtype_locals_dict_table); + +STATIC void bleio_uuidtype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + qstr type = MP_QSTR_TYPE_128BIT; + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_uuidtype_16bit_obj)) { + type = MP_QSTR_TYPE_16BIT; + } + mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_UUIDType, type); +} + +const mp_obj_type_t bleio_uuidtype_type = { + { &mp_type_type }, + .name = MP_QSTR_UUIDType, + .print = bleio_uuidtype_print, + .locals_dict = (mp_obj_t)&bleio_uuidtype_locals_dict, +}; diff --git a/shared-bindings/bleio/UUIDType.h b/shared-bindings/bleio/UUIDType.h new file mode 100644 index 000000000..87bbf9b53 --- /dev/null +++ b/shared-bindings/bleio/UUIDType.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * 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_UUIDTYPE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H + +#include "py/obj.h" + +typedef enum { + UUID_TYPE_16BIT, + UUID_TYPE_128BIT +} bleio_uuid_type_t; + +extern const mp_obj_type_t bleio_uuidtype_type; + +typedef struct { + mp_obj_base_t base; +} bleio_uuidtype_obj_t; + +extern const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj; +extern const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 475fb395a..98099422c 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -25,8 +25,18 @@ * THE SOFTWARE. */ -#include "py/obj.h" #include "shared-bindings/bleio/__init__.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/AddressType.h" +#include "shared-bindings/bleio/AdvertisementData.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/Scanner.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-bindings/bleio/UUIDType.h" //| :mod:`bleio` --- Bluetooth Low Energy functionality //| ================================================================ @@ -42,7 +52,18 @@ //| .. toctree:: //| :maxdepth: 3 //| +//| Address +//| AddressType +//| AdvertisementData //| Adapter +//| Characteristic +//| Descriptor +//| Device +//| ScanEntry +//| Scanner +//| Service +//| UUID +//| UUIDType //| //| .. attribute:: adapter //| @@ -52,8 +73,23 @@ //| 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(&common_hal_bleio_adapter_obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, + { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, + { MP_ROM_QSTR(MP_QSTR_AdvertisementData), MP_ROM_PTR(&bleio_advertisementdata_type) }, + { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, + { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, + { MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&bleio_device_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_Service), MP_ROM_PTR(&bleio_service_type) }, + { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + + // Enum-like Classes. + { MP_ROM_QSTR(MP_QSTR_AddressType), MP_ROM_PTR(&bleio_addresstype_type) }, + { MP_ROM_QSTR(MP_QSTR_UUIDType), MP_ROM_PTR(&bleio_uuidtype_type) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); |
