From 5638512c8cfec03fdb7d20198a31fb9106f9e1c0 Mon Sep 17 00:00:00 2001 From: n1klasD <67094918+n1klasD@users.noreply.github.com> Date: Tue, 1 Mar 2022 11:27:53 +0100 Subject: [PATCH 01/22] added basic connection test --- .../ble_gatt_server/advertisement.py | 134 +++++++ Communication/ble_gatt_server/bletools.py | 59 +++ Communication/ble_gatt_server/service.py | 323 +++++++++++++++++ Communication/notes.txt | 0 Communication/testConnection.py | 341 ++++++++++++++++++ 5 files changed, 857 insertions(+) create mode 100644 Communication/ble_gatt_server/advertisement.py create mode 100644 Communication/ble_gatt_server/bletools.py create mode 100644 Communication/ble_gatt_server/service.py create mode 100644 Communication/notes.txt create mode 100644 Communication/testConnection.py diff --git a/Communication/ble_gatt_server/advertisement.py b/Communication/ble_gatt_server/advertisement.py new file mode 100644 index 0000000..86a31c5 --- /dev/null +++ b/Communication/ble_gatt_server/advertisement.py @@ -0,0 +1,134 @@ +"""Copyright (c) 2019, Douglas Otwell + +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. +""" + +import dbus +import dbus.service + +from bletools import BleTools + +BLUEZ_SERVICE_NAME = "org.bluez" +LE_ADVERTISING_MANAGER_IFACE = "org.bluez.LEAdvertisingManager1" +DBUS_OM_IFACE = "org.freedesktop.DBus.ObjectManager" +DBUS_PROP_IFACE = "org.freedesktop.DBus.Properties" +LE_ADVERTISEMENT_IFACE = "org.bluez.LEAdvertisement1" + + +class Advertisement(dbus.service.Object): + PATH_BASE = "/org/bluez/example/advertisement" + + def __init__(self, index, advertising_type): + self.path = self.PATH_BASE + str(index) + self.bus = BleTools.get_bus() + self.ad_type = advertising_type + self.local_name = None + self.service_uuids = None + self.solicit_uuids = None + self.manufacturer_data = None + self.service_data = None + self.include_tx_power = None + dbus.service.Object.__init__(self, self.bus, self.path) + + def get_properties(self): + properties = dict() + properties["Type"] = self.ad_type + + if self.local_name is not None: + properties["LocalName"] = dbus.String(self.local_name) + + if self.service_uuids is not None: + properties["ServiceUUIDs"] = dbus.Array(self.service_uuids, + signature='s') + if self.solicit_uuids is not None: + properties["SolicitUUIDs"] = dbus.Array(self.solicit_uuids, + signature='s') + if self.manufacturer_data is not None: + properties["ManufacturerData"] = dbus.Dictionary( + self.manufacturer_data, signature='qv') + + if self.service_data is not None: + properties["ServiceData"] = dbus.Dictionary(self.service_data, + signature='sv') + if self.include_tx_power is not None: + properties["IncludeTxPower"] = dbus.Boolean(self.include_tx_power) + + if self.local_name is not None: + properties["LocalName"] = dbus.String(self.local_name) + + return {LE_ADVERTISEMENT_IFACE: properties} + + def get_path(self): + return dbus.ObjectPath(self.path) + + def add_service_uuid(self, uuid): + if not self.service_uuids: + self.service_uuids = [] + self.service_uuids.append(uuid) + + def add_solicit_uuid(self, uuid): + if not self.solicit_uuids: + self.solicit_uuids = [] + self.solicit_uuids.append(uuid) + + def add_manufacturer_data(self, manuf_code, data): + if not self.manufacturer_data: + self.manufacturer_data = dbus.Dictionary({}, signature="qv") + self.manufacturer_data[manuf_code] = dbus.Array(data, signature="y") + + def add_service_data(self, uuid, data): + if not self.service_data: + self.service_data = dbus.Dictionary({}, signature="sv") + self.service_data[uuid] = dbus.Array(data, signature="y") + + def add_local_name(self, name): + if not self.local_name: + self.local_name = "" + self.local_name = dbus.String(name) + + @dbus.service.method(DBUS_PROP_IFACE, + in_signature="s", + out_signature="a{sv}") + def GetAll(self, interface): + if interface != LE_ADVERTISEMENT_IFACE: + raise InvalidArgsException() + + return self.get_properties()[LE_ADVERTISEMENT_IFACE] + + @dbus.service.method(LE_ADVERTISEMENT_IFACE, + in_signature='', + out_signature='') + def Release(self): + print ('%s: Released!' % self.path) + + def register_ad_callback(self): + print("GATT advertisement registered") + + def register_ad_error_callback(self): + print("Failed to register GATT advertisement") + + def register(self): + bus = BleTools.get_bus() + adapter = BleTools.find_adapter(bus) + + ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter), + LE_ADVERTISING_MANAGER_IFACE) + ad_manager.RegisterAdvertisement(self.get_path(), {}, + reply_handler=self.register_ad_callback, + error_handler=self.register_ad_error_callback) diff --git a/Communication/ble_gatt_server/bletools.py b/Communication/ble_gatt_server/bletools.py new file mode 100644 index 0000000..433e8b4 --- /dev/null +++ b/Communication/ble_gatt_server/bletools.py @@ -0,0 +1,59 @@ +"""Copyright (c) 2019, Douglas Otwell + +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. +""" + +import dbus + +try: + from gi.repository import GObject +except ImportError: + import gobject as GObject + +BLUEZ_SERVICE_NAME = "org.bluez" +LE_ADVERTISING_MANAGER_IFACE = "org.bluez.LEAdvertisingManager1" +DBUS_OM_IFACE = "org.freedesktop.DBus.ObjectManager" + + +class BleTools(object): + @classmethod + def get_bus(self): + bus = dbus.SystemBus() + + return bus + + @classmethod + def find_adapter(self, bus): + remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, "/"), + DBUS_OM_IFACE) + objects = remote_om.GetManagedObjects() + + for o, props in objects.items(): + if LE_ADVERTISING_MANAGER_IFACE in props: + return o + + return None + + @classmethod + def power_adapter(self): + adapter = self.get_adapter() + + adapter_props = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter), + "org.freedesktop.DBus.Properties"); + adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(1)) diff --git a/Communication/ble_gatt_server/service.py b/Communication/ble_gatt_server/service.py new file mode 100644 index 0000000..105d3b4 --- /dev/null +++ b/Communication/ble_gatt_server/service.py @@ -0,0 +1,323 @@ +"""Copyright (c) 2019, Douglas Otwell + +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. +""" + +import dbus +import dbus.mainloop.glib +import dbus.exceptions + +try: + from gi.repository import GObject +except ImportError: + import gobject as GObject +from bletools import BleTools + +BLUEZ_SERVICE_NAME = "org.bluez" +GATT_MANAGER_IFACE = "org.bluez.GattManager1" +DBUS_OM_IFACE = "org.freedesktop.DBus.ObjectManager" +DBUS_PROP_IFACE = "org.freedesktop.DBus.Properties" +GATT_SERVICE_IFACE = "org.bluez.GattService1" +GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1" +GATT_DESC_IFACE = "org.bluez.GattDescriptor1" + + +class InvalidArgsException(dbus.exceptions.DBusException): + _dbus_error_name = "org.freedesktop.DBus.Error.InvalidArgs" + + +class NotSupportedException(dbus.exceptions.DBusException): + _dbus_error_name = "org.bluez.Error.NotSupported" + + +class NotPermittedException(dbus.exceptions.DBusException): + _dbus_error_name = "org.bluez.Error.NotPermitted" + + +class Application(dbus.service.Object): + def __init__(self): + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + self.mainloop = GObject.MainLoop() + self.bus = BleTools.get_bus() + self.path = "/" + self.services = [] + self.next_index = 0 + dbus.service.Object.__init__(self, self.bus, self.path) + + def get_path(self): + return dbus.ObjectPath(self.path) + + def add_service(self, service): + self.services.append(service) + + @dbus.service.method(DBUS_OM_IFACE, out_signature="a{oa{sa{sv}}}") + def GetManagedObjects(self): + response = {} + + for service in self.services: + response[service.get_path()] = service.get_properties() + chrcs = service.get_characteristics() + for chrc in chrcs: + response[chrc.get_path()] = chrc.get_properties() + descs = chrc.get_descriptors() + for desc in descs: + response[desc.get_path()] = desc.get_properties() + + return response + + def register_app_callback(self): + print("GATT application registered") + + def register_app_error_callback(self, error): + print("Failed to register application: " + str(error)) + + def register(self): + adapter = BleTools.find_adapter(self.bus) + + service_manager = dbus.Interface( + self.bus.get_object(BLUEZ_SERVICE_NAME, adapter), + GATT_MANAGER_IFACE) + + service_manager.RegisterApplication(self.get_path(), {}, + reply_handler=self.register_app_callback, + error_handler=self.register_app_error_callback) + + def run(self): + self.mainloop.run() + + def quit(self): + print("\nGATT application terminated") + self.mainloop.quit() + + +class Service(dbus.service.Object): + PATH_BASE = "/org/bluez/example/service" + + def __init__(self, index, uuid, primary): + self.bus = BleTools.get_bus() + self.path = self.PATH_BASE + str(index) + self.uuid = uuid + self.primary = primary + self.characteristics = [] + self.next_index = 0 + dbus.service.Object.__init__(self, self.bus, self.path) + + def get_properties(self): + return { + GATT_SERVICE_IFACE: { + 'UUID': self.uuid, + 'Primary': self.primary, + 'Characteristics': dbus.Array( + self.get_characteristic_paths(), + signature='o') + } + } + + def get_path(self): + return dbus.ObjectPath(self.path) + + def add_characteristic(self, characteristic): + self.characteristics.append(characteristic) + + def get_characteristic_paths(self): + result = [] + for chrc in self.characteristics: + result.append(chrc.get_path()) + return result + + def get_characteristics(self): + return self.characteristics + + def get_bus(self): + return self.bus + + def get_next_index(self): + idx = self.next_index + self.next_index += 1 + + return idx + + @dbus.service.method(DBUS_PROP_IFACE, + in_signature='s', + out_signature='a{sv}') + def GetAll(self, interface): + if interface != GATT_SERVICE_IFACE: + raise InvalidArgsException() + + return self.get_properties()[GATT_SERVICE_IFACE] + + +class Characteristic(dbus.service.Object): + """ + org.bluez.GattCharacteristic1 interface implementation + """ + + def __init__(self, uuid, flags, service): + index = service.get_next_index() + self.path = service.path + '/char' + str(index) + self.bus = service.get_bus() + self.uuid = uuid + self.service = service + self.flags = flags + self.descriptors = [] + self.next_index = 0 + dbus.service.Object.__init__(self, self.bus, self.path) + + def get_properties(self): + return { + GATT_CHRC_IFACE: { + 'Service': self.service.get_path(), + 'UUID': self.uuid, + 'Flags': self.flags, + 'Descriptors': dbus.Array( + self.get_descriptor_paths(), + signature='o') + } + } + + def get_path(self): + return dbus.ObjectPath(self.path) + + def add_descriptor(self, descriptor): + self.descriptors.append(descriptor) + + def get_descriptor_paths(self): + result = [] + for desc in self.descriptors: + result.append(desc.get_path()) + return result + + def get_descriptors(self): + return self.descriptors + + @dbus.service.method(DBUS_PROP_IFACE, + in_signature='s', + out_signature='a{sv}') + def GetAll(self, interface): + if interface != GATT_CHRC_IFACE: + raise InvalidArgsException() + + return self.get_properties()[GATT_CHRC_IFACE] + + @dbus.service.method(GATT_CHRC_IFACE, + in_signature='a{sv}', + out_signature='ay') + def ReadValue(self, options): + print('Default ReadValue called, returning error') + raise NotSupportedException() + + @dbus.service.method(GATT_CHRC_IFACE, in_signature='aya{sv}') + def WriteValue(self, value, options): + print('Default WriteValue called, returning error') + raise NotSupportedException() + + @dbus.service.method(GATT_CHRC_IFACE) + def StartNotify(self): + print('Default StartNotify called, returning error') + raise NotSupportedException() + + @dbus.service.method(GATT_CHRC_IFACE) + def StopNotify(self): + print('Default StopNotify called, returning error') + raise NotSupportedException() + + @dbus.service.signal(DBUS_PROP_IFACE, + signature='sa{sv}as') + def PropertiesChanged(self, interface, changed, invalidated): + pass + + def get_bus(self): + bus = self.bus + + return bus + + def get_next_index(self): + idx = self.next_index + self.next_index += 1 + + return idx + + def add_timeout(self, timeout, callback): + GObject.timeout_add(timeout, callback) + + +class Descriptor(dbus.service.Object): + def __init__(self, uuid, flags, characteristic): + index = characteristic.get_next_index() + self.path = characteristic.path + '/desc' + str(index) + self.uuid = uuid + self.flags = flags + self.chrc = characteristic + self.bus = characteristic.get_bus() + dbus.service.Object.__init__(self, self.bus, self.path) + + def get_properties(self): + return { + GATT_DESC_IFACE: { + 'Characteristic': self.chrc.get_path(), + 'UUID': self.uuid, + 'Flags': self.flags, + } + } + + def get_path(self): + return dbus.ObjectPath(self.path) + + @dbus.service.method(DBUS_PROP_IFACE, + in_signature='s', + out_signature='a{sv}') + def GetAll(self, interface): + if interface != GATT_DESC_IFACE: + raise InvalidArgsException() + + return self.get_properties()[GATT_DESC_IFACE] + + @dbus.service.method(GATT_DESC_IFACE, + in_signature='a{sv}', + out_signature='ay') + def ReadValue(self, options): + print('Default ReadValue called, returning error') + raise NotSupportedException() + + @dbus.service.method(GATT_DESC_IFACE, in_signature='aya{sv}') + def WriteValue(self, value, options): + print('Default WriteValue called, returning error') + raise NotSupportedException() + + +class CharacteristicUserDescriptionDescriptor(Descriptor): + CUD_UUID = '2901' + + def __init__(self, bus, index, characteristic): + self.writable = 'writable-auxiliaries' in characteristic.flags + self.value = array.array('B', b'This is a characteristic for testing') + self.value = self.value.tolist() + Descriptor.__init__( + self, bus, index, + self.CUD_UUID, + ['read', 'write'], + characteristic) + + def ReadValue(self, options): + return self.value + + def WriteValue(self, value, options): + if not self.writable: + raise NotPermittedException() + self.value = value diff --git a/Communication/notes.txt b/Communication/notes.txt new file mode 100644 index 0000000..e69de29 diff --git a/Communication/testConnection.py b/Communication/testConnection.py new file mode 100644 index 0000000..c94b6fd --- /dev/null +++ b/Communication/testConnection.py @@ -0,0 +1,341 @@ +""" +Start connection with smartphone and send a hello message +""" +import time + +import dbus + +from ble_gatt_server.advertisement import Advertisement +from ble_gatt_server.service import Application, Service, Characteristic, Descriptor + +GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1" +NOTIFY_TIMEOUT = 5000 + + +class BleApplication(Application): + pass + + +class MagicMirrorAdvertisement(Advertisement): + def __init__(self, index): + Advertisement.__init__(self, index, "peripheral") + self.add_local_name("MagicMirror") + self.include_tx_power = True + + +class TestService(Service): + # todo: change? + TEST_SVC_UUID = "00000000-8cb1-44ce-9a66-001dca0941a6" + + def __init__(self, index): + Service.__init__(self, index, self.TEST_SVC_UUID, True) + self.add_characteristic(HelloCharacteristic(self)) + + +class HelloCharacteristic(Characteristic): + HELLO_CHARACTERISTIC_UUID = "00000001-8cb1-44ce-9a66-001dca0941a6" + + def __init__(self, service): + self.notifying = False + + Characteristic.__init__( + self, self.HELLO_CHARACTERISTIC_UUID, + ["notify", "read"], service) + self.add_descriptor(HelloDescriptor(self)) + + def get_hello(self): + value = [] + + data = 'Hello there '# + str(time.time()) + # data = 'D=%s,W=%s,C=%s' % (degrees, weather_id, city_id) + print('Sending: ', data, flush=True) + + for c in data: + value.append(dbus.Byte(c.encode())) + + return value + + def set_hello_callback(self): + if self.notifying: + value = self.get_hello() + self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + + return self.notifying + + def StartNotify(self): + if self.notifying: + return + + self.notifying = True + print('Start notify weather service', flush=True) + + value = self.get_hello() + self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + self.add_timeout(NOTIFY_TIMEOUT, self.set_hello_callback) + + def StopNotify(self): + self.notifying = False + + def ReadValue(self, options): + value = self.get_hello() + + return value + + +# todo: What is descriptor ? !!! + +class HelloDescriptor(Descriptor): + HELLO_DESCRIPTOR_UUID = "0001" + HELLO_DESCRIPTOR_VALUE = "Send hello messages" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.HELLO_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.HELLO_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + +""" +class ResumeWeatherCharacteristic(Characteristic): + RESUME_WEATHER_CHARACTERISTIC_UUID = "00000002-8cb1-44ce-9a66-001dca0941a6" + + def __init__(self, service): + Characteristic.__init__( + self, self.RESUME_WEATHER_CHARACTERISTIC_UUID, + ["write"], service) + self.add_descriptor(ResumeWeatherDescriptor(self)) + + def WriteValue(self, value, options): + print('Resume command received', flush=True) + self.service.get_characteristics()[0].StartNotify() + + +class ResumeWeatherDescriptor(Descriptor): + RESUME_WEATHER_DESCRIPTOR_UUID = "0002" + RESUME_WEATHER_DESCRIPTOR_VALUE = "Resume weather" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.RESUME_WEATHER_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.RESUME_WEATHER_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +class CityIdCharacteristic(Characteristic): + CITY_ID_CHARACTERISTIC_UUID = "00000003-8cb1-44ce-9a66-001dca0941a6" + + def __init__(self, service): + Characteristic.__init__( + self, self.CITY_ID_CHARACTERISTIC_UUID, + ["read", "write"], service) + self.add_descriptor(CityIdDescriptor(self)) + + def WriteValue(self, value, options): + print('Value received: ', (str(value)), flush=True) + val = "".join(map(chr, value)) + print('New city value:', val, flush=True) + + self.service.set_city_id(val) + self.service.get_characteristics()[0].StartNotify() + + def ReadValue(self, options): + value = [] + + val = self.service.get_city_id() + value.append(dbus.Byte(val.encode())) + + return value + + +class CityIdDescriptor(Descriptor): + CITY_ID_DESCRIPTOR_UUID = "0003" + CITY_ID_DESCRIPTOR_VALUE = "City id" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.CITY_ID_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.CITY_ID_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +class RgbColorService(Service): + RGB_COLOR_SVC_UUID = "00000000-8194-4451-aaf5-7874c7c16a27" + + def __init__(self, index): + Service.__init__(self, index, self.RGB_COLOR_SVC_UUID, True) + self.add_characteristic(RgbColorCharacteristic(self)) + + def get_rgb_color(self): + return self.rgb_color + + def set_rgb_color(self, rgb_color): + self.rgb_color = rgb_color + + +class RgbColorCharacteristic(Characteristic): + RGB_COLOR_CHARACTERISTIC_UUID = "00000001-8194-4451-aaf5-7874c7c16a27" + + def __init__(self, service): + Characteristic.__init__( + self, self.RGB_COLOR_CHARACTERISTIC_UUID, + ["write"], service) + self.add_descriptor(RgbColorDescriptor(self)) + + def WriteValue(self, value, options): + app.services[0].get_characteristics()[0].StopNotify() + print('Weather service notifying stopped', flush=True) + + print('Value received: ', (str(value)), flush=True) + val = "".join(map(chr, value)) + print('New rgb color value: ', val, flush=True) + + self.service.set_rgb_color(val) + + +class RgbColorDescriptor(Descriptor): + RGB_COLOR_DESCRIPTOR_UUID = "0001" + RGB_COLOR_DESCRIPTOR_VALUE = "RGB Color array" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.RGB_COLOR_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.RGB_COLOR_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +class SystemService(Service): + SYSTEM_SVC_UUID = "00000000-61c8-471e-94f3-5050570167b2" + + def __init__(self, index): + Service.__init__(self, index, self.SYSTEM_SVC_UUID, True) + self.add_characteristic(IpAddressSystemCharacteristic(self)) + self.add_characteristic(ShutdownSystemCharacteristic(self)) + + def get_ip_address(self): + return self.ip_address + + def set_ip_address(self, ip_address): + self.ip_address = ip_address + + +class IpAddressSystemCharacteristic(Characteristic): + IP_ADDRESS_SYSTEM_CHARACTERISTIC_UUID = "00000001-61c8-471e-94f3-5050570167b2" + + def __init__(self, service): + Characteristic.__init__( + self, self.IP_ADDRESS_SYSTEM_CHARACTERISTIC_UUID, + ["read"], service) + self.add_descriptor(IpAddressSystemDescriptor(self)) + + def ReadValue(self, options): + value = [] + + data = self.service.get_ip_address() + for c in data: + value.append(dbus.Byte(c.encode())) + + return value + + +class IpAddressSystemDescriptor(Descriptor): + IP_ADDRESS_SYSTEM_DESCRIPTOR_UUID = "0001" + IP_ADDRESS_SYSTEM_DESCRIPTOR_VALUE = "Ip address" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.IP_ADDRESS_SYSTEM_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.IP_ADDRESS_SYSTEM_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +class ShutdownSystemCharacteristic(Characteristic): + SHUTDOWN_SYSTEM_CHARACTERISTIC_UUID = "00000002-61c8-471e-94f3-5050570167b2" + + def __init__(self, service): + Characteristic.__init__( + self, self.SHUTDOWN_SYSTEM_CHARACTERISTIC_UUID, + ["write"], service) + self.add_descriptor(ShutdownSystemDescriptor(self)) + + def WriteValue(self, value, options): + print('Shutdown command received', flush=True) + app.services[0].get_characteristics()[0].StopNotify() + print('Weather service notifying stopped', flush=True) + ##### app.shutdown() + + +class ShutdownSystemDescriptor(Descriptor): + SHUTDOWN_SYSTEM_DESCRIPTOR_UUID = "0001" + SHUTDOWN_SYSTEM_DESCRIPTOR_VALUE = "Shutdown system" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.SHUTDOWN_SYSTEM_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.SHUTDOWN_SYSTEM_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value +""" + +app = Application() +app.add_service(TestService(0)) +app.register() + +adv = MagicMirrorAdvertisement(0) +adv.register() + +try: + app.run() +except KeyboardInterrupt: + app.quit() \ No newline at end of file From 6cecc8e072b55310db9d7be00b182032b95c3f8d Mon Sep 17 00:00:00 2001 From: n1klasD <67094918+n1klasD@users.noreply.github.com> Date: Tue, 1 Mar 2022 11:43:33 +0100 Subject: [PATCH 02/22] refactory paths --- .../{ble_gatt_server => }/advertisement.py | 0 Communication/{ble_gatt_server => }/bletools.py | 0 Communication/{ble_gatt_server => }/service.py | 0 Communication/testConnection.py | 5 ++--- install.sh | 15 +++++++++++++++ 5 files changed, 17 insertions(+), 3 deletions(-) rename Communication/{ble_gatt_server => }/advertisement.py (100%) rename Communication/{ble_gatt_server => }/bletools.py (100%) rename Communication/{ble_gatt_server => }/service.py (100%) create mode 100644 install.sh diff --git a/Communication/ble_gatt_server/advertisement.py b/Communication/advertisement.py similarity index 100% rename from Communication/ble_gatt_server/advertisement.py rename to Communication/advertisement.py diff --git a/Communication/ble_gatt_server/bletools.py b/Communication/bletools.py similarity index 100% rename from Communication/ble_gatt_server/bletools.py rename to Communication/bletools.py diff --git a/Communication/ble_gatt_server/service.py b/Communication/service.py similarity index 100% rename from Communication/ble_gatt_server/service.py rename to Communication/service.py diff --git a/Communication/testConnection.py b/Communication/testConnection.py index c94b6fd..9c7629e 100644 --- a/Communication/testConnection.py +++ b/Communication/testConnection.py @@ -1,12 +1,11 @@ """ Start connection with smartphone and send a hello message """ -import time import dbus -from ble_gatt_server.advertisement import Advertisement -from ble_gatt_server.service import Application, Service, Characteristic, Descriptor +from Communication.advertisement import Advertisement +from Communication.service import Application, Service, Characteristic, Descriptor GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1" NOTIFY_TIMEOUT = 5000 diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..427507d --- /dev/null +++ b/install.sh @@ -0,0 +1,15 @@ +# enable camera in raspi config +sudo apt update +sudo apt upgrade +sudo reboot +git clone https://github.com/n1klasD/MagicController.git +cd MagicController +git checkout PyDeploy +sudo curl -s https://get.docker.com | bash +sudo usermod -aG docker pi +create the file /etc/udev/rules.d/99-camera.rules with content: SUBSYSTEM=="vchiq",MODE="0666" + +sudo docker run -it --device /dev/vchiq --env LD_LIBRARY_PATH=/opt/vc/lib -v /opt/vc:/opt/vc + +# bluetooth +ExecStart=/usr/lib/bluetooth/bluetoothd -E \ No newline at end of file From 465ca4629c13f4c49b9997bad59d1a9734aa71a8 Mon Sep 17 00:00:00 2001 From: n1klasD <67094918+n1klasD@users.noreply.github.com> Date: Tue, 1 Mar 2022 11:46:47 +0100 Subject: [PATCH 03/22] import errors --- Communication/__init__.py | 3 +++ Communication/testConnection.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Communication/__init__.py b/Communication/__init__.py index e69de29..4b8378a 100644 --- a/Communication/__init__.py +++ b/Communication/__init__.py @@ -0,0 +1,3 @@ +from .bletools import BleTools +from .advertisement import * +from .service import * \ No newline at end of file diff --git a/Communication/testConnection.py b/Communication/testConnection.py index 9c7629e..5207683 100644 --- a/Communication/testConnection.py +++ b/Communication/testConnection.py @@ -4,8 +4,8 @@ import dbus -from Communication.advertisement import Advertisement -from Communication.service import Application, Service, Characteristic, Descriptor +from advertisement import Advertisement +from service import Application, Service, Characteristic, Descriptor GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1" NOTIFY_TIMEOUT = 5000 From 4a987615d176571ca08bdfd7ec8152cb409f7e33 Mon Sep 17 00:00:00 2001 From: n1klasD <67094918+n1klasD@users.noreply.github.com> Date: Tue, 1 Mar 2022 12:07:19 +0100 Subject: [PATCH 04/22] added further test --- Communication/reference.py | 171 ++++++++++++++++++++++++++++++++ Communication/testConnection.py | 16 +-- 2 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 Communication/reference.py diff --git a/Communication/reference.py b/Communication/reference.py new file mode 100644 index 0000000..a8b8e69 --- /dev/null +++ b/Communication/reference.py @@ -0,0 +1,171 @@ +#!/usr/bin/python3 + +"""Copyright (c) 2019, Douglas Otwell +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. +""" +import time + +import dbus + +from advertisement import Advertisement +from service import Application, Service, Characteristic, Descriptor + +GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1" +NOTIFY_TIMEOUT = 5000 + + +class ThermometerAdvertisement(Advertisement): + def __init__(self, index): + Advertisement.__init__(self, index, "peripheral") + self.add_local_name("Thermometer") + self.include_tx_power = True + + +class ThermometerService(Service): + THERMOMETER_SVC_UUID = "00000001-710e-4a5b-8d75-3e5b444bc3cf" + + def __init__(self, index): + Service.__init__(self, index, self.THERMOMETER_SVC_UUID, True) + self.add_characteristic(TempCharacteristic(self)) + self.add_characteristic(UnitCharacteristic(self)) + + +class TempCharacteristic(Characteristic): + TEMP_CHARACTERISTIC_UUID = "00000002-710e-4a5b-8d75-3e5b444bc3cf" + + def __init__(self, service): + self.notifying = False + + Characteristic.__init__( + self, self.TEMP_CHARACTERISTIC_UUID, + ["notify", "read"], service) + self.add_descriptor(TempDescriptor(self)) + + def get_temperature(self): + value = [] + + strtemp = "hello " + str(time.time()) + for c in strtemp: + value.append(dbus.Byte(c.encode())) + + return value + + def set_temperature_callback(self): + if self.notifying: + value = self.get_temperature() + self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + + return self.notifying + + def StartNotify(self): + if self.notifying: + return + + self.notifying = True + + value = self.get_temperature() + self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + self.add_timeout(NOTIFY_TIMEOUT, self.set_temperature_callback) + + def StopNotify(self): + self.notifying = False + + def ReadValue(self, options): + value = self.get_temperature() + + return value + + +class TempDescriptor(Descriptor): + TEMP_DESCRIPTOR_UUID = "2901" + TEMP_DESCRIPTOR_VALUE = "CPU Temperature" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.TEMP_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.TEMP_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +class UnitCharacteristic(Characteristic): + UNIT_CHARACTERISTIC_UUID = "00000003-710e-4a5b-8d75-3e5b444bc3cf" + + def __init__(self, service): + Characteristic.__init__( + self, self.UNIT_CHARACTERISTIC_UUID, + ["read", "write"], service) + self.add_descriptor(UnitDescriptor(self)) + + def WriteValue(self, value, options): + val = str(value[0]).upper() + if val == "C": + self.service.set_farenheit(False) + elif val == "F": + self.service.set_farenheit(True) + + def ReadValue(self, options): + value = [] + + if self.service.is_farenheit(): + val = "F" + else: + val = "C" + value.append(dbus.Byte(val.encode())) + + return value + + +class UnitDescriptor(Descriptor): + UNIT_DESCRIPTOR_UUID = "2901" + UNIT_DESCRIPTOR_VALUE = "Temperature Units (F or C)" + + def __init__(self, characteristic): + Descriptor.__init__( + self, self.UNIT_DESCRIPTOR_UUID, + ["read"], + characteristic) + + def ReadValue(self, options): + value = [] + desc = self.UNIT_DESCRIPTOR_VALUE + + for c in desc: + value.append(dbus.Byte(c.encode())) + + return value + + +app = Application() +app.add_service(ThermometerService(0)) +app.register() + +adv = ThermometerAdvertisement(0) +adv.register() + +try: + app.run() +except KeyboardInterrupt: + app.quit() diff --git a/Communication/testConnection.py b/Communication/testConnection.py index 5207683..f7f8c61 100644 --- a/Communication/testConnection.py +++ b/Communication/testConnection.py @@ -1,6 +1,7 @@ """ Start connection with smartphone and send a hello message """ +import time import dbus @@ -11,10 +12,6 @@ NOTIFY_TIMEOUT = 5000 -class BleApplication(Application): - pass - - class MagicMirrorAdvertisement(Advertisement): def __init__(self, index): Advertisement.__init__(self, index, "peripheral") @@ -45,7 +42,7 @@ def __init__(self, service): def get_hello(self): value = [] - data = 'Hello there '# + str(time.time()) + data = 'Hello there ' # + str(time.time()) # data = 'D=%s,W=%s,C=%s' % (degrees, weather_id, city_id) print('Sending: ', data, flush=True) @@ -102,6 +99,7 @@ def ReadValue(self, options): return value + """ class ResumeWeatherCharacteristic(Characteristic): RESUME_WEATHER_CHARACTERISTIC_UUID = "00000002-8cb1-44ce-9a66-001dca0941a6" @@ -336,5 +334,11 @@ def ReadValue(self, options): try: app.run() + + while True: + # update "hello" + time.sleep(1) + app.services[1].he + except KeyboardInterrupt: - app.quit() \ No newline at end of file + app.quit() From 5b7278797df80bfff43b36430288039ad1856c8f Mon Sep 17 00:00:00 2001 From: n1klasD <67094918+n1klasD@users.noreply.github.com> Date: Tue, 1 Mar 2022 12:12:18 +0100 Subject: [PATCH 05/22] f --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index a8b8e69..941296b 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -31,7 +31,7 @@ class ThermometerAdvertisement(Advertisement): def __init__(self, index): Advertisement.__init__(self, index, "peripheral") - self.add_local_name("Thermometer") + self.add_local_name("MagicMirror") self.include_tx_power = True From ef45b3a3620d5fb98d12843167ea259bd63e2e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 13:37:05 +0100 Subject: [PATCH 06/22] added print debug --- Communication/reference.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Communication/reference.py b/Communication/reference.py index 941296b..4871e60 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -57,6 +57,8 @@ def __init__(self, service): def get_temperature(self): value = [] + + print("Called hello function") strtemp = "hello " + str(time.time()) for c in strtemp: From fe37af2c34e1909b14c8f80d9b6930b22d63eb93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 13:42:12 +0100 Subject: [PATCH 07/22] changed name --- Communication/reference.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index 4871e60..c497d44 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -31,7 +31,7 @@ class ThermometerAdvertisement(Advertisement): def __init__(self, index): Advertisement.__init__(self, index, "peripheral") - self.add_local_name("MagicMirror") + self.add_local_name("Thermometer") self.include_tx_power = True @@ -57,7 +57,7 @@ def __init__(self, service): def get_temperature(self): value = [] - + print("Called hello function") strtemp = "hello " + str(time.time()) From 97fcf2dd048c28fd035d357c83d22bf22f005d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 15:36:04 +0100 Subject: [PATCH 08/22] request response test --- Communication/reference.py | 117 ++++++++++--------------------------- 1 file changed, 31 insertions(+), 86 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index c497d44..2755c7d 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -31,66 +31,58 @@ class ThermometerAdvertisement(Advertisement): def __init__(self, index): Advertisement.__init__(self, index, "peripheral") - self.add_local_name("Thermometer") + self.add_local_name("MagicMirror") self.include_tx_power = True -class ThermometerService(Service): - THERMOMETER_SVC_UUID = "00000001-710e-4a5b-8d75-3e5b444bc3cf" +class HelloService(Service): + HELLO_SVC_UUID = "00000001-710e-4a5b-8d75-3e5b444bc3cf" def __init__(self, index): - Service.__init__(self, index, self.THERMOMETER_SVC_UUID, True) - self.add_characteristic(TempCharacteristic(self)) - self.add_characteristic(UnitCharacteristic(self)) + Service.__init__(self, index, self.HELLO_SVC_UUID, True) + self.add_characteristic(HelloCharacteristic(self)) -class TempCharacteristic(Characteristic): - TEMP_CHARACTERISTIC_UUID = "00000002-710e-4a5b-8d75-3e5b444bc3cf" +class HelloCharacteristic(Characteristic): + HELLO_CHARACTERISTIC_UUID = "00000002-710e-4a5b-8d75-3e5b444bc3cf" def __init__(self, service): - self.notifying = False Characteristic.__init__( - self, self.TEMP_CHARACTERISTIC_UUID, - ["notify", "read"], service) + self, self.HELLO_CHARACTERISTIC_UUID, + ["read", "write", "notify"], service) self.add_descriptor(TempDescriptor(self)) - def get_temperature(self): - value = [] - - print("Called hello function") - - strtemp = "hello " + str(time.time()) - for c in strtemp: - value.append(dbus.Byte(c.encode())) - - return value - - def set_temperature_callback(self): - if self.notifying: - value = self.get_temperature() - self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + def WriteValue(self, value, options): + """ + App sends value to characteristics - return self.notifying + """ - def StartNotify(self): - if self.notifying: - return + request = str(value[0]) + print("request", request) - self.notifying = True + time.sleep(0.5) - value = self.get_temperature() + # send response + value = [] + reply = 'OK' + value.append(dbus.Byte(reply.encode())) + print("Notify response: OK") self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) - self.add_timeout(NOTIFY_TIMEOUT, self.set_temperature_callback) - - def StopNotify(self): - self.notifying = False def ReadValue(self, options): - value = self.get_temperature() + """ + App reads characteristic from Pi - return value + """ + value = [] + reply = 'OK' + value.append(dbus.Byte(reply.encode())) + print("Normal read: OK") + + return value class TempDescriptor(Descriptor): TEMP_DESCRIPTOR_UUID = "2901" @@ -112,56 +104,9 @@ def ReadValue(self, options): return value -class UnitCharacteristic(Characteristic): - UNIT_CHARACTERISTIC_UUID = "00000003-710e-4a5b-8d75-3e5b444bc3cf" - - def __init__(self, service): - Characteristic.__init__( - self, self.UNIT_CHARACTERISTIC_UUID, - ["read", "write"], service) - self.add_descriptor(UnitDescriptor(self)) - - def WriteValue(self, value, options): - val = str(value[0]).upper() - if val == "C": - self.service.set_farenheit(False) - elif val == "F": - self.service.set_farenheit(True) - - def ReadValue(self, options): - value = [] - - if self.service.is_farenheit(): - val = "F" - else: - val = "C" - value.append(dbus.Byte(val.encode())) - - return value - - -class UnitDescriptor(Descriptor): - UNIT_DESCRIPTOR_UUID = "2901" - UNIT_DESCRIPTOR_VALUE = "Temperature Units (F or C)" - - def __init__(self, characteristic): - Descriptor.__init__( - self, self.UNIT_DESCRIPTOR_UUID, - ["read"], - characteristic) - - def ReadValue(self, options): - value = [] - desc = self.UNIT_DESCRIPTOR_VALUE - - for c in desc: - value.append(dbus.Byte(c.encode())) - - return value - app = Application() -app.add_service(ThermometerService(0)) +app.add_service(HelloService(0)) app.register() adv = ThermometerAdvertisement(0) From 5ea3fc75c51b94d14317eb618dbaadc0b4d429e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 15:50:38 +0100 Subject: [PATCH 09/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index 2755c7d..dc5b7af 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -59,7 +59,7 @@ def WriteValue(self, value, options): """ - request = str(value[0]) + request = str(value) print("request", request) time.sleep(0.5) From d9525c73553047839d7081fb1e71f70c77b89619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 15:57:25 +0100 Subject: [PATCH 10/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index dc5b7af..543dd0b 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -59,7 +59,7 @@ def WriteValue(self, value, options): """ - request = str(value) + request = value.decode("utf-8") print("request", request) time.sleep(0.5) From d46e9d67f9e0466314c19598c6911d4791044e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:00:27 +0100 Subject: [PATCH 11/22] Update reference.py --- Communication/reference.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Communication/reference.py b/Communication/reference.py index 543dd0b..1b177e8 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -59,7 +59,9 @@ def WriteValue(self, value, options): """ + print("received message") request = value.decode("utf-8") + print("decoded") print("request", request) time.sleep(0.5) From 3a70ddb0f0e18cbb5a7e5ab0697bc01eac55be0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:01:19 +0100 Subject: [PATCH 12/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index 1b177e8..9ecc886 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,7 +60,7 @@ def WriteValue(self, value, options): """ print("received message") - request = value.decode("utf-8") + request = str(value[0]) print("decoded") print("request", request) From d48f2d01ce89556db22b05da2e8f3d458fb1225c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:02:08 +0100 Subject: [PATCH 13/22] Update reference.py --- Communication/reference.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index 9ecc886..5d67baf 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -64,8 +64,6 @@ def WriteValue(self, value, options): print("decoded") print("request", request) - time.sleep(0.5) - # send response value = [] reply = 'OK' From b5bd0e73b08c1d8258acb4005a45199996f4b38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:10:13 +0100 Subject: [PATCH 14/22] Update reference.py --- Communication/reference.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index 5d67baf..8e14001 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,16 +60,16 @@ def WriteValue(self, value, options): """ print("received message") - request = str(value[0]) + request = value.decode() print("decoded") print("request", request) # send response - value = [] - reply = 'OK' - value.append(dbus.Byte(reply.encode())) - print("Notify response: OK") - self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) + # value = [] + # reply = 'OK' + # value.append(dbus.Byte(reply.encode())) + # print("Notify response: OK") + # self.PropertiesChanged(GATT_CHRC_IFACE, {"Value": value}, []) def ReadValue(self, options): """ From 33110d890dc350e2a7d782c98de7449d0bec3bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:11:19 +0100 Subject: [PATCH 15/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index 8e14001..3da8c53 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -59,7 +59,7 @@ def WriteValue(self, value, options): """ - print("received message") + print("received message: ", value, type(value)) request = value.decode() print("decoded") print("request", request) From 7ac97b90c33a24e8a4bb032dd308302145d99123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:11:35 +0100 Subject: [PATCH 16/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index 3da8c53..5a6b92c 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,7 +60,7 @@ def WriteValue(self, value, options): """ print("received message: ", value, type(value)) - request = value.decode() + request = str(value[0]) print("decoded") print("request", request) From e09aea929cafdca925de4b47e9206147ad3289d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:13:38 +0100 Subject: [PATCH 17/22] Update reference.py --- Communication/reference.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index 5a6b92c..dd55f49 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -58,11 +58,13 @@ def WriteValue(self, value, options): App sends value to characteristics """ - - print("received message: ", value, type(value)) - request = str(value[0]) - print("decoded") - print("request", request) + try: + print("received message: ", value, type(value)) + request = str(value[0]) + print("decoded") + print("request", request) + except Exception as e: + print(e) # send response # value = [] From 8ba36506cd3a59887cf2a7a9df004eab1113e571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:17:27 +0100 Subject: [PATCH 18/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index dd55f49..7afb98d 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,7 +60,7 @@ def WriteValue(self, value, options): """ try: print("received message: ", value, type(value)) - request = str(value[0]) + request = "".join([str(c) for c in value]) print("decoded") print("request", request) except Exception as e: From 67c4065fb102a62da30e9696b4ad0ea8780340f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:24:31 +0100 Subject: [PATCH 19/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index 7afb98d..bd704ec 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,7 +60,7 @@ def WriteValue(self, value, options): """ try: print("received message: ", value, type(value)) - request = "".join([str(c) for c in value]) + request = bytes(value).decode() print("decoded") print("request", request) except Exception as e: From 63f689a9af7fa08d7971e0346764bc70ad25a4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:32:21 +0100 Subject: [PATCH 20/22] Update reference.py --- Communication/reference.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index bd704ec..d465ecc 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -60,11 +60,12 @@ def WriteValue(self, value, options): """ try: print("received message: ", value, type(value)) - request = bytes(value).decode() + # request = bytes(value).decode() + request = str(value[0]) print("decoded") print("request", request) except Exception as e: - print(e) + print(e, flush=True) # send response # value = [] From cd7572a0b2e6904cb7500680dc8dd8da6a3afcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:34:43 +0100 Subject: [PATCH 21/22] Update reference.py --- Communication/reference.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Communication/reference.py b/Communication/reference.py index d465ecc..ed6e996 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -59,11 +59,11 @@ def WriteValue(self, value, options): """ try: - print("received message: ", value, type(value)) + print("received message: ", value, type(value), flush=True) # request = bytes(value).decode() request = str(value[0]) - print("decoded") - print("request", request) + print("decoded", flush=True) + print("request", request, flush=True) except Exception as e: print(e, flush=True) From 50be4adfc7405fd65d1f7f7b0baf40d018a51578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Dr=C3=B6ssler?= Date: Thu, 3 Mar 2022 16:38:32 +0100 Subject: [PATCH 22/22] Update reference.py --- Communication/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Communication/reference.py b/Communication/reference.py index ed6e996..8ec1105 100644 --- a/Communication/reference.py +++ b/Communication/reference.py @@ -50,7 +50,7 @@ def __init__(self, service): Characteristic.__init__( self, self.HELLO_CHARACTERISTIC_UUID, - ["read", "write", "notify"], service) + ["read", "write"], service) self.add_descriptor(TempDescriptor(self)) def WriteValue(self, value, options):