From e838e0ddd297d5cf70c387bb996a037a9de34bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 10 Jan 2020 12:18:05 +0100 Subject: [PATCH] Add nuki plugin Revert copyright changes --- debian/control | 17 + debian/copyright | 1 + debian/nymea-plugin-nuki.install.in | 1 + nuki/README.md | 3 + nuki/bluez/bluetoothadapter.cpp | 416 ++++++++++++ nuki/bluez/bluetoothadapter.h | 152 +++++ nuki/bluez/bluetoothdevice.cpp | 546 ++++++++++++++++ nuki/bluez/bluetoothdevice.h | 185 ++++++ nuki/bluez/bluetoothgattcharacteristic.cpp | 368 +++++++++++ nuki/bluez/bluetoothgattcharacteristic.h | 132 ++++ nuki/bluez/bluetoothgattdescriptor.cpp | 219 +++++++ nuki/bluez/bluetoothgattdescriptor.h | 104 +++ nuki/bluez/bluetoothgattservice.cpp | 168 +++++ nuki/bluez/bluetoothgattservice.h | 96 +++ nuki/bluez/bluetoothmanager.cpp | 306 +++++++++ nuki/bluez/bluetoothmanager.h | 85 +++ nuki/bluez/blueztypes.cpp | 32 + nuki/bluez/blueztypes.h | 103 +++ nuki/devicepluginnuki.cpp | 325 ++++++++++ nuki/devicepluginnuki.h | 78 +++ nuki/devicepluginnuki.json | 157 +++++ nuki/docs/20170619-Bridge-API-v1.6.pdf | Bin 0 -> 161131 bytes nuki/docs/20171120.Smartlock.API_.v1.10.pdf | Bin 0 -> 367134 bytes nuki/nuki.cpp | 556 ++++++++++++++++ nuki/nuki.h | 136 ++++ nuki/nuki.pro | 36 ++ nuki/nukiauthenticator.cpp | 602 ++++++++++++++++++ nuki/nukiauthenticator.h | 132 ++++ nuki/nukicontroller.cpp | 524 +++++++++++++++ nuki/nukicontroller.h | 113 ++++ nuki/nukiutils.cpp | 171 +++++ nuki/nukiutils.h | 167 +++++ nuki/plugins.pri | 63 ++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-cs.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-da.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-de.ts | 169 +++++ ...06d75-a40e-4766-a272-5a3a8d3ed625-en_US.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-es.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-fr.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-it.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-nl.ts | 169 +++++ ...e5806d75-a40e-4766-a272-5a3a8d3ed625-pt.ts | 169 +++++ nymea-plugins.pro | 1 + 43 files changed, 7516 insertions(+) create mode 100644 debian/nymea-plugin-nuki.install.in create mode 100644 nuki/README.md create mode 100644 nuki/bluez/bluetoothadapter.cpp create mode 100644 nuki/bluez/bluetoothadapter.h create mode 100644 nuki/bluez/bluetoothdevice.cpp create mode 100644 nuki/bluez/bluetoothdevice.h create mode 100644 nuki/bluez/bluetoothgattcharacteristic.cpp create mode 100644 nuki/bluez/bluetoothgattcharacteristic.h create mode 100644 nuki/bluez/bluetoothgattdescriptor.cpp create mode 100644 nuki/bluez/bluetoothgattdescriptor.h create mode 100644 nuki/bluez/bluetoothgattservice.cpp create mode 100644 nuki/bluez/bluetoothgattservice.h create mode 100644 nuki/bluez/bluetoothmanager.cpp create mode 100644 nuki/bluez/bluetoothmanager.h create mode 100644 nuki/bluez/blueztypes.cpp create mode 100644 nuki/bluez/blueztypes.h create mode 100644 nuki/devicepluginnuki.cpp create mode 100644 nuki/devicepluginnuki.h create mode 100644 nuki/devicepluginnuki.json create mode 100644 nuki/docs/20170619-Bridge-API-v1.6.pdf create mode 100755 nuki/docs/20171120.Smartlock.API_.v1.10.pdf create mode 100644 nuki/nuki.cpp create mode 100644 nuki/nuki.h create mode 100644 nuki/nuki.pro create mode 100644 nuki/nukiauthenticator.cpp create mode 100644 nuki/nukiauthenticator.h create mode 100644 nuki/nukicontroller.cpp create mode 100644 nuki/nukicontroller.h create mode 100644 nuki/nukiutils.cpp create mode 100644 nuki/nukiutils.h create mode 100644 nuki/plugins.pri create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-cs.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-da.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-de.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-en_US.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-es.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-fr.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-it.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-nl.ts create mode 100644 nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-pt.ts diff --git a/debian/control b/debian/control index 596620f0..4bb9f9bc 100644 --- a/debian/control +++ b/debian/control @@ -14,6 +14,7 @@ Build-depends: libboblight-dev, qtbase5-dev, qtconnectivity5-dev, libow-dev, + libsodium-dev, Standards-Version: 3.9.3 @@ -453,6 +454,21 @@ Description: nymea.io plugin for networkdetector This package will install the nymea.io plugin for networkdetector +Package: nymea-plugin-nuki +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends}, + libsodium23, + nymea-plugins-translations, +Description: nymea.io plugin for the nuki smart lock + The nymea daemon is a plugin based IoT (Internet of Things) server. The + server works like a translator for devices, things and services and + allows them to interact. + With the powerful rule engine you are able to connect any device available + in the system and create individual scenes and behaviors for your environment. + . + This package will install the nymea.io plugin for nuki devices + Package: nymea-plugin-onewire Architecture: any @@ -877,6 +893,7 @@ Depends: nymea-plugin-anel, nymea-plugin-texasinstruments, nymea-plugin-netatmo, nymea-plugin-networkdetector, + nymea-plugin-nuki, nymea-plugin-openuv, nymea-plugin-openweathermap, nymea-plugin-philipshue, diff --git a/debian/copyright b/debian/copyright index 268ef872..ae9f1c2c 100644 --- a/debian/copyright +++ b/debian/copyright @@ -54,6 +54,7 @@ Files: avahimonitor/* mailnotification/* netatmo/* networkdetector/* + nuki/* osdomotics/* senic/* udpcommander/* diff --git a/debian/nymea-plugin-nuki.install.in b/debian/nymea-plugin-nuki.install.in new file mode 100644 index 00000000..c0373c50 --- /dev/null +++ b/debian/nymea-plugin-nuki.install.in @@ -0,0 +1 @@ +usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginnuki.so diff --git a/nuki/README.md b/nuki/README.md new file mode 100644 index 00000000..55891fa1 --- /dev/null +++ b/nuki/README.md @@ -0,0 +1,3 @@ +# nymea-plugin-nuki + +Device plugin for the [Nuki Smartlock](https://nuki.io/en/) Bluetooth API. diff --git a/nuki/bluez/bluetoothadapter.cpp b/nuki/bluez/bluetoothadapter.cpp new file mode 100644 index 00000000..75c9596f --- /dev/null +++ b/nuki/bluez/bluetoothadapter.cpp @@ -0,0 +1,416 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothadapter.h" +#include "blueztypes.h" + +#include + +QString BluetoothAdapter::name() const +{ + return m_name; +} + +QString BluetoothAdapter::alias() const +{ + return m_alias; +} + +bool BluetoothAdapter::setAlias(const QString &alias) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("Alias", QVariant(alias)); +} + +QString BluetoothAdapter::address() const +{ + return m_address; +} + +QString BluetoothAdapter::modalias() const +{ + return m_modalias; +} + +bool BluetoothAdapter::discovering() const +{ + return m_discovering; +} + +bool BluetoothAdapter::discoverable() const +{ + return m_discoverable; +} + +bool BluetoothAdapter::setDiscoverable(const bool &discoverable) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("Discoverable", QVariant(discoverable)); +} + +uint BluetoothAdapter::discoverableTimeout() const +{ + return m_discoverableTimeout; +} + +bool BluetoothAdapter::setDiscoverableTimeout(const uint &seconds) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("DiscoverableTimeout", QVariant(seconds)); +} + +bool BluetoothAdapter::pairable() const +{ + return m_pairable; +} + +bool BluetoothAdapter::setPairable(const bool &pairable) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("Pairable", QVariant(pairable)); +} + +uint BluetoothAdapter::pairableTimeout() const +{ + return m_pairableTimeout; +} + +bool BluetoothAdapter::setPairableTimeout(const uint &seconds) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("PairableTimeout", QVariant(seconds)); +} + +uint BluetoothAdapter::adapterClass() const +{ + return m_adapterClass; +} + +QString BluetoothAdapter::adapterClassString() const +{ + QString adapterClassString; + switch (m_adapterClass) { + // TODO: get device type from class + default: + break; + } + return adapterClassString; +} + +bool BluetoothAdapter::powered() const +{ + return m_powered; +} + +bool BluetoothAdapter::setPower(const bool &power) +{ + if (!m_adapterInterface->isValid()) + return false; + + return m_adapterInterface->setProperty("Powered", QVariant(power)); +} + +QStringList BluetoothAdapter::uuids() const +{ + return m_uuids; +} + +QList BluetoothAdapter::devices() const +{ + return m_devices; +} + +bool BluetoothAdapter::hasDevice(const QBluetoothAddress &address) +{ + foreach (BluetoothDevice *device, m_devices) { + if (device->address() == address) { + return true; + } + } + + return false; +} + +BluetoothDevice *BluetoothAdapter::getDevice(const QBluetoothAddress &address) +{ + foreach (BluetoothDevice *device, m_devices) { + if (device->address() == address) { + return device; + } + } + + return nullptr; +} + +bool BluetoothAdapter::removeDevice(const QBluetoothAddress &address) +{ + foreach (BluetoothDevice *device, m_devices) { + if (device->address() == address) { + return removeDevice(device->m_path); + } + } + + return false; +} + +bool BluetoothAdapter::isValid() const +{ + return m_adapterInterface->isValid(); +} + +BluetoothAdapter::BluetoothAdapter(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : + QObject(parent), + m_path(path), + m_discovering(false), + m_discoverable(false), + m_discoverableTimeout(0), + m_pairable(false), + m_pairableTimeout(0), + m_adapterClass(0), + m_powered(false) +{ + // Check DBus connection + if (!QDBusConnection::systemBus().isConnected()) { + qCWarning(dcBluez()) << "System DBus not connected."; + return; + } + + m_adapterInterface = new QDBusInterface(orgBluez, m_path.path(), orgBluezAdapter1, QDBusConnection::systemBus(), this); + if (!m_adapterInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus adapter interface for" << m_path.path(); + return; + } + + QDBusConnection::systemBus().connect(orgBluez, m_path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList))); + + processProperties(properties); +} + +BluetoothAdapter::~BluetoothAdapter() +{ + +} + +void BluetoothAdapter::processProperties(const QVariantMap &properties) +{ + foreach (const QString &propertyName, properties.keys()) { + if (propertyName == "Name") { + m_name = properties.value(propertyName).toString(); + } else if (propertyName == "Alias") { + setAliasInternally(properties.value(propertyName).toString()); + } else if (propertyName == "Address") { + m_address = properties.value(propertyName).toString(); + } else if (propertyName == "Modalias") { + m_modalias = properties.value(propertyName).toString(); + } else if (propertyName == "Discovering") { + setDiscoveringInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "Discoverable") { + setDiscoverableInernally(properties.value(propertyName).toBool()); + } else if (propertyName == "DiscoverableTimeout") { + setDiscoverableTimeoutInternally(properties.value(propertyName).toUInt()); + } else if (propertyName == "Pairable") { + setPairableInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "PairableTimeout") { + setPairableTimeoutInternally(properties.value(propertyName).toUInt()); + } else if (propertyName == "Class") { + m_adapterClass = properties.value(propertyName).toUInt(); + } else if (propertyName == "Powered") { + setPoweredInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "UUIDs") { + m_uuids = properties.value(propertyName).toStringList(); + } + } +} + +void BluetoothAdapter::addDeviceInternally(const QDBusObjectPath &path, const QVariantMap &properties) +{ + // Check if device already added + if (hasDevice(path)) + return; + + BluetoothDevice *device = new BluetoothDevice(path, properties, this); + m_devices.append(device); + + qCDebug(dcBluez()) << "[+]" << device; + + emit deviceAdded(device); +} + +void BluetoothAdapter::removeDeviceInternally(const QDBusObjectPath &path) +{ + foreach (BluetoothDevice *device, m_devices) { + if (device->m_path == path) { + m_devices.removeOne(device); + emit deviceRemoved(device); + device->deleteLater(); + } + } +} + +bool BluetoothAdapter::hasDevice(const QDBusObjectPath &path) +{ + foreach (BluetoothDevice *device, m_devices) { + if (device->m_path == path) + return true; + } + + return false; +} + +bool BluetoothAdapter::removeDevice(const QDBusObjectPath &path) +{ + if (!m_adapterInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus adapter interface for" << m_path.path(); + return false; + } + + qCDebug(dcBluez()) << "Remove and unpair device" << path.path(); + QDBusPendingCall removeCall = m_adapterInterface->asyncCall("RemoveDevice", QVariant::fromValue(path)); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(removeCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothAdapter::onRemoveDeviceFinished); + return true; +} + +void BluetoothAdapter::setAliasInternally(const QString &alias) +{ + if (m_alias != alias) { + m_alias = alias; + emit aliasChanged(m_alias); + } +} + +void BluetoothAdapter::setDiscoveringInternally(const bool &discovering) +{ + if (m_discovering != discovering) { + m_discovering = discovering; + emit discoveringChanged(m_discovering); + } +} + +void BluetoothAdapter::setDiscoverableInernally(const bool &discoverable) +{ + if (m_discoverable != discoverable) { + m_discoverable = discoverable; + emit discoverableChanged(m_discoverable); + } +} + +void BluetoothAdapter::setDiscoverableTimeoutInternally(const uint &discoverableTimeout) +{ + if (m_discoverableTimeout != discoverableTimeout) { + m_discoverableTimeout = discoverableTimeout; + emit discoverableTimeoutChanged(m_discoverableTimeout); + } +} + +void BluetoothAdapter::setPairableInternally(const bool &pairable) +{ + if (m_pairable != pairable) { + m_pairable = pairable; + emit pairableChanged(m_pairable); + } +} + +void BluetoothAdapter::setPairableTimeoutInternally(const uint &pairableTimeout) +{ + if (m_pairableTimeout != pairableTimeout) { + m_pairableTimeout = pairableTimeout; + emit pairableTimeoutChanged(m_pairableTimeout); + } +} + +void BluetoothAdapter::setPoweredInternally(const bool &powered) +{ + if (m_powered != powered) { + m_powered = powered; + emit poweredChanged(m_powered); + } +} + +void BluetoothAdapter::onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties) +{ + if (interface != orgBluezAdapter1) + return; + + qCDebug(dcBluez()) << "BluetoothAdapter:" << m_name << m_address << "properties changed" << interface << changedProperties << invalidatedProperties; + processProperties(changedProperties); +} + +void BluetoothAdapter::onRemoveDeviceFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not remove device" << m_address << reply.error().name() << reply.error().message(); + + call->deleteLater(); +} + +void BluetoothAdapter::startDiscovering() +{ + if (!m_adapterInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus adapter interface for" << m_path.path(); + return; + } + + if (discovering()) + return; + + QDBusMessage query = m_adapterInterface->call("StartDiscovery"); + if(query.type() != QDBusMessage::ReplyMessage) { + qCWarning(dcBluez()) << "Could not start discovery" << m_name << ":" << query.errorName() << query.errorMessage(); + return; + } +} + +void BluetoothAdapter::stopDiscovering() +{ + if (!m_adapterInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus adapter interface for" << m_path.path(); + return; + } + + QDBusMessage query = m_adapterInterface->call("StopDiscovery"); + if(query.type() != QDBusMessage::ReplyMessage) { + qCWarning(dcBluez()) << "Could not start discovery" << m_name << ":" << query.errorName() << query.errorMessage(); + return; + } +} + +QDebug operator<<(QDebug debug, BluetoothAdapter *adapter) +{ + debug.noquote().nospace() << "BluetoothAdapter(" << adapter->name() << ", " << adapter->address(); + debug.noquote().nospace() << ", powered: " << adapter->powered(); + debug.noquote().nospace() << ", pairable: " << adapter->pairable(); + debug.noquote().nospace() << ", visible: " << adapter->discoverable(); + debug.noquote().nospace() << ") "; + return debug; +} diff --git a/nuki/bluez/bluetoothadapter.h b/nuki/bluez/bluetoothadapter.h new file mode 100644 index 00000000..d5fa900e --- /dev/null +++ b/nuki/bluez/bluetoothadapter.h @@ -0,0 +1,152 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHADAPTER_H +#define BLUETOOTHADAPTER_H + +#include +#include +#include +#include +#include + +#include "bluetoothdevice.h" + +// Note: DBus documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt + +class BluetoothManager; + +class BluetoothAdapter : public QObject +{ + Q_OBJECT + + friend class BluetoothManager; + +public: + // Properties + QString name() const; + + QString alias() const; + bool setAlias(const QString &alias); + + QString address() const; + QString modalias() const; + bool discovering() const; + + bool discoverable() const; + bool setDiscoverable(const bool &discoverable); + + uint discoverableTimeout() const; + bool setDiscoverableTimeout(const uint &seconds); + + bool pairable() const; + bool setPairable(const bool &pairable); + + uint pairableTimeout() const; + bool setPairableTimeout(const uint &seconds); + + uint adapterClass() const; + QString adapterClassString() const; + + bool powered() const; + bool setPower(const bool &power); + + QStringList uuids() const; + + QList devices() const; + bool hasDevice(const QBluetoothAddress &address); + BluetoothDevice *getDevice(const QBluetoothAddress &address); + bool removeDevice(const QBluetoothAddress &address); + + bool isValid() const; + +private: + // Note: only BluetoothManager can create adapter objects + explicit BluetoothAdapter(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = 0); + ~BluetoothAdapter(); + + QDBusObjectPath m_path; + QDBusInterface *m_adapterInterface; + + QString m_name; + QString m_address; + + QString m_alias; + QString m_modalias; + bool m_discovering; + bool m_discoverable; + uint m_discoverableTimeout; + bool m_pairable; + uint m_pairableTimeout; + uint m_adapterClass; + bool m_powered; + QStringList m_uuids; + + QList m_devices; + + void processProperties(const QVariantMap &properties); + + // Methods called from BluetoothManager + void addDeviceInternally(const QDBusObjectPath &path, const QVariantMap &properties); + void removeDeviceInternally(const QDBusObjectPath &path); + + // Verification methods + bool hasDevice(const QDBusObjectPath &path); + + // DBus methods + bool removeDevice(const QDBusObjectPath &path); + + + void setAliasInternally(const QString &alias); + void setDiscoveringInternally(const bool &discovering); + void setDiscoverableInernally(const bool &discoverable); + void setDiscoverableTimeoutInternally(const uint &discoverableTimeout); + void setPairableInternally(const bool &pairable); + void setPairableTimeoutInternally(const uint &pairableTimeout); + void setPoweredInternally(const bool &powered); + +private slots: + void onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); + void onRemoveDeviceFinished(QDBusPendingCallWatcher *call); + +signals: + void aliasChanged(const QString &alias); + void discoveringChanged(const bool &discovering); + void discoverableChanged(const bool &discoverable); + void discoverableTimeoutChanged(const uint &discoverableTimeout); + void pairableChanged(const bool &pairable); + void pairableTimeoutChanged(const uint &pairableTimeout); + void poweredChanged(const bool &powered); + + void deviceAdded(BluetoothDevice *device); + void deviceRemoved(BluetoothDevice *device); + +public slots: + void startDiscovering(); + void stopDiscovering(); + +}; + +QDebug operator<<(QDebug debug, BluetoothAdapter *adapter); + + +#endif // BLUETOOTHADAPTER_H diff --git a/nuki/bluez/bluetoothdevice.cpp b/nuki/bluez/bluetoothdevice.cpp new file mode 100644 index 00000000..871d03e8 --- /dev/null +++ b/nuki/bluez/bluetoothdevice.cpp @@ -0,0 +1,546 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothdevice.h" + +#include + +BluetoothDevice::State BluetoothDevice::state() const +{ + return m_state; +} + +QString BluetoothDevice::name() const +{ + return m_name; +} + +QBluetoothAddress BluetoothDevice::address() const +{ + return m_address; +} + +QString BluetoothDevice::iconName() const +{ + return m_iconName; +} + +QBluetoothHostInfo BluetoothDevice::hostInfo() const +{ + return m_hostInfo; +} + +QString BluetoothDevice::alias() const +{ + return m_alias; +} + +bool BluetoothDevice::setAlias(const QString &alias) +{ + if (!m_deviceInterface->isValid()) + return false; + + return m_deviceInterface->setProperty("Alias", QVariant(alias)); +} + +QString BluetoothDevice::modalias() const +{ + return m_modalias; +} + +quint32 BluetoothDevice::deviceClass() const +{ + return m_deviceClass; +} + +quint16 BluetoothDevice::appearance() const +{ + return m_appearance; +} + +qint16 BluetoothDevice::rssi() const +{ + return m_rssi; +} + +qint16 BluetoothDevice::txPower() const +{ + return m_txPower; +} + +QList BluetoothDevice::uuids() const +{ + return m_uuids; +} + +bool BluetoothDevice::paired() const +{ + return m_paired; +} + +bool BluetoothDevice::connected() const +{ + return m_connected; +} + +bool BluetoothDevice::trusted() const +{ + return m_trusted; +} + +bool BluetoothDevice::setTrusted(const bool &trusted) +{ + if (!m_deviceInterface->isValid()) + return false; + + return m_deviceInterface->setProperty("Trusted", QVariant(trusted)); +} + +bool BluetoothDevice::blocked() const +{ + return m_blocked; +} + +bool BluetoothDevice::setBlocked(const bool &blocked) +{ + if (!m_deviceInterface->isValid()) + return false; + + return m_deviceInterface->setProperty("Blocked", QVariant(blocked)); +} + +bool BluetoothDevice::legacyPairing() const +{ + return m_legacyPairing; +} + +bool BluetoothDevice::servicesResolved() const +{ + return m_servicesResolved; +} + +QList BluetoothDevice::services() const +{ + return m_services; +} + +bool BluetoothDevice::hasService(const QBluetoothUuid &serviceUuid) +{ + foreach (BluetoothGattService *service, m_services) { + if (service->uuid() == serviceUuid) { + return true; + } + } + + return false; +} + +BluetoothGattService *BluetoothDevice::getService(const QBluetoothUuid &serviceUuid) +{ + foreach (BluetoothGattService *service, m_services) { + if (service->uuid() == serviceUuid) { + return service; + } + } + + return nullptr; +} + +BluetoothDevice::BluetoothDevice(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : + QObject(parent), + m_path(path), + m_state(Disconnected), + m_deviceClass(0), + m_appearance(0), + m_rssi(0), + m_txPower(0), + m_paired(false), + m_connected(false), + m_trusted(false), + m_blocked(false), + m_legacyPairing(false), + m_servicesResolved(false), + m_connectWatcher(nullptr), + m_disconnectWatcher(nullptr), + m_pairingWatcher(nullptr) +{ + // Check DBus connection + if (!QDBusConnection::systemBus().isConnected()) { + qCWarning(dcBluez()) << "System DBus not connected."; + return; + } + + m_deviceInterface = new QDBusInterface(orgBluez, m_path.path(), orgBluezDevice1, QDBusConnection::systemBus(), this); + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return; + } + + QDBusConnection::systemBus().connect(orgBluez, m_path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList))); + + processProperties(properties); + + // Set initial state + evaluateCurrentState(); +} + +BluetoothDevice::~BluetoothDevice() +{ + +} + +void BluetoothDevice::processProperties(const QVariantMap &properties) +{ + foreach (const QString &propertyName, properties.keys()) { + if (propertyName == "Name") { + m_name = properties.value(propertyName).toString(); + m_hostInfo.setName(m_name); + } else if (propertyName == "Address") { + m_address = QBluetoothAddress(properties.value(propertyName).toString()); + m_hostInfo.setAddress(m_address); + } else if (propertyName == "Icon") { + m_iconName = properties.value(propertyName).toString(); + } else if (propertyName == "Alias") { + setAliasInternally(properties.value(propertyName).toString()); + } else if (propertyName == "Modalias") { + m_modalias = properties.value(propertyName).toString(); + } else if (propertyName == "Class") { + m_deviceClass = properties.value(propertyName).toUInt(); + } else if (propertyName == "Appearance") { + m_appearance = properties.value(propertyName).toUInt(); + } else if (propertyName == "RSSI") { + setRssiInternally(properties.value(propertyName).toInt()); + } else if (propertyName == "TxPower") { + setTxPowerInternally(properties.value(propertyName).toInt()); + } else if (propertyName == "UUIDs") { + QStringList uuidStrings = properties.value(propertyName).toStringList(); + m_uuids.clear(); + foreach (const QString &uuidString, uuidStrings) { + QBluetoothUuid uuid = QBluetoothUuid(QUuid(uuidString)); + m_uuids.append(uuid); + } + } else if (propertyName == "Paired") { + setPairedInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "Connected") { + setConnectedInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "Trusted") { + setTrustedInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "Blocked") { + setBlockedInternally(properties.value(propertyName).toBool()); + } else if (propertyName == "LegacyPairing") { + m_legacyPairing = properties.value(propertyName).toBool(); + } else if (propertyName == "ServicesResolved") { + setServicesResolvedInternally(properties.value(propertyName).toBool()); + } + } + +} + +void BluetoothDevice::evaluateCurrentState() +{ + if (!connected()) { + setStateInternally(Disconnected); + } else if (connected() && servicesResolved()) { + setStateInternally(Discovered); + } +} + +void BluetoothDevice::addServiceInternally(const QDBusObjectPath &path, const QVariantMap &properties) +{ + if (hasService(path)) + return; + + BluetoothGattService *service = new BluetoothGattService(path, properties, this); + m_services.append(service); + qCDebug(dcBluez()) << "[+]" << service; +} + +bool BluetoothDevice::hasService(const QDBusObjectPath &path) +{ + foreach (BluetoothGattService *service, m_services) { + if (service->m_path == path) { + return true; + } + } + + return false; +} + +BluetoothGattService *BluetoothDevice::getService(const QDBusObjectPath &path) +{ + foreach (BluetoothGattService *service, m_services) { + if (service->m_path == path) { + return service; + } + } + + return nullptr; +} + +void BluetoothDevice::setStateInternally(const BluetoothDevice::State &state) +{ + if (m_state != state) { + m_state = state; + emit stateChanged(m_state); + } +} + +void BluetoothDevice::setAliasInternally(const QString &alias) +{ + if (m_alias != alias) { + m_alias = alias; + emit aliasChanged(m_alias); + } +} + +void BluetoothDevice::setRssiInternally(const qint16 &rssi) +{ + if (m_rssi != rssi) { + m_rssi = rssi; + emit rssiChanged(m_rssi); + } +} + +void BluetoothDevice::setTxPowerInternally(const qint16 &txPower) +{ + if (m_txPower != txPower) { + m_txPower = txPower; + emit txPowerChanged(m_txPower); + } +} + +void BluetoothDevice::setPairedInternally(const bool &paired) +{ + if (m_paired != paired) { + m_paired = paired; + emit pairedChanged(m_paired); + + // Paired, if services not resolved + if (!m_servicesResolved) { + setStateInternally(Discovering); + } else { + setStateInternally(Discovered); + } + } +} + +void BluetoothDevice::setConnectedInternally(const bool &connected) +{ + if (m_connected != connected) { + m_connected = connected; + emit connectedChanged(m_connected); + + if (m_connected) { + setStateInternally(Connected); + + if (!m_servicesResolved) + setStateInternally(Discovering); + + } else { + setStateInternally(Disconnected); + } + } +} + +void BluetoothDevice::setTrustedInternally(const bool &trusted) +{ + if (m_trusted != trusted) { + m_trusted = trusted; + emit trustedChanged(m_trusted); + } +} + +void BluetoothDevice::setBlockedInternally(const bool &blocked) +{ + if (m_blocked != blocked) { + m_blocked = blocked; + emit blockedChanged(m_blocked); + } +} + +void BluetoothDevice::setServicesResolvedInternally(const bool &servicesResolved) +{ + if (m_servicesResolved != servicesResolved) { + m_servicesResolved = servicesResolved; + emit servicesResolvedChanged(m_servicesResolved); + + if (m_servicesResolved) + setStateInternally(Discovered); + + // Note: if unresolved, the device is about to disconnect + } +} + +void BluetoothDevice::onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties) +{ + if (interface != orgBluezDevice1) + return; + + qCDebug(dcBluez()) << "BluetoothDevice:" << m_name << m_address << "properties changed" << interface << changedProperties << invalidatedProperties; + processProperties(changedProperties); +} + +void BluetoothDevice::onConnectDeviceFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) { + setStateInternally(Disconnected); + qCWarning(dcBluez()) << "Could not connect device" << m_address.toString() << reply.error().name() << reply.error().message(); + } + + call->deleteLater(); + m_connectWatcher = nullptr; +} + +void BluetoothDevice::onDisconnectDeviceFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not disconnect device" << m_address.toString() << reply.error().name() << reply.error().message(); + + evaluateCurrentState(); + + call->deleteLater(); + m_disconnectWatcher = nullptr; +} + +void BluetoothDevice::onPairingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not pair device" << m_address.toString() << reply.error().name() << reply.error().message(); + + evaluateCurrentState(); + + call->deleteLater(); + m_pairingWatcher = nullptr; +} + +void BluetoothDevice::onCancelPairingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not cancel pairing" << m_address.toString() << reply.error().name() << reply.error().message(); + + evaluateCurrentState(); + + call->deleteLater(); +} + +bool BluetoothDevice::connectDevice() +{ + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return false; + } + + if (connected() || state() == Connecting || m_connectWatcher) + return true; + + setStateInternally(Connecting); + + QDBusPendingCall connectingCall = m_deviceInterface->asyncCall("Connect"); + m_connectWatcher = new QDBusPendingCallWatcher(connectingCall, this); + connect(m_connectWatcher, &QDBusPendingCallWatcher::finished, this, &BluetoothDevice::onConnectDeviceFinished); + return true; +} + +bool BluetoothDevice::disconnectDevice() +{ + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return false; + } + + if (!connected() || state() == Disconnecting || m_disconnectWatcher) + return true; + + setStateInternally(Disconnecting); + + QDBusPendingCall disconnectingCall = m_deviceInterface->asyncCall("Disconnect"); + m_disconnectWatcher = new QDBusPendingCallWatcher(disconnectingCall, this); + connect(m_disconnectWatcher, &QDBusPendingCallWatcher::finished, this, &BluetoothDevice::onDisconnectDeviceFinished); + return true; +} + +bool BluetoothDevice::disconnectDeviceBlocking() +{ + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return false; + } + + if (!connected() || state() == Disconnecting) + return true; + + qCWarning(dcBluez()) << "Disconnecting blocking" << this; + QDBusPendingReply reply = m_deviceInterface->call("Disconnect"); + reply.waitForFinished(); + if(reply.isError()) { + qCWarning(dcBluez()) << reply.error(); + return false; + } + + return true; +} + +bool BluetoothDevice::requestPairing() +{ + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return false; + } + + if (paired() || state() == Pairing || m_pairingWatcher) + return true; + + setStateInternally(Pairing); + + QDBusPendingCall pairCall = m_deviceInterface->asyncCall("Pair"); + m_pairingWatcher = new QDBusPendingCallWatcher(pairCall, this); + connect(m_pairingWatcher, &QDBusPendingCallWatcher::finished, this, &BluetoothDevice::onPairingFinished); + return true; +} + +bool BluetoothDevice::cancelPairingRequest() +{ + if (!m_deviceInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus device interface for" << m_path.path(); + return false; + } + + if (!paired() || state() == Unpairing) + return true; + + setStateInternally(Unpairing); + + QDBusPendingCall cancelPairingCall = m_deviceInterface->asyncCall("CancelPairing"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(cancelPairingCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothDevice::onPairingFinished); + return true; +} + +QDebug operator<<(QDebug debug, BluetoothDevice *device) +{ + debug.noquote().nospace() << "BluetoothDevice(" << device->name() << ", " << device->address() << ") "; + return debug; +} diff --git a/nuki/bluez/bluetoothdevice.h b/nuki/bluez/bluetoothdevice.h new file mode 100644 index 00000000..dcb6d9ef --- /dev/null +++ b/nuki/bluez/bluetoothdevice.h @@ -0,0 +1,185 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHDEVICE_H +#define BLUETOOTHDEVICE_H + +#include +#include +#include +#include +#include +#include + +#include "blueztypes.h" +#include "bluetoothgattservice.h" + +// Note: DBus documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt + +class BluetoothManager; +class BluetoothAdapter; + +class BluetoothDevice : public QObject +{ + Q_OBJECT + + friend class BluetoothManager; + friend class BluetoothAdapter; + +public: + enum State { + Connecting, + Connected, + Pairing, + Unpairing, + Discovering, + Discovered, + Disconnecting, + Disconnected + }; + Q_ENUM(State) + + State state() const; + + QString name() const; + QBluetoothAddress address() const; + QString iconName() const; + + QBluetoothHostInfo hostInfo() const; + + QString alias() const; + bool setAlias(const QString &alias); + + QString modalias() const; + quint32 deviceClass() const; + quint16 appearance() const; + qint16 rssi() const; + qint16 txPower() const; + QList uuids() const; + bool paired() const; + bool connected() const; + + bool trusted() const; + bool setTrusted(const bool &trusted); + + bool blocked() const; + bool setBlocked(const bool &blocked); + + bool legacyPairing() const; + bool servicesResolved() const; + + // Service methods + QList services() const; + bool hasService(const QBluetoothUuid &serviceUuid); + BluetoothGattService *getService(const QBluetoothUuid &serviceUuid); + +private: + explicit BluetoothDevice(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = 0); + ~BluetoothDevice(); + + QDBusObjectPath m_path; + QDBusInterface *m_deviceInterface; + + QList m_services; + + State m_state; + + QString m_name; + QBluetoothAddress m_address; + QBluetoothHostInfo m_hostInfo; + QString m_iconName; + QString m_alias; + QString m_modalias; + quint32 m_deviceClass; + quint16 m_appearance; + qint16 m_rssi; + qint16 m_txPower; + + QList m_uuids; + bool m_paired; + bool m_connected; + bool m_trusted; + bool m_blocked; + bool m_legacyPairing; + bool m_servicesResolved; + + QDBusObjectPath m_adapterObjectPath; + + QDBusPendingCallWatcher *m_connectWatcher; + QDBusPendingCallWatcher *m_disconnectWatcher; + QDBusPendingCallWatcher *m_pairingWatcher; + + // TODO: org.bluez.Device1.ManufacturerData + // TODO: org.bluez.Device1.ServiceData + + void processProperties(const QVariantMap &properties); + + void evaluateCurrentState(); + + // Methods called from BluetoothManager + void addServiceInternally(const QDBusObjectPath &path, const QVariantMap &properties); + bool hasService(const QDBusObjectPath &path); + BluetoothGattService *getService(const QDBusObjectPath &path); + + void setStateInternally(const State &state); + + void setAliasInternally(const QString &alias); + void setRssiInternally(const qint16 &rssi); + void setTxPowerInternally(const qint16 &txPower); + void setPairedInternally(const bool &paired); + void setConnectedInternally(const bool &connected); + void setTrustedInternally(const bool &trusted); + void setBlockedInternally(const bool &blocked); + void setServicesResolvedInternally(const bool &servicesResolved); + +signals: + void stateChanged(const State &state); + + void aliasChanged(const QString &alias); + void rssiChanged(const qint16 &rssi); + void txPowerChanged(const qint16 &txPower); + void pairedChanged(const bool &paired); + void connectedChanged(const bool &connected); + void trustedChanged(const bool &trusted); + void blockedChanged(const bool &blocked); + void servicesResolvedChanged(const bool &servicesResolved); + +private slots: + void onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); + + void onConnectDeviceFinished(QDBusPendingCallWatcher *call); + void onDisconnectDeviceFinished(QDBusPendingCallWatcher *call); + void onPairingFinished(QDBusPendingCallWatcher *call); + void onCancelPairingFinished(QDBusPendingCallWatcher *call); + +public slots: + bool connectDevice(); + bool disconnectDevice(); + bool disconnectDeviceBlocking(); + bool requestPairing(); + bool cancelPairingRequest(); +}; + +QDebug operator<<(QDebug debug, BluetoothDevice *device); + + +#endif // BLUETOOTHDEVICE_H diff --git a/nuki/bluez/bluetoothgattcharacteristic.cpp b/nuki/bluez/bluetoothgattcharacteristic.cpp new file mode 100644 index 00000000..20a48d69 --- /dev/null +++ b/nuki/bluez/bluetoothgattcharacteristic.cpp @@ -0,0 +1,368 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothgattcharacteristic.h" + +#include + +QString BluetoothGattCharacteristic::chararcteristicName() const +{ + bool ok = false; + quint16 typeId = m_uuid.toUInt16(&ok); + + if (ok) { + QBluetoothUuid::CharacteristicType uuid = static_cast(typeId); + const QString name = QBluetoothUuid::characteristicToString(uuid); + if (!name.isEmpty()) + return name; + } + + return QString("Unknown Characteristic"); +} + +QBluetoothUuid BluetoothGattCharacteristic::uuid() const +{ + return m_uuid; +} + +bool BluetoothGattCharacteristic::notifying() const +{ + return m_notifying; +} + +BluetoothGattCharacteristic::Properties BluetoothGattCharacteristic::properties() const +{ + return m_properties; +} + +QByteArray BluetoothGattCharacteristic::value() const +{ + return m_value; +} + +QList BluetoothGattCharacteristic::descriptors() const +{ + return m_descriptors; +} + +BluetoothGattCharacteristic::BluetoothGattCharacteristic(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : + QObject(parent), + m_path(path), + m_notifying(false) +{ + m_characteristicInterface = new QDBusInterface(orgBluez, m_path.path(), orgBluezGattCharacteristic1, QDBusConnection::systemBus(), this); + if (!m_characteristicInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return; + } + + QDBusConnection::systemBus().connect(orgBluez, m_path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList))); + + processProperties(properties); +} + +void BluetoothGattCharacteristic::processProperties(const QVariantMap &properties) +{ + foreach (const QString &propertyName, properties.keys()) { + if (propertyName == "UUID") { + m_uuid = QBluetoothUuid(properties.value(propertyName).toString()); + } else if (propertyName == "Notifying") { + m_notifying = properties.value(propertyName).toBool(); + emit notifyingChanged(m_notifying); + } else if (propertyName == "Flags") { + m_properties = parsePropertyFlags(properties.value(propertyName).toStringList()); + } else if (propertyName == "Value") { + m_value = properties.value(propertyName).toByteArray(); + emit valueChanged(m_value); + } + } +} + +void BluetoothGattCharacteristic::addDescriptorInternally(const QDBusObjectPath &path, const QVariantMap &properties) +{ + if (hasDescriptor(path)) + return; + + BluetoothGattDescriptor *descriptor = new BluetoothGattDescriptor(path, properties, this); + m_descriptors.append(descriptor); + + qCDebug(dcBluez()) << "[+]" << descriptor; +} + +bool BluetoothGattCharacteristic::hasDescriptor(const QDBusObjectPath &path) +{ + foreach (BluetoothGattDescriptor *descriptor, m_descriptors) { + if (descriptor->m_path == path) { + return true; + } + } + + return false; +} + +BluetoothGattDescriptor *BluetoothGattCharacteristic::getDescriptor(const QDBusObjectPath &path) +{ + foreach (BluetoothGattDescriptor *descriptor, m_descriptors) { + if (descriptor->m_path == path) { + return descriptor; + } + } + + return nullptr; +} + +void BluetoothGattCharacteristic::setValueInternally(const QByteArray &value) +{ + if (m_value != value) { + m_value = value; + emit valueChanged(m_value); + } +} + +void BluetoothGattCharacteristic::setNotifyingInternally(const bool ¬ifying) +{ + if (m_notifying != notifying) { + m_notifying = notifying; + emit notifyingChanged(m_notifying); + } +} + +BluetoothGattCharacteristic::Properties BluetoothGattCharacteristic::parsePropertyFlags(const QStringList &characteristicProperties) +{ + Properties properties; + + foreach (const QString &propertyString, characteristicProperties) { + if (propertyString == "broadcast") { + properties |= Broadcasting; + } else if (propertyString == "read") { + properties |= Read; + } else if (propertyString == "write-without-response") { + properties |= WriteNoResponse; + } else if (propertyString == "write") { + properties |= Write; + } else if (propertyString == "notify") { + properties |= Notify; + } else if (propertyString == "indicate") { + properties |= Indicate; + } else if (propertyString == "authenticated-signed-writes") { + properties |= WriteAuthenticatedSigned; + } else if (propertyString == "reliable-write") { + properties |= ReliableWrite; + } else if (propertyString == "writable-auxiliaries") { + properties |= WritableAuxiliaries; + } else if (propertyString == "encrypt-read") { + properties |= EncryptRead; + } else if (propertyString == "encrypt-write") { + properties |= EncryptWrite; + } else if (propertyString == "encrypt-authenticated-read") { + properties |= EncryptAuthenticatedRead; + } else if (propertyString == "encrypt-authenticated-write") { + properties |= EncryptAuthenticatedWrite; + } else if (propertyString == "secure-read") { + properties |= SecureRead; + } else if (propertyString == "secure-write") { + properties |= Unknown; + } + } + + return properties; +} + +void BluetoothGattCharacteristic::onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties) +{ + if (interface != orgBluezGattCharacteristic1) + return; + + qCDebug(dcBluez()) << "BluetoothCharacteristic:" << m_uuid.toString() << "properties changed" << interface << changedProperties << invalidatedProperties; + processProperties(changedProperties); +} + +void BluetoothGattCharacteristic::onReadingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(dcBluez()) << "Could not read characteristic" << m_uuid.toString() << reply.error().name() << reply.error().message(); + } else { + QByteArray value = reply.argumentAt<0>(); + qCDebug(dcBluez()) << "Async reading finished for" << m_uuid.toString() << value; + setValueInternally(value); + emit readingFinished(value); + } + + call->deleteLater(); +} + +void BluetoothGattCharacteristic::onWritingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(dcBluez()) << "Could not write characteristic" << m_uuid.toString() << reply.error().name() << reply.error().message(); + } else { + QByteArray value = m_asyncWrites.take(call); + qCDebug(dcBluez()) << "Async characteristic writing finished for" << m_uuid.toString() << value; + emit writingFinished(value); + } + + call->deleteLater(); +} + +void BluetoothGattCharacteristic::onStartNotificationFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not start notifications on characteristic" << m_uuid.toString() << reply.error().name() << reply.error().message(); + + call->deleteLater(); +} + +void BluetoothGattCharacteristic::onStopNotificationFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) + qCWarning(dcBluez()) << "Could not stop notifications on characteristic" << m_uuid.toString() << reply.error().name() << reply.error().message(); + + call->deleteLater(); +} + +bool BluetoothGattCharacteristic::readCharacteristic() +{ + if (!m_characteristicInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + QDBusPendingCall readingCall = m_characteristicInterface->asyncCall("ReadValue", QVariantMap()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(readingCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattCharacteristic::onReadingFinished); + return true; +} + +bool BluetoothGattCharacteristic::writeCharacteristic(const QByteArray &value) +{ + if (!m_characteristicInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + QDBusPendingCall writingCall = m_characteristicInterface->asyncCall("WriteValue", value, QVariantMap()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(writingCall, this); + m_asyncWrites.insert(watcher, value); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattCharacteristic::onWritingFinished); + return true; +} + +bool BluetoothGattCharacteristic::startNotifications() +{ + if (!m_characteristicInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + // If already notifying + if (notifying()) + return true; + + QDBusPendingCall startNotifyCall = m_characteristicInterface->asyncCall("StartNotify"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(startNotifyCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattCharacteristic::onStartNotificationFinished); + return true; +} + +bool BluetoothGattCharacteristic::stopNotifications() +{ + if (!m_characteristicInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + // If already stopped + if (!notifying()) + return true; + + QDBusPendingCall stopNotifyCall = m_characteristicInterface->asyncCall("StopNotify"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(stopNotifyCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattCharacteristic::onStopNotificationFinished); + return true; +} + +QDebug operator<<(QDebug debug, BluetoothGattCharacteristic *characteristic) +{ + debug.noquote().nospace() << "GattCharacteristic(" << characteristic->chararcteristicName(); + debug.noquote().nospace() << ", " << characteristic->uuid().toString(); + debug.noquote().nospace() << ", Properties: " << characteristic->properties(); + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Unknown)) + debug.noquote().nospace() << " Unknown"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Broadcasting)) + debug.noquote().nospace() << " B"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Read)) + debug.noquote().nospace() << " R "; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::WriteNoResponse)) + debug.noquote().nospace() << " WNR"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Write)) + debug.noquote().nospace() << " W"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Notify)) + debug.noquote().nospace() << " N"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Indicate)) + debug.noquote().nospace() << " I"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::WriteAuthenticatedSigned)) + debug.noquote().nospace() << " WAS"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::ReliableWrite)) + debug.noquote().nospace() << " RW"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::WritableAuxiliaries)) + debug.noquote().nospace() << " WA"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::EncryptWrite)) + debug.noquote().nospace() << " EW"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::EncryptRead)) + debug.noquote().nospace() << " ER"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::EncryptAuthenticatedRead)) + debug.noquote().nospace() << " EAR"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::EncryptAuthenticatedWrite)) + debug.noquote().nospace() << " EAW"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::SecureRead)) + debug.noquote().nospace() << " SR"; + + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::SecureWrite)) + debug.noquote().nospace() << " SW"; + + // If this is a notifying characteristic, inform if notifications are enabled + if (characteristic->properties().testFlag(BluetoothGattCharacteristic::Notify)) + debug.noquote().nospace() << ", Notify: " << (characteristic->notifying() ? "ON" : "OFF"); + + debug.noquote().nospace() << ", value:" << characteristic->value(); + debug.noquote().nospace() << ") "; + return debug; +} diff --git a/nuki/bluez/bluetoothgattcharacteristic.h b/nuki/bluez/bluetoothgattcharacteristic.h new file mode 100644 index 00000000..91de433e --- /dev/null +++ b/nuki/bluez/bluetoothgattcharacteristic.h @@ -0,0 +1,132 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHGATTCHARACTERISTIC_H +#define BLUETOOTHGATTCHARACTERISTIC_H + +#include +#include +#include +#include +#include +#include +#include + +#include "blueztypes.h" +#include "bluetoothgattdescriptor.h" + +// Note: DBus documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt + +class BluetoothManager; +class BluetoothGattService; + +class BluetoothGattCharacteristic : public QObject +{ + Q_OBJECT + Q_FLAGS(Properties) + + friend class BluetoothManager; + friend class BluetoothGattService; + +public: + enum Property { + Unknown = 0x00, + Broadcasting = 0x01, + Read = 0x02, + WriteNoResponse = 0x04, + Write = 0x08, + Notify = 0x10, + Indicate = 0x20, + WriteAuthenticatedSigned = 0x40, + ReliableWrite = 0x80, + WritableAuxiliaries = 0x100, + EncryptRead = 0x200, + EncryptWrite = 0x400, + EncryptAuthenticatedRead = 0x800, + EncryptAuthenticatedWrite = 0x1000, + SecureRead = 0x2000, // Server only + SecureWrite = 0x4000, // Server only + }; + Q_DECLARE_FLAGS(Properties, Property) + + QString chararcteristicName() const; + QBluetoothUuid uuid() const; + bool notifying() const; + Properties properties() const; + QByteArray value() const; + QList descriptors() const; + + +private: + explicit BluetoothGattCharacteristic(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = 0); + + QDBusObjectPath m_path; + QDBusInterface *m_characteristicInterface; + + QString m_characteristicName; + QBluetoothUuid m_uuid; + bool m_notifying; + Properties m_properties; + QByteArray m_value; + QList m_descriptors; + + QHash m_asyncWrites; + + void processProperties(const QVariantMap &properties); + + // Methods called from BluetoothManager + void addDescriptorInternally(const QDBusObjectPath &path, const QVariantMap &properties); + bool hasDescriptor(const QDBusObjectPath &path); + BluetoothGattDescriptor *getDescriptor(const QDBusObjectPath &path); + + void setValueInternally(const QByteArray &value); + void setNotifyingInternally(const bool ¬ifying); + + Properties parsePropertyFlags(const QStringList &characteristicProperties); + +signals: + void notifyingChanged(const bool ¬ifying); + void valueChanged(const QByteArray &value); + void readingFinished(const QByteArray &value); + void writingFinished(const QByteArray &value); + +private slots: + void onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); + + void onReadingFinished(QDBusPendingCallWatcher *call); + void onWritingFinished(QDBusPendingCallWatcher *call); + void onStartNotificationFinished(QDBusPendingCallWatcher *call); + void onStopNotificationFinished(QDBusPendingCallWatcher *call); + +public slots: + bool readCharacteristic(); + bool writeCharacteristic(const QByteArray &value); + bool startNotifications(); + bool stopNotifications(); + +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(BluetoothGattCharacteristic::Properties) + +QDebug operator<<(QDebug debug, BluetoothGattCharacteristic *characteristic); + +#endif // BLUETOOTHGATTCHARACTERISTIC_H diff --git a/nuki/bluez/bluetoothgattdescriptor.cpp b/nuki/bluez/bluetoothgattdescriptor.cpp new file mode 100644 index 00000000..07688140 --- /dev/null +++ b/nuki/bluez/bluetoothgattdescriptor.cpp @@ -0,0 +1,219 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothgattdescriptor.h" + +#include + +QString BluetoothGattDescriptor::name() const +{ + bool ok = false; + quint16 typeId = m_uuid.toUInt16(&ok); + + if (ok) { + QBluetoothUuid::DescriptorType type = static_cast(typeId); + const QString name = QBluetoothUuid::descriptorToString(type); + if (!name.isEmpty()) + return name; + } + + return QString("Unknown Descriptor"); +} + +QBluetoothUuid BluetoothGattDescriptor::uuid() const +{ + return m_uuid; +} + +QByteArray BluetoothGattDescriptor::value() const +{ + return m_value; +} + +BluetoothGattDescriptor::Properties BluetoothGattDescriptor::properties() const +{ + return m_properties; +} + +BluetoothGattDescriptor::BluetoothGattDescriptor(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : + QObject(parent), + m_path(path) +{ + m_descriptorInterface = new QDBusInterface(orgBluez, m_path.path(), orgBluezGattDescriptor1, QDBusConnection::systemBus(), this); + if (!m_descriptorInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus descriptor interface for" << m_path.path(); + return; + } + + QDBusConnection::systemBus().connect(orgBluez, m_path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList))); + + processProperties(properties); +} + +void BluetoothGattDescriptor::processProperties(const QVariantMap &properties) +{ + foreach (const QString &propertyName, properties.keys()) { + if (propertyName == "UUID") { + m_uuid = QBluetoothUuid(properties.value(propertyName).toString()); + } else if (propertyName == "Value") { + setValueInternally(properties.value(propertyName).toByteArray()); + } else if (propertyName == "Flags") { + m_properties = parsePropertyFlags(properties.value(propertyName).toStringList()); + } + } +} + +void BluetoothGattDescriptor::setValueInternally(const QByteArray &value) +{ + if (m_value != value) { + m_value = value; + emit valueChanged(m_value); + } +} + +BluetoothGattDescriptor::Properties BluetoothGattDescriptor::parsePropertyFlags(const QStringList &descriptorProperties) +{ + Properties properties; + + foreach (const QString &propertyString, descriptorProperties) { + if (propertyString == "read") { + properties |= Read; + } else if (propertyString == "write") { + properties |= Write; + } else if (propertyString == "encrypt-read") { + properties |= EncryptRead; + } else if (propertyString == "encrypt-write") { + properties |= EncryptWrite; + } else if (propertyString == "encrypt-authenticated-read") { + properties |= EncryptAuthenticatedRead; + } else if (propertyString == "encrypt-authenticated-write") { + properties |= EncryptAuthenticatedWrite; + } else if (propertyString == "secure-read") { + properties |= SecureRead; + } else if (propertyString == "secure-write") { + properties |= SecureWrite; + } + } + + return properties; +} + +void BluetoothGattDescriptor::onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties) +{ + if (interface != orgBluezGattDescriptor1) + return; + + qCDebug(dcBluez()) << "BluetoothDescriptor:" << m_uuid << "properties changed" << interface << changedProperties << invalidatedProperties; + processProperties(changedProperties); +} + +void BluetoothGattDescriptor::onReadingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(dcBluez()) << "Could not read descriptor" << m_uuid.toString() << reply.error().name() << reply.error().message(); + } else { + QByteArray value = reply.argumentAt<0>(); + qCDebug(dcBluez()) << "Async descriptor reading finished for" << m_uuid.toString() << value; + setValueInternally(value); + emit readingFinished(value); + } + + call->deleteLater(); +} + +void BluetoothGattDescriptor::onWritingFinished(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(dcBluez()) << "Could not write descriptor" << m_uuid.toString() << reply.error().name() << reply.error().message(); + } else { + QByteArray value = m_asyncWrites.take(call); + qCDebug(dcBluez()) << "Async descriptor writing finished for" << m_uuid.toString() << value; + emit writingFinished(value); + } + + call->deleteLater(); +} + +bool BluetoothGattDescriptor::readValue() +{ + if (!m_descriptorInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + QDBusPendingCall readingCall = m_descriptorInterface->asyncCall("ReadValue", QVariantMap()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(readingCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattDescriptor::onReadingFinished); + return true; +} + +bool BluetoothGattDescriptor::writeValue(const QByteArray &value) +{ + if (!m_descriptorInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus characteristic interface for" << m_path.path(); + return false; + } + + QDBusPendingCall writingCall = m_descriptorInterface->asyncCall("WriteValue", value, QVariantMap()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(writingCall, this); + m_asyncWrites.insert(watcher, value); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &BluetoothGattDescriptor::onWritingFinished); + return true; +} + +QDebug operator<<(QDebug debug, BluetoothGattDescriptor *descriptor) +{ + debug.noquote().nospace() << "GattDescriptor(" << descriptor->name(); + debug.noquote().nospace() << ", " << descriptor->uuid().toString(); + debug.noquote().nospace() << ", Properties: "; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::Read)) + debug.noquote().nospace() << " R "; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::Write)) + debug.noquote().nospace() << " W"; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::EncryptRead)) + debug.noquote().nospace() << " ER"; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::EncryptWrite)) + debug.noquote().nospace() << " EW"; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::EncryptAuthenticatedRead)) + debug.noquote().nospace() << " EAR"; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::EncryptAuthenticatedWrite)) + debug.noquote().nospace() << " EAW"; + + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::SecureRead)) + debug.noquote().nospace() << " SR"; + + if (descriptor->properties().testFlag(BluetoothGattDescriptor::SecureWrite)) + debug.noquote().nospace() << " SW"; + + debug.noquote().nospace() << ", value: " << descriptor->value(); + debug.noquote().nospace() << ") "; + return debug; +} diff --git a/nuki/bluez/bluetoothgattdescriptor.h b/nuki/bluez/bluetoothgattdescriptor.h new file mode 100644 index 00000000..f51a142d --- /dev/null +++ b/nuki/bluez/bluetoothgattdescriptor.h @@ -0,0 +1,104 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHGATTDESCRIPTOR_H +#define BLUETOOTHGATTDESCRIPTOR_H + +#include +#include +#include +#include +#include + +#include "blueztypes.h" + +// Note: DBus documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt + +class BluetoothManager; +class BluetoothGattCharacteristic; + +class BluetoothGattDescriptor : public QObject +{ + Q_OBJECT + Q_FLAGS(Properties) + + friend class BluetoothManager; + friend class BluetoothGattCharacteristic; + +public: + enum Property { + Unknown = 0x00, + Read = 0x01, + Write = 0x02, + EncryptRead = 0x04, + EncryptWrite = 0x08, + EncryptAuthenticatedRead = 0x10, + EncryptAuthenticatedWrite = 0x20, + SecureRead = 0x40, // Server only + SecureWrite = 0x80 // Server only + }; + Q_DECLARE_FLAGS(Properties, Property) + + QString name() const; + QBluetoothUuid uuid() const; + QByteArray value() const; + Properties properties() const; + +private: + explicit BluetoothGattDescriptor(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = 0); + + QDBusObjectPath m_path; + QDBusInterface *m_descriptorInterface; + + QBluetoothUuid m_uuid; + QByteArray m_value; + Properties m_properties; + QHash m_asyncWrites; + + void processProperties(const QVariantMap &properties); + + void setValueInternally(const QByteArray &value); + + Properties parsePropertyFlags(const QStringList &descriptorProperties); + +signals: + void valueChanged(const QByteArray &value); + void readingFinished(const QByteArray &value); + void writingFinished(const QByteArray &value); + +private slots: + void onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); + + void onReadingFinished(QDBusPendingCallWatcher *call); + void onWritingFinished(QDBusPendingCallWatcher *call); + +public slots: + bool readValue(); + bool writeValue(const QByteArray &value); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(BluetoothGattDescriptor::Properties) + +QDebug operator<<(QDebug debug, BluetoothGattDescriptor *descriptor); + + +#endif // BLUETOOTHGATTDESCRIPTOR_H diff --git a/nuki/bluez/bluetoothgattservice.cpp b/nuki/bluez/bluetoothgattservice.cpp new file mode 100644 index 00000000..5f46b9f4 --- /dev/null +++ b/nuki/bluez/bluetoothgattservice.cpp @@ -0,0 +1,168 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothgattservice.h" + +QString BluetoothGattService::serviceName() const +{ + bool ok = false; + quint16 typeId = m_uuid.toUInt16(&ok); + + if (ok) { + QBluetoothUuid::ServiceClassUuid uuid = static_cast(typeId); + const QString name = QBluetoothUuid::serviceClassToString(uuid); + if (!name.isEmpty()) + return name; + } + + return QString("Unknown Service"); +} + +BluetoothGattService::Type BluetoothGattService::type() const +{ + return m_type; +} + +QBluetoothUuid BluetoothGattService::uuid() const +{ + return m_uuid; +} + +QList BluetoothGattService::characteristics() const +{ + return m_characteristics; +} + +bool BluetoothGattService::hasCharacteristic(const QBluetoothUuid &characteristicUuid) +{ + foreach (BluetoothGattCharacteristic *characteristic, m_characteristics) { + if (characteristic->uuid() == characteristicUuid) { + return true; + } + } + + return false; +} + +BluetoothGattCharacteristic *BluetoothGattService::getCharacteristic(const QBluetoothUuid &characteristicUuid) +{ + foreach (BluetoothGattCharacteristic *characteristic, m_characteristics) { + if (characteristic->uuid() == characteristicUuid) { + return characteristic; + } + } + + return nullptr; +} + +BluetoothGattService::BluetoothGattService(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : + QObject(parent), + m_path(path), + m_type(Primary), + m_discovered(false) +{ + processProperties(properties); +} + +void BluetoothGattService::processProperties(const QVariantMap &properties) +{ + foreach (const QString &propertyName, properties.keys()) { + if (propertyName == "Primary") { + m_type = (properties.value(propertyName).toBool() ? Primary : Secondary); + } else if (propertyName == "UUID") { + m_uuid = QBluetoothUuid(properties.value(propertyName).toString()); + } + } +} + +void BluetoothGattService::addCharacteristicInternally(const QDBusObjectPath &path, const QVariantMap &properties) +{ + if (hasCharacteristic(path)) + return; + + BluetoothGattCharacteristic *characteristic = new BluetoothGattCharacteristic(path, properties, this); + m_characteristics.append(characteristic); + + connect(characteristic, &BluetoothGattCharacteristic::readingFinished, this, &BluetoothGattService::onCharacteristicReadFinished); + connect(characteristic, &BluetoothGattCharacteristic::writingFinished, this, &BluetoothGattService::onCharacteristicReadFinished); + connect(characteristic, &BluetoothGattCharacteristic::valueChanged, this, &BluetoothGattService::onCharacteristicValueChanged); + + qCDebug(dcBluez()) << "[+]" << characteristic; +} + +bool BluetoothGattService::hasCharacteristic(const QDBusObjectPath &path) +{ + foreach (BluetoothGattCharacteristic *characteristic, m_characteristics) { + if (characteristic->m_path == path) { + return true; + } + } + + return false; +} + +BluetoothGattCharacteristic *BluetoothGattService::getCharacteristic(const QDBusObjectPath &path) +{ + foreach (BluetoothGattCharacteristic *characteristic, m_characteristics) { + if (characteristic->m_path == path) { + return characteristic; + } + } + + return nullptr; +} + +void BluetoothGattService::onCharacteristicReadFinished(const QByteArray &value) +{ + BluetoothGattCharacteristic *characteristic = static_cast(sender()); + emit characteristicReadFinished(characteristic, value); +} + +void BluetoothGattService::onCharacteristicWriteFinished(const QByteArray &value) +{ + BluetoothGattCharacteristic *characteristic = static_cast(sender()); + emit characteristicWriteFinished(characteristic, value); +} + +void BluetoothGattService::onCharacteristicValueChanged(const QByteArray &newValue) +{ + BluetoothGattCharacteristic *characteristic = static_cast(sender()); + emit characteristicChanged(characteristic, newValue); +} + +bool BluetoothGattService::readCharacteristic(const QBluetoothUuid &characteristicUuid) +{ + if (!hasCharacteristic(characteristicUuid)) + return false; + + return getCharacteristic(characteristicUuid)->readCharacteristic(); +} + +QDebug operator<<(QDebug debug, BluetoothGattService *service) +{ + debug.noquote().nospace() << "GattService(" << (service->type() == BluetoothGattService::Primary ? "Primary" : "Secondary"); + debug.noquote().nospace() << ", " << service->serviceName(); + debug.noquote().nospace() << ", " << service->uuid().toString(); + debug.noquote().nospace() << ") "; + + return debug; +} diff --git a/nuki/bluez/bluetoothgattservice.h b/nuki/bluez/bluetoothgattservice.h new file mode 100644 index 00000000..eefcfa05 --- /dev/null +++ b/nuki/bluez/bluetoothgattservice.h @@ -0,0 +1,96 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHGATTSERVICE_H +#define BLUETOOTHGATTSERVICE_H + +#include +#include + +#include "blueztypes.h" +#include "bluetoothgattcharacteristic.h" + +// Note: DBus documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt + +class BluetoothManager; +class BluetoothDevice; + +class BluetoothGattService : public QObject +{ + Q_OBJECT + + friend class BluetoothManager; + friend class BluetoothDevice; + +public: + enum Type { + Primary, + Secondary + }; + Q_ENUM(Type) + + QString serviceName() const; + Type type() const; + QBluetoothUuid uuid() const; + + // Characteristic methods + QList characteristics() const; + bool hasCharacteristic(const QBluetoothUuid &characteristicUuid); + BluetoothGattCharacteristic *getCharacteristic(const QBluetoothUuid &characteristicUuid); + +private: + explicit BluetoothGattService(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = 0); + + QDBusObjectPath m_path; + + Type m_type; + QBluetoothUuid m_uuid; + QList m_characteristics; + + bool m_discovered; + + void processProperties(const QVariantMap &properties); + + // Methods called from BluetoothManager + void addCharacteristicInternally(const QDBusObjectPath &path, const QVariantMap &properties); + bool hasCharacteristic(const QDBusObjectPath &path); + BluetoothGattCharacteristic *getCharacteristic(const QDBusObjectPath &path); + +private slots: + void onCharacteristicReadFinished(const QByteArray &value); + void onCharacteristicWriteFinished(const QByteArray &value); + void onCharacteristicValueChanged(const QByteArray &newValue); + +signals: + void characteristicReadFinished(BluetoothGattCharacteristic *characteristic, const QByteArray &value); + void characteristicWriteFinished(BluetoothGattCharacteristic *characteristic, const QByteArray &value); + void characteristicChanged(BluetoothGattCharacteristic *characteristic, const QByteArray &newValue); + +public slots: + bool readCharacteristic(const QBluetoothUuid &characteristicUuid); + +}; + +QDebug operator<<(QDebug debug, BluetoothGattService *service); + + +#endif // BLUETOOTHGATTSERVICE_H diff --git a/nuki/bluez/bluetoothmanager.cpp b/nuki/bluez/bluetoothmanager.cpp new file mode 100644 index 00000000..c0e72399 --- /dev/null +++ b/nuki/bluez/bluetoothmanager.cpp @@ -0,0 +1,306 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothmanager.h" + +#include +#include +#include + +BluetoothManager::BluetoothManager(QObject *parent) : + QObject(parent), + m_available(false) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + // Check DBus connection + if (!QDBusConnection::systemBus().isConnected()) { + qCWarning(dcBluez()) << "System DBus not connected."; + return; + } + + // Get notification when bluez appears/disappears on DBus + m_serviceWatcher = new QDBusServiceWatcher(orgBluez, QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &BluetoothManager::serviceRegistered); + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &BluetoothManager::serviceUnregistered); + + m_objectManagerInterface = new QDBusInterface(orgBluez, "/", orgFreedesktopDBusObjectManager, QDBusConnection::systemBus(), this); + if (!m_objectManagerInterface->isValid()) { + qCWarning(dcBluez()) << "Invalid DBus ObjectManager interface."; + return; + } + + QDBusConnection::systemBus().connect(orgBluez, "/", orgFreedesktopDBusObjectManager, "InterfacesAdded", this, SLOT(onInterfaceAdded(QDBusObjectPath,InterfaceList))); + QDBusConnection::systemBus().connect(orgBluez, "/", orgFreedesktopDBusObjectManager, "InterfacesRemoved", this, SLOT(onInterfaceRemoved(QDBusObjectPath,QStringList))); + + init(); +} + +QList BluetoothManager::adapters() const +{ + return m_adapters; +} + +bool BluetoothManager::isAvailable() const +{ + return m_available; +} + +void BluetoothManager::init() +{ + // Get current object from org.bluez + QDBusMessage query = m_objectManagerInterface->call("GetManagedObjects"); + if(query.type() != QDBusMessage::ReplyMessage) { + qCWarning(dcBluez()) << "Could not initialize BluetoothManager:" << query.errorName() << query.errorMessage(); + return; + } + + const QDBusArgument &argument = query.arguments().at(0).value(); + ManagedObjectList objectList = qdbus_cast(argument); + processObjectList(objectList); + + if (!m_adapters.isEmpty()) + setAvailable(true); + + qCDebug(dcBluez()) << "BluetoothManager initialized successfully."; +} + +void BluetoothManager::clean() +{ + // Delete all adapter objects + // Note: devices, services and characteristic objects will be removed throug parent relation + foreach (BluetoothAdapter *adapter, m_adapters) { + m_adapters.removeOne(adapter); + emit adapterRemoved(adapter); + adapter->deleteLater(); + } + + m_adapters.clear(); + + setAvailable(false); +} + +void BluetoothManager::setAvailable(const bool &available) +{ + if (m_available != available) { + m_available = available; + emit availableChanged(m_available); + } +} + +void BluetoothManager::processObjectList(const ManagedObjectList &objectList) +{ + foreach (const QDBusObjectPath &objectPath, objectList.keys()) { + InterfaceList interfaceList = objectList.value(objectPath); + processInterfaceList(objectPath, interfaceList); + } +} + +void BluetoothManager::processInterfaceList(const QDBusObjectPath &objectPath, const InterfaceList &interfaceList) +{ + // Note: object hierarchy: first add adapters, than devices, services, characteristics and finally descriptors + + // Adapter interface + foreach (const QString &interface, interfaceList.keys()) { + if (interface == orgBluezAdapter1) { + QVariantMap properties = interfaceList.value(interface); + // Check if this adapter already added + if (!adapterAlreadyAdded(objectPath)) { + BluetoothAdapter *adapter = new BluetoothAdapter(objectPath, properties, this); + m_adapters.append(adapter); + emit adapterAdded(adapter); + qCDebug(dcBluez()) << "[+]" << adapter; + } + } + } + + // Device interface + foreach (const QString &interface, interfaceList.keys()) { + if (interface == orgBluezDevice1) { + QVariantMap properties = interfaceList.value(interface); + // Find adapter for this device and add the device internally + if (properties.contains("Adapter")) { + QDBusObjectPath adapterObjectPath = qvariant_cast(properties.value("Adapter")); + BluetoothAdapter *adapter = findAdapter(adapterObjectPath); + if (adapter) + adapter->addDeviceInternally(objectPath, properties); + + } + } + } + + // GATT Service interface + foreach (const QString &interface, interfaceList.keys()) { + if (interface == orgBluezGattService1) { + QVariantMap properties = interfaceList.value(interface); + // Find device for this service and add the service internally + if (properties.contains("Device")) { + QDBusObjectPath deviceObjectPath = qvariant_cast(properties.value("Device")); + BluetoothDevice *device = findDevice(deviceObjectPath); + if (device) + device->addServiceInternally(objectPath, properties); + + } + } + } + + // GATT Characteristic interface + foreach (const QString &interface, interfaceList.keys()) { + if (interface == orgBluezGattCharacteristic1) { + QVariantMap properties = interfaceList.value(interface); + // Find service for this characteristic + if (properties.contains("Service")) { + QDBusObjectPath serviceObjectPath = qvariant_cast(properties.value("Service")); + BluetoothGattService *service = findService(serviceObjectPath); + if (service) + service->addCharacteristicInternally(objectPath, properties); + + } + } + } + + // GATT Descriptor interface + foreach (const QString &interface, interfaceList.keys()) { + if (interface == orgBluezGattDescriptor1) { + QVariantMap properties = interfaceList.value(interface); + // Find characteristic for this desciptor + if (properties.contains("Characteristic")) { + QDBusObjectPath characterisitcObjectPath = qvariant_cast(properties.value("Characteristic")); + BluetoothGattCharacteristic *characteristic = findCharacteristic(characterisitcObjectPath); + if (characteristic) + characteristic->addDescriptorInternally(objectPath, properties); + + } + } + } + +} + +bool BluetoothManager::adapterAlreadyAdded(const QDBusObjectPath &objectPath) +{ + foreach (BluetoothAdapter *existingAdapter, m_adapters) { + if (existingAdapter->m_path == objectPath) { + return true; + } + } + + return false; +} + +BluetoothAdapter *BluetoothManager::findAdapter(const QDBusObjectPath &objectPath) +{ + foreach (BluetoothAdapter *adapter, m_adapters) { + if (adapter->m_path == objectPath) { + return adapter; + } + } + + return nullptr; +} + +BluetoothDevice *BluetoothManager::findDevice(const QDBusObjectPath &objectPath) +{ + foreach (BluetoothAdapter *adapter, m_adapters) { + foreach (BluetoothDevice *device, adapter->devices()) { + if (device->m_path == objectPath) { + return device; + } + } + } + + return nullptr; +} + +BluetoothGattService *BluetoothManager::findService(const QDBusObjectPath &objectPath) +{ + foreach (BluetoothAdapter *adapter, m_adapters) { + foreach (BluetoothDevice *device, adapter->devices()) { + if (device->hasService(objectPath)) { + return device->getService(objectPath); + } + } + } + + return nullptr; +} + +BluetoothGattCharacteristic *BluetoothManager::findCharacteristic(const QDBusObjectPath &objectPath) +{ + foreach (BluetoothAdapter *adapter, m_adapters) { + foreach (BluetoothDevice *device, adapter->devices()) { + foreach (BluetoothGattService *service, device->services()) { + if (service->hasCharacteristic(objectPath)) { + return service->getCharacteristic(objectPath); + } + } + } + } + + return nullptr; +} + +void BluetoothManager::serviceRegistered(const QString &serviceName) +{ + qCDebug(dcBluez()) << "BluetoothManager: service registered" << serviceName; + init(); +} + +void BluetoothManager::serviceUnregistered(const QString &serviceName) +{ + qCDebug(dcBluez()) << "BluetoothManager: service unregistered" << serviceName; + if (serviceName == orgBluez) + clean(); +} + +void BluetoothManager::onInterfaceAdded(const QDBusObjectPath &objectPath, const InterfaceList &interfaceList) +{ + //qCDebug(dcBluez()) << "Interface added" << objectPath.path(); + processInterfaceList(objectPath, interfaceList); +} + +void BluetoothManager::onInterfaceRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces) +{ + //qCDebug(dcBluez()) << "Interface removed" << objectPath.path() << interfaces; + + // Adapter removed + if (interfaces.contains(orgBluezAdapter1)) { + BluetoothAdapter *adapter = findAdapter(objectPath); + qCDebug(dcBluez()) << "[-]" << adapter; + if (adapter) { + m_adapters.removeOne(adapter); + emit adapterRemoved(adapter); + adapter->deleteLater(); + } + } + + // Device removed + if (interfaces.contains(orgBluezDevice1)) { + // Find adapter for this device + foreach (BluetoothAdapter *adapter, m_adapters) { + if (adapter->hasDevice(objectPath)) { + adapter->removeDeviceInternally(objectPath); + } + } + } + +} diff --git a/nuki/bluez/bluetoothmanager.h b/nuki/bluez/bluetoothmanager.h new file mode 100644 index 00000000..752a9ec6 --- /dev/null +++ b/nuki/bluez/bluetoothmanager.h @@ -0,0 +1,85 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHMANAGER_H +#define BLUETOOTHMANAGER_H + +#include +#include +#include +#include + +#include "blueztypes.h" +#include "bluetoothadapter.h" + +class BluetoothManager : public QObject +{ + Q_OBJECT +public: + explicit BluetoothManager(QObject *parent = 0); + + QList adapters() const; + + bool isAvailable() const; + +private: + QDBusInterface *m_objectManagerInterface; + QDBusServiceWatcher *m_serviceWatcher; + + QList m_adapters; + + bool m_available; + + void init(); + void clean(); + + void setAvailable(const bool &available); + + // DBus object helpers + void processObjectList(const ManagedObjectList &objectList); + void processInterfaceList(const QDBusObjectPath &objectPath, const InterfaceList &interfaceList); + + bool adapterAlreadyAdded(const QDBusObjectPath &objectPath); + + BluetoothAdapter *findAdapter(const QDBusObjectPath &objectPath); + BluetoothDevice *findDevice(const QDBusObjectPath &objectPath); + BluetoothGattService *findService(const QDBusObjectPath &objectPath); + BluetoothGattCharacteristic *findCharacteristic(const QDBusObjectPath &objectPath); + +signals: + void availableChanged(const bool &available); + + void adapterAdded(BluetoothAdapter *adapter); + void adapterRemoved(BluetoothAdapter *adapter); + +private slots: + void serviceRegistered(const QString &serviceName); + void serviceUnregistered(const QString &serviceName); + + void onInterfaceAdded(const QDBusObjectPath &objectPath, const InterfaceList &interfaceList); + void onInterfaceRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces); + +public slots: + +}; + +#endif // BLUETOOTHMANAGER_H diff --git a/nuki/bluez/blueztypes.cpp b/nuki/bluez/blueztypes.cpp new file mode 100644 index 00000000..8e103db3 --- /dev/null +++ b/nuki/bluez/blueztypes.cpp @@ -0,0 +1,32 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "blueztypes.h" + +Q_LOGGING_CATEGORY(dcBluez, "Bluez") + +Bluez::Bluez() +{ + +} + + diff --git a/nuki/bluez/blueztypes.h b/nuki/bluez/blueztypes.h new file mode 100644 index 00000000..0f846b0f --- /dev/null +++ b/nuki/bluez/blueztypes.h @@ -0,0 +1,103 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUEZTYPES_H +#define BLUEZTYPES_H + +#include +#include +#include +#include +#include + +// Interfaces DBus +static const QString orgFreedesktopDBus = QStringLiteral("org.freedesktop.DBus"); +static const QString orgFreedesktopDBusObjectManager = QStringLiteral("org.freedesktop.DBus.ObjectManager"); + +// Interfaces Bluez +static const QString orgBluez = QStringLiteral("org.bluez"); +static const QString orgBluezAdapter1 = QStringLiteral("org.bluez.Adapter1"); +static const QString orgBluezDevice1 = QStringLiteral("org.bluez.Device1"); +static const QString orgBluezGattService1 = QStringLiteral("org.bluez.GattService1"); +static const QString orgBluezGattCharacteristic1 = QStringLiteral("org.bluez.GattCharacteristic1"); +static const QString orgBluezGattDescriptor1 = QStringLiteral("org.bluez.GattDescriptor1"); + +// DBus Object and interface types +typedef QMap InterfaceList; +Q_DECLARE_METATYPE(InterfaceList) + +typedef QMap ManagedObjectList; +Q_DECLARE_METATYPE(ManagedObjectList) + +typedef struct { + quint16 manufacturerId; + QByteArray data; +} ManufacturerData; + +Q_DECLARE_METATYPE(ManufacturerData) + +typedef QList ManufacturerDataList; +Q_DECLARE_METATYPE(ManufacturerDataList) + +// TODO: get naufacturer data +//QDBusArgument &operator<<(QDBusArgument &argument, const ManufacturerDataList &manufacturerDataList); + +// Logging cathegory +Q_DECLARE_LOGGING_CATEGORY(dcBluez) + +// Gadget class fot handling types +class Bluez { + + Q_GADGET + Q_ENUMS(Error) + +public: + enum Error { + NoError, + NotReady, + Failed, + Rejected, + Canceled, + InvalidArguments, + AlreadyExists, + DoesNotExist, + InProgress, + NotInProgress, + AlreadyConnected, + ConnectFailed, + NotConnected, + NotSupported, + NotAuthorized, + AuthenticationCanceled, + AuthenticationFailed, + AuthenticationRejected, + AuthenticationTimeout, + ConnectionAttemptFailed, + DBusError, + UnknownError + }; + Q_ENUM(Error) + + Bluez(); +}; + +#endif // BLUEZTYPES_H diff --git a/nuki/devicepluginnuki.cpp b/nuki/devicepluginnuki.cpp new file mode 100644 index 00000000..5c95848e --- /dev/null +++ b/nuki/devicepluginnuki.cpp @@ -0,0 +1,325 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Bernhard Trinnes * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "devicepluginnuki.h" +#include "devices/device.h" +#include "plugininfo.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergymanager.h" + +extern "C"{ +#include "sodium.h" +} + +DevicePluginNuki::DevicePluginNuki() +{ + +} + +DevicePluginNuki::~DevicePluginNuki() +{ + hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer); +} + +void DevicePluginNuki::init() +{ + // Read every hour the state of the lock + m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(3600); + connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginNuki::onRefreshTimeout); + + // Bluetooth manager for BTLE bluez handling + m_bluetoothManager = new BluetoothManager(this); + if (!m_bluetoothManager->isAvailable()) { + qCWarning(dcNuki()) << "Bluetooth not available"; + return; + } + + if (m_bluetoothManager->adapters().isEmpty()) { + qCWarning(dcNuki()) << "No bluetooth adapter found."; + return; + } + + m_bluetoothAdapter = m_bluetoothManager->adapters().first(); + m_bluetoothAdapter->setPower(true); + m_bluetoothAdapter->setDiscoverable(true); + m_bluetoothAdapter->setPairable(true); + + qCDebug(dcNuki()) << "Using bluetooth adapter" << m_bluetoothAdapter; + + if (sodium_init() < 0) { + qCCritical(dcNuki()) << "Could not initialize encryption library sodium"; + m_encrytionLibraryInitialized = false; + return; + } + + m_encrytionLibraryInitialized = true; + qCDebug(dcNuki()) << "Encryption library initialized successfully: libsodium" << sodium_version_string(); +} + +void DevicePluginNuki::setupDevice(DeviceSetupInfo *info) +{ + Device *device = info->device(); + qCDebug(dcNuki()) << "Setup device" << device->name() << device->params(); + + QBluetoothAddress address = QBluetoothAddress(device->params().paramValue(nukiDeviceMacParamTypeId).toString()); + if (bluetoothDeviceAlreadyAdded(address)) { + qCWarning(dcNuki()) << "Device already added."; + return info->finish(Device::DeviceErrorDeviceInUse, QT_TR_NOOP("Device is already in use.")); + } + + if (!m_bluetoothAdapter){ + qCWarning(dcNuki()) << "No bluetooth adapter available"; + return info->finish(Device::DeviceErrorHardwareNotAvailable, QT_TR_NOOP("Bluetooth is not available on this system.")); + } + + if (m_bluetoothAdapter->hasDevice(address)) { + Nuki *nuki = new Nuki(device, m_bluetoothAdapter->getDevice(address), this); + m_nukiDevices.insert(nuki, device); + } else { + qCWarning(dcNuki()) << "Could not find bluetooth device for setup" << address; + return info->finish(Device::DeviceErrorHardwareNotAvailable, QT_TR_NOOP("Bluetooth device not found.")); + } + + info->finish(Device::DeviceErrorNoError); +} + +void DevicePluginNuki::discoverDevices(DeviceDiscoveryInfo *info) +{ + + if (info->deviceClassId() != nukiDeviceClassId) + return info->finish(Device::DeviceErrorDeviceClassNotFound); + + if (!hardwareManager()->bluetoothLowEnergyManager()->enabled()) + return info->finish(Device::DeviceErrorHardwareNotAvailable, QT_TR_NOOP("Bluetooth is not available on this system.")); + + if (!m_bluetoothAdapter) + return info->finish(Device::DeviceErrorHardwareNotAvailable, QT_TR_NOOP("Bluetooth is not available on this system.")); + + m_bluetoothAdapter->setDiscoverable(true); + m_bluetoothAdapter->setPairable(true); + + qCDebug(dcNuki()) << "Start bluetooth discovery..."; + if (!m_bluetoothAdapter->discovering()) + m_bluetoothAdapter->startDiscovering(); + + QTimer::singleShot(5000, info, [this, info]() { onBluetoothDiscoveryFinished(info); }); + +} + +void DevicePluginNuki::startPairing(DevicePairingInfo *info) +{ + info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue.")); +} + +void DevicePluginNuki::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) +{ + Q_UNUSED(username) + Q_UNUSED(secret) + + qCDebug(dcNuki()) << "Pairing confirmed, assuming the pairing mode is active. Start authentication process"; + if (info->deviceClassId() != nukiDeviceClassId) { + qCWarning(dcNuki()) << "Invalid device class id"; + return info->finish(Device::DeviceErrorDeviceClassNotFound); + } + + if (m_asyncSetupNuki) { + qCWarning(dcNuki()) << "There is already an async setup for a nuki running."; + return info->finish(Device::DeviceErrorDeviceInUse); + } + + QBluetoothAddress address = QBluetoothAddress(info->params().paramValue(nukiDeviceMacParamTypeId).toString()); + if (!m_bluetoothAdapter->hasDevice(address)) { + qCWarning(dcNuki()) << "Could not find bluetooth device for" << address.toString(); + return info->finish(Device::DeviceErrorDeviceNotFound); + } + + BluetoothDevice *bluetoothDevice = m_bluetoothAdapter->getDevice(address); + + m_asyncSetupNuki = new Nuki(nullptr, bluetoothDevice, this); + connect(m_asyncSetupNuki, &Nuki::authenticationProcessFinished, this, &DevicePluginNuki::onNukiAuthenticationProcessFinished); + connect(m_asyncSetupNuki, &Nuki::availableChanged, this, &DevicePluginNuki::onAsyncSetupNukiAvailableChanged); + + m_asyncSetupNuki->startAuthenticationProcess(info->transactionId()); + m_pairingInfo = info; + connect(info, &DevicePairingInfo::destroyed, this, [this] { m_pairingInfo = nullptr; }); +} + +void DevicePluginNuki::postSetupDevice(Device *device) +{ + Nuki *nuki = m_nukiDevices.key(device); + nuki->refreshStates(); +} + +void DevicePluginNuki::executeAction(DeviceActionInfo *info) +{ + Device *device = info->device(); + Action action = info->action(); + + QPointer nuki = m_nukiDevices.key(device); + if (nuki.isNull()) { + qCWarning(dcNuki()) << "Could not execute action. There is no nuki object for this device"; + return info->finish(Device::DeviceErrorHardwareFailure); + } + + if (!hardwareManager()->bluetoothLowEnergyManager()->enabled()) { + qCWarning(dcNuki()) << "Could not execute action. There bluetooth hardware resource is disabled."; + return info->finish(Device::DeviceErrorHardwareNotAvailable); + } + + if (action.actionTypeId() == nukiCloseActionTypeId) { + if (!nuki->executeDeviceAction(Nuki::NukiActionLock, info)) { + return info->finish(Device::DeviceErrorDeviceInUse); + } + return; + } else if (action.actionTypeId() == nukiOpenActionTypeId) { + if (!nuki->executeDeviceAction(Nuki::NukiActionUnlock, info)) { + return info->finish(Device::DeviceErrorDeviceInUse); + } + return; + } else if (action.actionTypeId() == nukiUnlatchActionTypeId) { + if (!nuki->executeDeviceAction(Nuki::NukiActionUnlatch, info)) { + return info->finish(Device::DeviceErrorDeviceInUse); + } + return; + } else if (action.actionTypeId() == nukiRefreshActionTypeId) { + if (!nuki->executeDeviceAction(Nuki::NukiActionRefresh, info)) { + return info->finish(Device::DeviceErrorDeviceInUse); + } + return; + } + + info->finish(Device::DeviceErrorActionTypeNotFound); +} + +void DevicePluginNuki::deviceRemoved(Device *device) +{ + if (!m_nukiDevices.values().contains(device)) + return; + + Nuki *nuki = m_nukiDevices.key(device); + nuki->clearSettings(); + + // FIXME: deauthenticate nymea from nuki device + + qCDebug(dcNuki()) << "Delete pairing information from bluez" << nuki->bluetoothDevice(); + m_bluetoothAdapter->removeDevice(nuki->bluetoothDevice()->address()); + m_nukiDevices.remove(nuki); + nuki->deleteLater(); +} + +bool DevicePluginNuki::bluetoothDeviceAlreadyAdded(const QBluetoothAddress &address) +{ + foreach (Device *device, m_nukiDevices.values()) { + if (device->deviceClassId() == nukiDeviceClassId && device->paramValue(nukiDeviceMacParamTypeId).toString() == address.toString()) { + qCDebug(dcNuki()) << "Nuki with address" << address.toString() << "already added."; + return true; + } + } + + return false; +} + +void DevicePluginNuki::onRefreshTimeout() +{ + // Only reconnect if the hardware resource is enabled + if (hardwareManager()->bluetoothLowEnergyManager()->enabled()) { + foreach (Nuki *nuki, m_nukiDevices.keys()) { + nuki->refreshStates(); + } + } +} + +void DevicePluginNuki::onBluetoothEnabledChanged(const bool &enabled) +{ + qCDebug(dcNuki()) << "Bluetooth hardware resource" << (enabled ? "enabled" : "disabled"); + + // Disconnect all devices, autoconnect will not trigger until the resource is enabled again + foreach (Nuki *nuki, m_nukiDevices.keys()) { + if (!enabled) { + nuki->disconnectDevice(); + } else { + nuki->connectDevice(); + } + } +} + +void DevicePluginNuki::onBluetoothDiscoveryFinished(DeviceDiscoveryInfo *info) +{ + qCDebug(dcNuki()) << "Bluetooth discovery for nuki devices finished"; + m_bluetoothAdapter->stopDiscovering(); + + foreach (BluetoothDevice *device, m_bluetoothAdapter->devices()) { + if (!bluetoothDeviceAlreadyAdded(device->address()) && device->name().contains("Nuki")) { + DeviceDescriptor descriptor(nukiDeviceClassId, "Nuki", device->address().toString()); + + // Get serial number from name + QString serialNumber; + QStringList tokens = device->name().split("_"); + if (tokens.count() == 2) { + serialNumber = tokens.at(1); + } else { + qCWarning(dcNuki()) << "Could not read serial number from bluetooth device name" << device->name(); + } + + ParamList params; + params.append(Param(nukiDeviceNameParamTypeId, device->name())); + params.append(Param(nukiDeviceMacParamTypeId, device->address().toString())); + params.append(Param(nukiDeviceSerialNumberParamTypeId, serialNumber)); + descriptor.setParams(params); + info->addDeviceDescriptor(descriptor); + } + } + + info->finish(Device::DeviceErrorNoError); +} + +void DevicePluginNuki::onAsyncSetupNukiAvailableChanged(bool available) +{ + // Remove possibly running Nuki setup devices on disconnected + if (!available && m_asyncSetupNuki) { + qCDebug(dcNuki()) << "Delete the temporary pairing device"; + m_asyncSetupNuki->deleteLater(); + m_asyncSetupNuki = nullptr; + } +} + +void DevicePluginNuki::onNukiAuthenticationProcessFinished(const PairingTransactionId &pairingTransactionId, bool success) +{ + if (m_asyncSetupNuki) { + qCDebug(dcNuki()) << "Delete the temporary pairing device"; + m_asyncSetupNuki->deleteLater(); + m_asyncSetupNuki = nullptr; + } + + if (!m_pairingInfo) { + qCWarning(dcNuki()) << "Authentication process finished, but have not valid pairing translaction id"; + return; + } + + if (m_pairingInfo->transactionId() != pairingTransactionId) { + qCWarning(dcNuki()) << "Authentication process finished, but have not valid pairing translaction id"; + return; + } + + m_pairingInfo->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure); + m_pairingInfo = nullptr; +} diff --git a/nuki/devicepluginnuki.h b/nuki/devicepluginnuki.h new file mode 100644 index 00000000..a7c6f20d --- /dev/null +++ b/nuki/devicepluginnuki.h @@ -0,0 +1,78 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Bernhard Trinnes * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEPLUGINNUKI_H +#define DEVICEPLUGINNUKI_H + +#include "plugintimer.h" +#include "devices/deviceplugin.h" +#include "bluez/bluetoothmanager.h" + +#include "nuki.h" + +class DevicePluginNuki : public DevicePlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginnuki.json") + Q_INTERFACES(DevicePlugin) + +public: + explicit DevicePluginNuki(); + ~DevicePluginNuki(); + + void init() override; + void setupDevice(DeviceSetupInfo *info) override; + void discoverDevices(DeviceDiscoveryInfo *info) override; + void startPairing(DevicePairingInfo *info) override; + void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) override; + void postSetupDevice(Device *device) override; + void executeAction(DeviceActionInfo *info) override; + void deviceRemoved(Device *device) override; + +private: + QHash m_nukiDevices; + PluginTimer *m_refreshTimer = nullptr; + + BluetoothManager *m_bluetoothManager = nullptr; + BluetoothAdapter *m_bluetoothAdapter = nullptr; + + Nuki *m_asyncSetupNuki = nullptr; + DevicePairingInfo *m_pairingInfo = nullptr; + + bool m_encrytionLibraryInitialized = false; + + bool bluetoothDeviceAlreadyAdded(const QBluetoothAddress &address); + +private slots: + void onRefreshTimeout(); + void onBluetoothEnabledChanged(const bool &enabled); + void onBluetoothDiscoveryFinished(DeviceDiscoveryInfo *info); + + void onAsyncSetupNukiAvailableChanged(bool available); + + void onNukiAuthenticationProcessFinished(const PairingTransactionId &pairingTransactionId, bool success); + +}; + +#endif // DEVICEPLUGINNUKI_H diff --git a/nuki/devicepluginnuki.json b/nuki/devicepluginnuki.json new file mode 100644 index 00000000..c4b9f54b --- /dev/null +++ b/nuki/devicepluginnuki.json @@ -0,0 +1,157 @@ +{ + "name": "Nuki", + "displayName": "Nuki", + "id": "e5806d75-a40e-4766-a272-5a3a8d3ed625", + "vendors": [ + { + "name": "nuki", + "displayName": "Nuki", + "id": "bf313b83-2ac5-4d22-bf0e-c13d3b4caf52", + "deviceClasses": [ + { + "id": "4a1cc5d9-9b44-4632-8db0-66d64efd4767", + "name": "nuki", + "displayName": "Smartlock", + "interfaces": [ "connectable", "battery", "smartlock" ], + "createMethods": [ "discovery" ], + "setupMethod": "pushButton", + "paramTypes": [ + { + "id": "2477abba-874b-4c48-b543-7b911ff215b3", + "name": "name", + "displayName": "Name", + "type": "QString", + "inputType": "TextLine" + }, + { + "id": "30976794-6066-4f72-8135-6d50499247a5", + "name": "mac", + "displayName": "MAC address", + "type": "QString", + "inputType": "MacAddress" + }, + { + "id": "ea51d911-f94a-4d2d-97fd-9f1d4c6519bf", + "name": "serialNumber", + "displayName": "Serial number", + "type": "QString", + "inputType": "TextLine" + } + ], + "stateTypes": [ + { + "id": "d5fbd774-4e87-4c7c-8c92-f094352897f6", + "name": "connected", + "displayName": "Connected", + "displayNameEvent": "Connected changed", + "type": "bool", + "defaultValue": false + }, + { + "id": "e9ffe14f-b71d-44cd-96c7-eb90fe243e13", + "name": "batteryCritical", + "displayName": "Battery critical", + "displayNameEvent": "Battery critical changed", + "type": "bool", + "defaultValue": false + }, + { + "id": "a47dec8b-4df2-4acd-895b-bfeacbcb6f2e", + "name": "status", + "displayName": "Status", + "displayNameEvent": "Status changed", + "type": "QString", + "possibleValues": [ + "Ok", + "Uncalibrated", + "Motor blocked", + "Undefined" + ], + "defaultValue": "Undefined" + }, + { + "id": "07a09bd8-b342-4e33-92cd-0af21f8689fa", + "name": "state", + "displayName": "State", + "displayNameEvent": "State changed", + "type": "QString", + "possibleValues": [ + "locked", + "locking", + "unlocked", + "unlocking", + "unlatched", + "unlatching" + ], + "defaultValue": "locked" + }, + { + "id": "4e291e6a-2b90-4e6c-bad4-5400e6db4f05", + "name": "mode", + "displayName": "Mode", + "displayNameEvent": "Mode changed", + "type": "QString", + "possibleValues": [ + "Uninitialized", + "Pairing", + "Door" + ], + "defaultValue": "Uninitialized" + }, + { + "id": "b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a", + "name": "trigger", + "displayName": "Trigger", + "displayNameEvent": "Trigger changed", + "type": "QString", + "possibleValues": [ + "Bluetooth", + "Manual", + "Button" + ], + "defaultValue": "Bluetooth" + }, + { + "id": "b1b0eafb-e5f2-47d3-bd18-74a21129f9b5", + "name": "hardwareRevision", + "displayName": "Hardware revision", + "displayNameEvent": "Hardware revision changed", + "type": "QString", + "defaultValue": "-" + }, + { + "id": "9dc0115b-cdb4-472c-961b-b182f77a576f", + "name": "firmwareRevision", + "displayName": "Firmware revision", + "displayNameEvent": "Firmware revision changed", + "type": "QString", + "defaultValue": "-" + } + ], + "actionTypes": [ + { + "id": "55d25891-89b9-4a9f-a2b3-774eccf30183", + "name": "close", + "displayName": "Lock" + }, + { + "id": "76e96738-5336-4b9a-87f7-1822307b5a39", + "name": "open", + "displayName": "Unlock" + }, + { + "id": "45be8d24-17c3-422b-b264-381e673bb3c8", + "name": "unlatch", + "displayName": "Open door" + }, + { + "id": "7c9d5c5d-d8c1-424b-8620-daa3a757576b", + "name": "refresh", + "displayName": "Refresh" + } + ] + } + ] + } + ] +} diff --git a/nuki/docs/20170619-Bridge-API-v1.6.pdf b/nuki/docs/20170619-Bridge-API-v1.6.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2b9616c5d9cdc693a85a2ceb0da4643cdf983403 GIT binary patch literal 161131 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 z�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
8ZMp_F)&aW^bVVGyx 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%0DjmBTO`+Lq7(B~f2=+=>!{^yi;i- z^v;NOQm?Z4FbaFSr^Cbp5=|1Qi6(RsXxw?6%aWk+Y_Li!>YFX`UP~qtjJ#LV{8C=h z1F`xQf9HO;Ef)7Gb4G#$4Yt0vU6NjU9$`1fiM>zMdbs`{2d}t<5?}#L622Z-=8G9@oWcvm%E}>HE3#S%+Z-EZAaF zhoa!jRca0m||n>!pbpw%I8p_ekembt0kur)^|o1?f}Hc$L>$?CX!IOyV0TrET#9ViZ?JIHzUk zFAlPv@vLjo?i8OGS;}kvk$Pm#bEOmHO`pEOS&`KA;d7-Yq0X~&~rK{bIn&G zA24kL90gyU->h4P7JL=k@%VqR>#~dzT7ktv&xoge-wOeLb^%wE_dc0XhF>G7@PWiy z0q-g6xw7pg=iWK&*JE5qy5J702Q>@Ig&}c!yu}^rQKIUGE8l?Mqtq^jAa5t@wgPOM z$6dP(Ebq2ct7?TCdc?z#(!o_1O&jwOX9R_kxi~^Rld(Pn19kcI$^`QmezL3XczN8e ziW%*bRAzI2f~&uRqj3Wuzl=P~?c~ph%ti}y|29D52BLa_Oxa3T+4FK9JBF7~wQpT8#mUhRre(DDJTt^9%#$gmd#j_kx3hZNt6i8rkyJ4t?ulqJC<=9(9)4U~q*c`1GIT zVweAzuYq5RMIPygE?zZ#+ApuD!AUmkDaN$M-NL-N>VIS1N_oO-{q9yECe>6r`yWXk zX9hZJxgXDR9L^H>iv&g2_y-5WGDKgyJK-|Gk=i^xptQL!Q##mtiPX1kUvb0SzD#xc$|Oe~uONOniuLi8Q| zK>)O{=GHI#B)l#BxN#o{%EL$yoL*=dC0ywL`HYMsbz18)pV<=(-3MWYG+q}SX9bM zzr#a9f-?czBBGf9FQfu)n3l{?l*% zTYAsN@^3ur|F6=1{{JKGH`Oz=({(VlwvsorGd22KhBec7)pjZdS_V8i`frUl8!P?) zM6hQ4He~*HZU48@|G%{TY^>jd|4Fa@mi9CMr?j8>Kc)SQw2c27zdCN*%AXca=*c56 z`Se#GEKX!V3*z~cJRTp zH6W{+m1|!}r@TD6q~=kfbWrjAIZ>$`yt0ek+^RsqO3mEOKJ2a(d#@EQtVyRo)95d(XH;{$ll}_+NF%*rc2Ep{ zf=tg{;KJ8?`)!x3^7M5Wc}G6wtn!G*EWZtZ<*jbZQoUi0ReaJh^}H6>BG)K;t4T7l z9DBIS3CL^fiaekUSkKGs2N>Ra0H&afg8Xgf{{J*2_#YGXZ&}=o-<>8NXAT>Dwm!A7kJBzveM~f9v0KApVM3zvI8!f6V)9 zjDg`_@n7fvI{sSwSNr|&C+P^VO_;%9x z%N^n04HN!xHT-vm_%}117Vj^a#eWG9=ve+&!vs1uI@*6ZCeX1lvHr97pOy*D@(G4= zO*QCElThnTml5ADmh157O_m(}O_u8DXC?0EN(!5wxNZ?%=d;Hh8P->=ORq<3_SIZ4 z;Jzi1jrn=$mGFSjfK*&0T`{Fum06vgS%)(2>Dt1?(n)TQ&-eG*$tS5fXlQ@F@55L( z50R1+6}cy$#)O~BDR9F&8fu#y-lkBH8f*uja&&bJ`-*k-boz~R zzDw^I8|Od0b{C7QV6N{ld^!^aNjH5}fMiQAjLzM5Ta13eHX%KK(akD1WhJH-u7AyY z5SaIWLCu7!V6LF0siyBR)Ya^L>DOQ)eJl&p*VXK})9$3JVq&!JVYXtV?9I=rt+RST z_clA)-S@FH)ds%?GXipF4)FZ?0*-igSo-=&?7=?l4Zy&i`O)nIoIQ1<-4iBb{7j?M zUu^%1TC+co{tn6d=XBx|80ucz`8K@^>%Qw$qVGGPl>83*dzGepPB?B4^X{dz>ASm5 z$Aw?hyBq|+gW-qvD;nH#>(|@bk0P4v>j$)M51{T-T<-1r!@YMYZECCUAkWy)+~7LL z_@h%ZLRPSJlRIQ5cheYx|DT4>FH}~>t4I+C$y!tIdqKfIsqoM^~ksH ziHx44wDp9Ih>O0K0<`U}gdev%hbL~LnJ6v0(vuFyXNF$iylOqz)Y3oPcO>R#58WY> zXrw^vua$IO;ux9jKbrxx!{WB@3rWBC35zOv6#h#3C?x&%-+8<`72Jf06=gIk* z@satlxu4GY_4Mz~Wr4B#-o)N7>}YJ5p2;Jx(dw4__aCfvUS#QQt7)I^Q^^glEVZBV z{hvHd@rjq(5}(zO+Cm{-^UCmh+cM9|@5|qXh(2(WETFz3K92=0BEBl_dE!$)(Lc0D zwGCUm5yzj1KaNe7t|7n7e>Qn*(An8AzBLEwyp;`(Oo?5)7q51m#lCVEe9A=^&Ogad zd@6>muzWZxpL@U>e+`G;I|6y1dJlIkBzB)lY@VKPG&gc>@xhTN^%l z-?tPNrdIl|dSkv1uUhRGd^HwEeLeWSus?qVM@~{k{)vpxh=j`7`w4^x8v5446tNaC ze`)^H!3aVjXo`BVwy5+9+$dmjj4VlW-Tzn9x^NJODw=mYCZo#MV!AnSBJ?XXEVfac z78QV-t%0c(7h&gjRln`coI2B>B=V7o$+M8pJivptdiR}`0ZEJyA)Ts*j$?k`t)F13 z1UwKk!Zp*H4tFaW4AM|Fct3w(AM#ye?sS3 z)uhrhsS5#$+t9AFfjVEJ{i6pMmT$K#25U{9K>8-=7C-jn1)OlH7#Wjs8U4BnHLiQn z<#`3WC&LZ?kU!eFp z1HOnDvV*Ov^ytzO+}#=o_m6O1t!_3UOa}e5E}E! z`bJLFr%t!XMcFXi0BKZ-`B3;YK6wyyq?OfC)%h@9=)K z?%bY;m?VN9TeN7iI+6%yQattULW7L_wBeBh|9Udy7>PTUK``*TGyNDfDXGH@V zh2{jFFW^w1$`+F7r_jxF4;Ce#A2{9n#&9;;g`VujQwZlfmjj_o$die*4DZj7OqVI| zD=J|@54Z<=^a2Tk(3E6o^Z&XdoCZs3L;u0cTHqFYoz8;TZm+7o91bxCqF2lYXy{#* zTM;LmK|n0qI;|6FXo|C`8yLaR-%cL5m&#`@ad)`uO%vjY*A5X6H^_pO8mmGo@+dfY z?y7sqYA&(o;2)@8Kb4Ps-KQz8 ztT6ecnxtsCf#t1 z3FMCaVTB*^M2w{~)8;G6>n_)iJ_32i>+(aahk5mf*Xg#;;6yA=30XK(uo|dBB4ITd z<#;m_&~Lf!l@XB|D3hiiB5&%WvY2xIPPR1Gm=mq`-Vnxnq*_5TopE{ad}aprUq=$& z79~@uatuS~d69}NA!u2->`0h=Q7dGcg;(bL3JZ0~1xN}i4M4n$!;wi=N+_-@(K{dT zOp(jSG^vDc__XG&HKZ;o`{(h+fHJ<^u!(hHL+}>3J~<)~ZN2@4+o5>0Q1`toHs46(z%A7(4`J>vu%ylFp{6&3T)o+3AR-dnh+ByY_qFjQ zH9+}Y`HHx5*rj(hsXyRH!4qwSq}oERj@|M;ZC7L45`Cu$O9)}~PxklgUVBMoTG=zT z@HL|aelh{Yb$1FV_HtN$I(!1Q>kpw(hTEx)fZ@{meZEe`_*- zf>Qf@?qXr}CPw-QmpJ#0%3|9b$q>)!9Xb}j$x8FCH-Ls8On#1yWRDzAlBCPJE&HvX zisBYpm1Y*=7^}{bkhDT*0m6spC%5+0kHWZ4wTT^4W{V)f6jjv0B1ENQEt*DniJ4;k zIaF=G1G2$u91GZXEtbBHAX`-+9NH1~)iTp!60jBU1jPaHT=3+kQtVC}@ZQ?`=im=i zT&)C|*|6z`Xvh)k6z^~YvNRttEGX#dcK%rdW?!dktmG6;&tQ0u;V$Sp9S3?-Z|vb8 zdid?0gt0>W6-wNMNJ*oYeSbC}#g?&AFDfC1awb+9LNf2{iR-d6f_a;E{cRI99PUvS z^0Zg|zl>dnGg`v+1jAaD<+-#VB#J0W5~K7XcF?N^g?dKX>KwuW#1lo*zn9h2j4%04G4$zaOfxYbbw8 zffD{onIg}+zAL^3#=}oU-@-FhhJDE$`(5-c$nhZjyCpXW`PT_8EpN_FkX-kno8lZR zW~o}UHPsD(=c5NZiTs*7jQik3b) z<@(u#q@~}tf*3t5ACGcSmlqZ3SRimn3w~t<+i(KN(2?at3{BwJdunsnmiZxKO;z4NdlFmZwxb^U`VrV! zxui3&K4C*O+!iUwcNQ%e@}GpRZ^3?lf+8rap-P%oSmVoX}db2@)1T@||bG-g`0&>N-&A{}YmaV+q8xH=7$WUp{lR0pMTH z`FrnboHxVwhW}2((gS{*gFdM21ug*JQkFW@gyZ&}8L6$_yTz@${Y9jZ%5xH|5p?k6 zc9v|r3TZhU7-N+bCx8z-FNkOTQcY+FsWOj%_Z6)`{P@hqH>j{`*{Yqb!Y8D*G0z#Y zKA00>GSaDhYsJJrJ%IGQEs)m~ccBoiJlA8n%wrW_8kyU3x@XkG$$U}6@yWkP7Orwn zLQ3AEFA2X}($2*9|PshM_gVi>aoC`S9=HetR*YfT}?ZShj z(L~@E=Avu|&)Blgx*WQutJ-s@_h87dng#2(UorE<^D$DORz&A4@B#ej&a`DiswZop z#U;w-bbDh+Gm1qKgnGjTte&M~`(QwE^m;14*fD!PUQSuTfg7Apf%qF_YITXP2EMj(L&x4(zKj{^NCB;ezRz8 z%mXSWnZ|^$mm2pQ`ANd3d5EUzJ_nwjJarb`SKlkA+h~W|r{->~Q^Mgfw$rCU6v%^z zL!zIx;$-kjiVQ!+Uk|_mMt?D`GkzHu>|QMuZ)vUo!y($>IT>6BSF-XIsEP^sDUVskb^64h;bX@Op&14Tb1SSt}3~^Ojtzj(HHn^@uQIt`lukw$KCx6D^c7U#_XUeSKIbn5B2p5 zy~zLoR12{)ul3tS_C_-8O9yRx;3O&4&-3{J5zWYRG?aA0^i z(WU$C+7t+sNMR^VPD3@0GBg@9-%ySN@YI7S1)_&OF`eV^YDXIu$oD9u7io@Yfwi03 zn5X8|Lq2$c{!dTgH9_nVBI_JAcA_!S4IlR|Hpf2j*ga0`k>w05V+!LZAJQ5Yv<5^N z(^x2<2JQN#s>y{Rm%=nIB!5vMM?bA$SSd`u9OL^B4rJ%vz!1G&V8t7GhAe<<9UgY` zT5i9O(FREsw1rmXWH!>}mF5siIx7y}Nth_sRa3}7tM(-jFRO-x(&Z6 zE@Y_Z>sb~%it$qk+?N_1!({XuJSjtG%1;h+mX3Qq&ZfM2&u=2?H` zqtf8rxy6}MS4(X;3VAIDIJHm?4PVATiR%f8JV|8`JC7`2 znMGc^UG~N0hP~o!;p>y5^xb!+Py+<`#m4yA(9-WeHV7IobF@m>H%vL*?Oo*nt~iMW zc*V;ZJo?ji5g`)+Tt9hqn=gJ`=+{vc>}q*1lJpsoFtIw2u+o zcJI=oO7H$iiI3N?Y6q#mprZHEXCsCD0yUqb>Qv8al6!_K&9V55nr=}v_XeCgZCcuX zZ@eY!dw8TsTk(WTBO8xc{R4i?YMo7?Yg+-P7i|c?UBZ(df%tGHTcU*)IMd{CG?aaq zH-9kpDoMGpL@1lKxM9!5J{4XsTq42*kBD<;z^!*a-(F7m16))7bve0=>}oi;;K~pt z^O3=~8Lx1fXaJ^eY-l|T=6Ev7FGsq0*JMAk&e%KioQP(@4Q}|u)Zk)hg`nfVqB*~2 zZI_6&r!vUYa;XyJhQ_Sb)A&N5%BG$9LnxwcjE$m_RDspDASMSpfewNVHb>;r!qIU< ziSJ@Z*^Qsk^d;3s<35otHisPI*!T@u)#5J;K;{hIGxW^ko}91A zpiH$+J9N6$#7#jsmpmtuBr;@X7@eos4~wOaT2Ds$v83Set({tCrlIf}>Rb3CFBo@z zavGcY1hlKrze?VAX_CA+``9M!L;01?;AzTJ@#n=?$B)fk;OSw7l7E=f)%(gtE`r8E zk%mY;QZZ#*X1sUVKg&~c7v~)gAf*l;5pwqtxY2)*A;I?+f+w1~N@zktmE&}KWUy?L zWjt8?(adn1c3;U*wULijMLxSvO(~-B1M~LV+Mo~5lTmNIg($VR>DCw?vz4k_XB&=1 zI$clg6y;c@~=;C76WX|C-L zuY`Kps)_t}?U6u$`s|w@>|?`mS6b5ZI69A=k!n0xjVEnW`yn;uOfeX|KYgv}(|r-L z)Ujy}@hXLv-b@1|6l{muGwGwvR81M99ZT4sUi(6AIjA{k--gN*1bDd<*n@mS7~PQ_ zToIu!hyGY8a<(%0jx6;YMMHDw;_U_CfghD^d5}!)s2LYyFaWG8FV}SrRc#W|c!7t~ zIQD?}#|eu*wIcZV@81z}?!h=A;I7S8>|pRc7vDJbyi>scT|+>KOU}Y?D6!Ai7MI^V zE9*f}JG$H+>KEqNTP-b#_cEowayu<;63@2I94uObOS01axE}hnsIoIg5;S762PK(E zIBKp&UxDQEG7TS&BTg}F23T3qdNG~`x`0b_QnDgc`ccVBmU&l7ZP%n<$*(W=+=tlT zarN|rW)bbx2Eu33&kkpHsvL|;>CMP2R7{SmPBlugWvTKHMne42Sfk?h;5<-TOL7hB z96+Au@w#;oTQk-^6p9Oy5Yox6vKL$n zruZPLx^u#%G1ll$w~T); z&<;xs?c~mVD*K;&>J0azeeV^6QMsJQpKg-=LKcxZ^$0em=9F0ky3W#myfD<3OST<- zBtBN|@JWD6myY~{0uT{N+5piHLIqD(F7xYNwqbtm#VGF)M87aS8f%|F!VSDkHD~8U zYOvi^qG7QP-hC{f+A*+;`|H^inTt^3ZJb`&FOX|M4{OPs0~Wgyl*0s@lqb70e$$~E z*f_9SjY4$Qyx$%$MuFDzu~X2uSCdt|%Ad-N^6@=T*+J20(TPSgior}^H92sd%r7D# zQ3_gpLMl7IC)I#fQ^%4=$fJvvW|o_b)B$&oF%FFOQ~+o}LMI<()gff;7N-;APK75( zelXVGj|Q6%Hu4((WlYlOubg~_EDUnT;p@Nidn141^-E#+C5~Epnykd@z(r!~+V2=T zO@(BwUwJv_W<(hT4__s@s->^e!@%~gA0|KcRt8&SGTm(W$|~_oy6vF9*>A~W0WU+wvY z4jINo7e9$*LtBZ|(flq^WV@>cH;q5ucN{M`=9YL$;PWqvYmt@ltJLw2@b_JplK0H$ z%7x~z-7qyYwm$KZA0Hl7Wr_K)t*i8f0uspx?3Zh15TvTtx!vh_9#wQ z+5*4-B+@heL~f=R5YBvDmZj<6gtEnt*Q0Hk-wHc_Y-$G>KB$6IznH~MWHi0Atj6y~ z$V&-#h_4OF89(p=ZLPn#6=WrD%-HPQDr^lPY=}#pz%7_%ys*oBBc!>T}3BtbBKfi7K$$I?SZBO{Nq0OTKLCf&~1Qpg*fz)FonQt zH=lEmg|%60#u$f}q%Ym z#LCtC1YWtwJ-@m9@`QHc0u!3O-6iUnK@t+8K3|S_a0TJiMlINzpsMnY$PBMtj@Hx| zaKRg-YfPxbmYs$*Pc z?M-5Y$JCZ(DQkh<7!EvDCdtFPBO zjp}ljcg|EPT8BGn$=gW)qOGxFjHm&$54|<=p3ZP`4+W%lxSR^xA1DR3*q|w zz%{oD)){S!VceuaI<&@p#iOzm!@%3A?RN?Sb^0(cizAjKrFA~Jaxrz$&{vlUj2{a% z`097}fGQEq%FVE_F?GFiCf_OX1H-nOf#^-y-QX3%XA3_w0~T3p92JRE0C&WMW5d8? zh&rh{x zd5JlUv`BEB)`ST$1tan;?W!Z|{9%d0wP;3#niw7aN1elww9km7d%8I5^O;{b z5C#Qv0RuFRPJegt42>taCVlRXLT)i!knxP^kgllGpL-vERGlo&neD*Zo4e7mddr($55u06`_0*98iFq zWp4nSj@-dc&wj6kpuSloyWiU88#ZP`_GU1I(c1%&MqfUv2y_KG~Lt`tsqm6)A^)XjUuI6V}mTyJc_RAa9q}}&|CQRo8+ouYI{w20JIgZ>2 zHZ|MY^jX=mp|UBsD9r5ws@ZLVEWQ(d+OgNsg{xj(bIdP2n)+UlbyQSFoy^Y`{+1N4 zWlNsK@MlfkPrH6O(dw&vAV2!Xb2X3QhzfCshazdykunJgwI9G&@m^`4YdVn=j<)mN zK%@KM#XthD$ik>3{o%4kKOfnNxk}NNe7R&wFvs5xm6dVd>F>A!V;Z1eU1RV8R5nh? zN1E-BE==stF}Dk;lmu^E;t9%tO{0ILZ2H9!(8sG1PmzD zJyruYt%9O$fGE~)Hc=F)5#ie!k50gOmbZ>OS^(Iw<-0gL^#R_-b2&VyCe7({VR`B(iaP~`t9Br9c=fPy3ysW_}^()MYLx}v@xi@ zQlooJPg$q|jxgDM7|wlB*j5w<3}l>Er0i8M__nkP6T3Nzfr5Hs_=!NQ1uc_##TQhW zoJqo5W2Jn!m@A$+6!^htfFpVihyli3$1(9{7dkA+f{*rOW78E5nq{iZd7Ra4digFo zDsRzt`KoMOPsx|si<|1$7-p1hB z%=THcwj{V=fX~XnG6ZJ^s?tKhV{PkaA1;5$pi7FjXTmFF(N_&G8>vFaeyC@(WaI8l zjw11aZa)wRLN6L88u`Wn$KHALkgn`bdE6Q#pRETTDR3e=o>jA0HLF65$C);8w4s+k zQdPQk3k&fwLItqzapt2My~TkSbYNLKEFMX0#yElhJlDWW>?1@yg_&v?jhFnp34q1o zyic(4LBm4-YTj}tv^46{3T&&NDW9+?36msez=;5Rk7kFc=iJ`4wd+D}DzPxX5c7hg zNEAEtzFw-~-IaCPM<__>pO8)!sOqn&2jFVo#PKt}Gq_Xba`=@TH_s~R34loJ9cTxJ zAPd&olhjd9UR*tEpJ>VpN2*SutZ}V)RB3*e_m!RS`FyyB)Ns=3>(~q*z zQB{ZG7Th_CE}FCXSK7$Xx81*W{7C2Jxne3jfhBF7iAx_KLRm?jJGc&vjt^e{6kV1D?9+-?S z#){=mN-$oN)QPb2F|4^Bl)3CuMptE|fQjIq$Xoxg7%6Ym%B#VoQXXatvL0@8+bcMj zrJmqfIVA1`%h8S4E3Rd+djc2>ueSn|ONL1NxjRDq*C5*T)4`RgVOhmjBT&KGGa@l4 z>7_&BlEa>4u>L*d4DILE5^T@Dlw(26OE}W&m{kOb^rnqVW}o!3B7=HYJ4XAbTLwO_ zQX$iLO_CIPKx+W9&?NfIhcdh##;k$Y5M&y#!O)PYG}f|X7tWf>EL<;10p1o5hKcbk(Mx>KGLi(wEXEib3u$Y}SEkz8tXAF>n2xA~z zlXM@1Vr4VmPg;j|35-w+I4?k?e;m9POW0ifKdr?(m@wY&68e zYD>U|EQ;dXHk6y<-W?mKs+XJ=lgUoRW zI24g<1ErtxYDM(i0uPPFvzq_5shdWRlF9k9q%C`rmmKSBj#A-U;o>Q3ZO=y*d0Y z83l1iVmBV9uSOl}vTWK2fRf!0qBw_QS^@PFN{>baazB}ti9#W}xn_kCea2~&T{>%H z6E&lSX^#7f++pVEX|Vtq%T6d2xBZ7VA2(JuGp>{-~Z&mgTq31<*_l1OS zEn)uAdp|yHccx#kt34*;(>;GKouh#SM!`i3qi{+feRjX-ox3rT>#uRY^90sWjCfUd zsv=eX2JWKfSR6_U6*h@Yv>#O|yUCm2zfPhn#2p(lr)7lS1D_n;GXwjVv!PTosTE_6R7KKD;~!3@Ugrvr06h4soVb>#JcK3IcgyM8=?Qw`r~3Mv)* z^$R8{-5@Ze4s%ymqoA@7wUlgx4c!!c)XVLG6#DkcK=Bcn6LViQvEpMRRyvfP^wasR z-jwMABEEZiP&`l(Qvm>63sXgC&UP z8tI&+gSHEqJZ?%6!`)ya-9)v|;T|y1Pf^W~Y__-Ykq6j0(`4Y8zUrCFBpWv3NkzI4 zveA{(O-5W#ZGyz9R*E$si;>im4>^%@AS?`Zp=pcH9H71eHcE7kZ*{9r*vjDx!bC~H zHhFgs0}>wQVWW|20T8}kbj`X%znHsrXwG`2*%MkKT}Y{3#QtrZAn2wd@vl%f zhLLf-JP{JHA3^mjJkPpJ*9ll@!h*C`zgBC*i<7+eS9#|#^4T=Mb4@QkDFBZJ(IOg`LauPdzJ=LL7PcjfA~31yI`rxIuuyAN%W@#c z&-XS(M(&Av9&nfI%%kD2giMgmui;+ukTUI;GCG#@gLJCLveSUfWzV}em+S+NEPKf2 zPmvvnIh4a#05enrF*;(`g+chDT;({@NqwWihX{q;yb013<32K9A1h4?8Qoo&-5f<% z*fSURfpz`>LD=F}FB4#o=Pg|t+cdwc$XQ&6)=uf>thH43Pjz1K5V5D=v}EyFzjyNK z=!g%*G<=U}k5RCIHEih27M!#WnmoBvh}_Re#@!Eq0qG?pj#K|LVYOzKNc}4-UmnSK z7dhoE!3<;id=f-cf;h_HT!GR7oayCj%JB6$K%*u9fD<@&EyZf9#kXqef?>@lRTk5V~Omw+&_T% zzeUz3z+#8MSp_=ih-Xf)y=-p7nSnz4ddG3(p&K89@&Lr$9J`J#!zDP;{gnSGP2x8K z(Tulw&w0upa-IrHU2X*{_D~>IPz69d%{S&7($d#{BHUC@FOvw#+|!I_0*s@8v^JI3 zMwGauv=g09_ZG1nj1uCyf*QL=_ap!I)SEDJ)g5Y06Lf9b?B>p+j(6&(LAcA}i#$u3 zfeoiW_RxOqWz0$NbHA0MlYW*vJZ51`cN;b^ABwzzfyQrn>ymXpqcZ{;RpH&REMWi; zJt;PCJ{1)ndXE^zh)%<^CbMcxog~GanJOP2k9oe}#RIK6p=0j%Fx?~Nb}O29)ksGI4YwhKszOWV>!=? z`R4UVUIJjN=a~ZmW+xV#L*HV`+Zw|8SL#h4O{tK#I^ASGCc?e-7yRnSiM}|CGm1}G zDu_zD7cCDr;7=dFN=G%;$B;uTj|>5u+?0|4q2E>zLbI%s@mQs%iN@N(xW9JFt?@2A z<9w(PfsS(Y=qx+l5$wpvZPtn#(L4A`2&>J>lz`%-`|!O zxmugrjtf=&3EwwEC9ATBx_h@h5$I3sH0XQyMI9I zGgyJCJT42wc;dC!yML-i1X50So!LuA9#pAR!WkF7*W8o_@}@qW3p+A%qc`K%N1qKe zQP=l%GdsSJd79dX&j*aRQclP`Gj;cRIxFVT9b0Su*&;0Un@RS7x0cNzu?X&Xq!^ZQI+Qb#C@VT=YcB+kE}8cWs?amJ^g_$r-K9V={7EVc7`GW1V2~8vx^=M+Wm-+^GWbb7uV;cuN&-W3R$SQm@ z3Uz+npvuV3$|W`iErin=J@T6}0(*9AW-_f(IXABHMl<7xILh#mJrg;&lL9d$+)S}% zTBOro@s-xx*#D4Bkc3x&$|_#rjVOyEL*ptWJlt6&uW!d@~HJie$W!v3~vuO zV9gXW0`9GH-2)H`H}^6}#hy@fU!sGK%vNpga}C{%{^2+t@n?{9gL4{G;cZo-!dMLa zb!xk;lJeus!bXwNXfISF=Hb8^36D+Jd#s(KdcEpegDGM|_bYYZq+J=Fq!))lQ?F)wugFE)^N>}` z`1k@*zT_b>45$DnC8@u5h->NEI&rQ1@qBlaeVfdrcrK{4)6KzA%xRPe&NWH}-avFv8OT?!PFMVWaoF{Z8S(6==4Wuao0HSvYO^YD}7kN1q<` zT_1Hqs%_oH7Z-8OumawF zMR@}l@Y!fsT=n@olS$D8T*RD`@ZR3KHY zAVPKU!$^;1{At5kQ%trOt5!=r3w)-vk~^>N&8!B%eaDu}|3kBFtnwa-6=_7$Jmh_r zwoX^H4ml=eGak7IONi@h82!4i2+f0@{+Ph@q@&KPL?;!=Oi~_Ap_*U3?ona?} zzg9Xb`AD!{M(Z=cI8~^l8%U*~S)p(^me365K4Zl~D8~^Fk*8Csy#-38>xv)O#=UxN z7)v!7WF;K0=$AVN-?W{tFfLZAq(#^5uWa(i8D;ZVQu(O9)o;}k^dA*(pzx)rnbK=3 zj__5bRdq`G29oJln0U`(iFq8b3z@m{n;Dd-P5NPi;BYdMC)9%?r|0tR`&a0fFE{KH z$$e7oF+~%yaQ-#2? zq;<0ta;Y?L#Yxtr>bmfE3?BmPU!*XG@SQnA!!%ndTG0KYKd=%Sjt6Sv&#^)02=4~YMW_Qw^X^awm(vw!30la3Ry3<7@!h3X>P5K>hf+DW3S@H~Rr;GOy{ zgPyu@r5so#Xwj0Bs*kP%O&ByJV^o39Z8gNz^=(ecuS|LK(+HUjJeNl`Uzw@!#9p4Z zRe+_l5p$VbcmoprNDl08z&##rr&|{U$`kBo`j&e0sgTe}&9qnU&;?sgkOUb1H0^lf{GNPcPW+yP2 z1s+FcM^9~EU;K2Tt*o^TogrOOabY~b0#Zs_1IObiq(v~lZ@}Ja#8Mz+5&Tb zKs#e^6x%L%V0JNq9yIZnBCj2~kz)1ICjXGYh^W|2H6sdi9P<;wr4cZG+I)2sTdlIA z{cvc+=K*>34b>ZhW8tr~8_l{w#|+|Y^tm4J5?V+%Ffk#BE<>7(E1Q2H5a*s8XxqfK z7@RjfSZ2j-op^Pr@EDKYZho5n)%nBa2G$QoN(CbxX2AMxC{0zywM${+5=O_9JBzAo zVw>O3+MZf`wU9;vSBQqO@P{LV$t=7{+CV@Jp*E8r3V&l+@GAVegYj>iwL%XyF9{IC zE2dMIM|)G;w?Ay*1Nx1_l>LuaA$E@Du2>SmkRwv%^Pe3(YMjDr{;qX5np6at(-rdf z_ke5p!dXz6VrGq#I*#7v04VRj#ACD93{oK&Pd8+{^ounLnda>Q((>>_HqdMz1U9AD zAhpLIrob2g*$p5?I>SS>VxAJCsiWKZO^Jeh?ZBT1(|cA!D*qaIb?4qKW9e}%c zM>55Vd?ri&3>!Bv)Ut$X#d$53QqUibUWpIJ!K62CM6RwdXCa*i({KeUeJ)R>Oe(ks zX%Un9K@CJYS6jZe-X||gg_HWQB0d>u{Tt(eIET`Km=vxPUzy=;jwAL%n0FL5*M5H2 zRQae%rw%26!0ibM8L2u0^p9tTW&xMnq-orXZxy zGz+<%*0FH45+nQ_Wj7tw6_Kt)YU2bZ*e+H$Tf@trbG=dd*ru&~1ftxUc-%fMY%H%V zwp5HrG|&eFB?1!=_OK+Ae#+B5Y$55PeR?N$3G-XJ99T!crniin7nTnf$Z`DP9Zedi#wp^OoMl8AL!Of-ARj0{MZUXprUyCK1K0It1 zWh%d{*Tg@cG(D|@4SC$+bm=3Mx&n-?m+-O*vBhVxnu0SLTX>m0luA;flzLFRAurkH zhNr&?+EL3^%;Hv7$yV(Le+RxsUX1nRl8}2N7iy`#4~EA2L#Y0U3|lThF)w)l=o=FG z0o_cE4%^pnD&fKU@vU38|5Dn?GleXBcU?|xqz4PKo0v(%I5kSgt|d!_$_aD?Q>X*~3z?A$4ulqo z8Xr80#Pt&9L#0X`uMU=*qqSzWqy+h`eMxBGLYH59o~PKWj+_gLx`h5i6`J{JwMxUk z{1>#I#Z~V22I@6P|Hycr@6&1V$Cyo&9oPo=Mf-ZFq<<9btgoW8ScR&I?ZzcP+X@HH zb)6mKzT_T6khO)k)V5Ott8Tu)UdHWpmQaZ;Vt`?gPF2kJDVWy)391s&kOuNBQ0izQ z1hSJa@GT!7>DeI{aTf?;Hv_X0r=#H{##Of*A+UL<F@FgTm3z~_gbBn)vM{VfC6tp<8P-vLuzV4eQi&)*KXpW>>H788o z4<7ijdvu7!tb@>x#?wLLjx5;-ziu@&O893YBVD7?h4znFpe08{1{t+PB=@hdh^?rz zvH(sZ4SxJzs8nOnv4f+_W6qg=YMfSCluYgs#2P!Pil1FrUT5*gmF&X|V?c@i zscmdq{T9tc9kO0-$Fy`z~XpQM)?ycYSs%aJx;Fo2(9;`^}{T`#h~*~UqDk1NFhxj zKx#N)CFZag{Q#UjqKN=I(Dlh*|!ORb4CoZjTHKcFe`-kvAysD*GN~ z7dil5Of*@ftq3D z>Jj1+c=^n$8D6MuR2SJQx=|t#a0umN96<4|^b%0Os>~g&c)_DyMY?}_xQtx76t@`X zr`0`-=}t#rfO#1_gF0EiIaWS?JpK|xc4Cs08q_CUx8F$xnQFIaMn#2xe!FWq3yNoZ z@ilUHFx=_j!(~F(qzYAY1OLPg#iNBeeKij^weiSsp0k--ur4PHQI&TM<477c&cpH9s17(~hq)j0!i7F}PdVpHc<0MNjJwFchoiKYf&<_z#IJT_a zU{;{e2OV~;rix-VuMzh*uF}{0a8nD=nLLAHnH=+YHq3rGYbH;Iqj~9YEYwXmfqKmd zK);`DMj0AQfX84`LQNJzS=kf-?+vA3r;XPa4jz1vj5a53lt1Oad;h5;)G3Q*i-f2vC z_x4_8$y5J?joNNNr5*K&=Ni>)G!lUt84z{&u3^#DnkPbdOe(`QPn(&pcD}JSI~%~0 z+}r!U3_iyYvSuXO5yHlbN{4sKs+Mx*=ZJUcW2bx94bdEfX{<_7|DeyCF*Xa27$Hg$ zfj;8(ZCDjGH%P59PWkir+|jhOjR{}`^es#6BXBt ziHLTCVKuXcG{FUZq1zk4s?w5D_)!%sA!D9_tCN$)e&8rQ93|*&1`4Cn=5_04123vg|-=8F58L@N*iqtCnZ4NiR|97%V zS2h6CIIv2Jk)ZH3dH!jA7&X$zgd#}~DyCQ_TA(=351C#lCupuAMG!KuBlDsSX0pzo zd1kR;eGQ&qx;Dm0!aJTp=NL)z3QP9UMBs&4mCOrVoFB&$v>5v@|J!?2|%$_(wEka?8(fs zqHU-eZk*8vcOKH0!{oF7EtC>oT|BKplF;@?9E4JZ5l$3GWH9O2BuGqi=cl2~-@_dO&Tvm)ju-t#R=&y1TYtJ*w$L({?wI&U(H- z?_2h@QNycE?$|dq)5pSWF?j!@vEF~54}fBrGxCr@eE-u)p(K? zet5{6*r_-}1Mfjw)hw%+ixJCRHE{Z6LD0&*7jeK;ab%n9FbGdV6fnM=?J>%m6o68+U9z*tlW7^@iX<4IQAkGT2g zND{W)O~MW-Jg6YGmqe`|u%CH+5genz5{n`_4R{~trD_*zbK;j4;;?nhp*W+_u8K(g z7{97@x8I(JM;V&iN8o#7DGGE+^CEUI#m;bRr~6q^I+F`^m(Xe`mub^CDY>jCVwfAj zK8XWX@<};FIEsSsb)$IJFmKEeWk@71b7+bd=Y{?*8)MuL#i~}+ zqM2vX42#+NSA8}+2x%;oR+t~L08XGMb`!{N3`TwCa<$cV?u@!F+IEUcpS(cqbd=>i z(+2bPK9E;UG263m_ZCY^bqdCGiznoRPzj^4`F#m{1Tix#=i(};EERdKqRofAoAWWf zXoVm2jev^|QUVhnQ6He*;|C;~InSvUfdSVndE}#6_fF;BAdx1EmNv=50auNL;oM}% zt|X?BmWNGSeeGXB*s*=YwzmaQuA}Sm1Fy&f^@<9^QA)LJl_bG979ks%A1kbE`e1lD~IRysl@CO~Rvj zB^0LWLpN(c6Rk}u7JqK=bcOIpx&qI^CsD9)Dj!0+ELc)ycjAEFy1UCrCHe6RJ~-v1 zey1T%?_3#ysby@fJGXY)(u>&Xp^kT zs^_^@&bSeQaO7I1ra!_B$(*#iqJ^Cz5AWvAhkTVtd zgr%cY$?5UQ=&oD;ivK&$*}^}_{djZG?L6^y_osf6>+&z%@TNwbN>QTa^7RL(i|7*F zS@{Q{BBS?#pQY}7@%lJUTu^tk4G;(hI|409rzLE=X#f-5+5!p2>E%j-MwAhhlQna^ zDRy2whCsq-aa>L9@#zipg|~qllyq?K%n&EtCjx>E?Bpml!o5uFd168pVSiz zi08>yi6IRe-6o+Vz-D75v%jZ?OIY^O*3U_ql!zKhxmLyd1vq4YOUkT1!>gf4%YK}8 zwZ#y2DZhl{Hf!A)rci%9Gtpr_@f6gjJ*SJWzW0s9orL4oXo@% z+qNc7CUz#aZQHgcwr$(CxnsS1e)r&>bN=_Mj6qRD%lLHJM$!h3wXb6xY>_qH)0H5hT$YkEXFcvQ-{C*l8T)1n>=eC!HTV z6-8YoUC);e3fQngIHD-Jkipn2TIMRP3+f31=d-wi*uGG7mtNvk29TL(97m6E6(ia| z*1syJ;|VW@avyJN-Y}*HK#0>#Za<+Bj0PqprX6$-?y%V%;m(@xSh9!M z_XVubCGc^Nw|;Mw5ftG;AY7ttwG>#VGNQZaL^^AYM33Xn$G+lGa~nKJd7Fik3P>m? z2@Jmb5byFv!-xtIE}9!e*~Vilndrkbx}gvtgR<~!nbAvFfJg(YzYWlL(;#72cn+e* z&>YR9o$($GVOP(M7b#mX;0ysnycL7)7mo}4@YJx=vsQ#d3Vg>ofCi|V{#->EZcmoicU%TXRRZkG-`GjP z0ISEw-q<^Yd9Zl02CF@1<{U5*hr6HgOkkElKRj=3RN2splsWpS=c;|6+1T$fAzk7Y zzcin_Yj5&~rR37GdUe#lUsy<}j45 zw!>)z2^mY<>3QG0jtyUb*KB{qma{eZ0_hzj$cKQ(zxcp7ec@Ef6Z!q&aflEd(Qi-e zP0L`u_b9jerj~WuksiZXtCb-AF{N{rn=Ciu95FAGqxG;m?3+d88g^Y*y1VG^!uv|p za5Ii`ZF%O)b`q`|>fj|Y=dBm6xBt*@GQOOI`<&xX9j}j1*pDs-U*E#mtd9K1#H@~i zPe`9T82Eohiu{LX_?L0WNYBE-{GW_dHpc&CA1b-p7}1GZTR8|D*&EpXwsEkw`==&V#5KG3Vp;2Dfoi04 zYU*ypys0TWNd2Vw{|u`-!<2|AX}kpt#+|Y^SC3gYG3jxCgaAv zo5kVK1;8V-$>aN*3lcF)D{Y9vqf9fhGX7v$TaaPm(V2rIdwKjc%O{V9ixr2?sm=m> zF{Zs)*4lyFqNw9D6ir!2VB_&0(KNZ?;M882iy z$mhtx5$l~oqOQ4@eY&RUeYWFtVsBVhp^w@K9!9{nO=Ij60;d~Db}lqLUl0NJi_vk< z%HwKyb5Id-cpFQ4G*g2Uz>fgOjUf%I!_?C4=GydF#3pDuyt`^T+#=^hD25I|d`%7v zVgRu&$_vVRV1L^*CqQ?GEf-qA`g^C;HQD~-ahrM`td}oV=-aaSi1oCTlvl7l z&2z`#$dyw3mfy;tJ3rx%=SZ_#+^2?ZHrL!6(uTpkwgMB&uVSAUQNN~0y1LsU-*Cvg z0_m`xm4~cB2{NCLqV}2&c6qj~@IBd|YydkpQQ^Ec$dlCYn>Vg8{h_|GeyNYVWwS2~ zQFke`JtcRr@ue4nFU~GV?>?3Rz+fk0211A#S%DZ;b`~OL z7G@w;m6eDYSY`wwR#{m&;8_16SsDK#U4iv%%tY)AK>X`J7*^mhfMsTS24EhDaAjpA zVguH((gTmh48*_!ABZq<0FkfEz;>*_HXMvV)GP2h=sAekSviPU+3A6k0>j@*AXAos zm57yzfrt^<_;0WSD_Q7)3|K~HIAHvf`}_UhgPDT~xG(!Zc~%aFe@?&zyfLP~7yQ54 z!!i9m2RqZh)%~TiG7zx=g9&)^e}j>p@t?-ppO-+?P%R^C1adEY{YdDy z`OG{)W6~AT(NRHPgnTLLBP)=n7l&3sVW4sumebL4{*bexmzS|;#f^c7M%_(P?OyN7(WfM>>Xt>w{ zrGS8Gd=_Hk{rnAFVSI_af$jQ{i%S~K=dibLa`s_@ejJ&+MA(X2_aek*yy<-`I`Te+ zx_-R;nTv}b%;%85_Zn>FK!40v>>Y>pjz@8PibQ)<%Q#y2NK^@BV4Xl~6}By|_5E zh!cZOD|YL9mzhv{VIGM0_;Nk8M;he0)tOEob(2{gNu5*XV&bv-O+QHo8PJ7_Iu59_ za^SVHVU8|&Ls{Kwigot>WU|U}>0Fupy=q-EzXc?(|@!%HlDiIRTGkeQj?M=k~b^q%Ns9Slh*)Ksxjw)LFDib805*tnST zkfIL)W77-wS%q3x_oyt8%{Tsvrnmj!O;B1F0GfXy@9gf6ZpM3T!xUEvM^5#ul_<_{ zG2V*lwY*o^lubPsR21ag_&i-U>opE(H=^UjCbe*(AK^_9b~dX54%QCF=g2#`gJ`2N zi}A$1p|lu<{Hm`Qd+qjJ!_Sov=++X`yu|*3`D~EgE3|ZoWOz_+9D;fnTQlAk`S7mb zW`#ORP-9XMhoy=fMIelwI!lT$~H9h%b8)qThg?40M7v2)`qtDhLvwRKR`}%I} z67%=|c(|jRfP4KyExRyCAe{p?hjtP2Uv(8S) z!%KA&SYdeE$s#P^X`iu~7aF#m`iD|>qz^+xaZT)fG0`TKee48#>g+L9%dZzXYOW}* ztB9-+(CFlIdnHmXk@C(+?}E}Mto$!CE-G6cN$4#hY~y2E_4o@glJ9x zdQx-E3s5k*?b{5EF%s=Ca=3s$G;*!+fbXaWZ+^rzgqDFlp63S420@KqNxhUP;hBh{ ze+2CH?I{~Tng$w}-l>K1z>8EFD^OQV z;zWRhJk_zJ@h;tP&orXeLbmstKMl8`p3&zs*lYzO%Ve=>6&(VYBl1c5E2eQRBvA|j1gh`Cddk~m9Bnff^QSL%}`{y1ekHhr{D;7AZ`GZFQQ9pLKD z#{KA~T(srnX56zCkp7U`h)b4&ey2#hb$`qw(9M$Fch4w>}*N#>3b2RN6>|$wI?$-_j@=5lA=cZ*YTQ z3@N)0@T7u+LaZ6|`sngV(GJTAg6nhkYoI2ptNhgX>%-Ogq9nKtVw2ocp+Vve(i}qR zw}O7Vh(?6(^#l(KZ+>VpAgSR_a4HIoa*EW1XNU~512Y+$Ma@+lol}y`-bO{b^r4lh zRxBAYao1@PWP0B}lcn3xb)+sSupAN#zl$lzA941OK9^Zjcn9o|Cw3GAg7cU8)SPRr|?AHri*ANz7>q! z=>iIW|Mk5EY>eJDXq`sKvbMwhRrb=?-eXQ(A~KaCwn2AJumAt zwd$qt)dNepGZoIJELr94kIC>yw!PhD-8>%InGF3<5KX+q(w{OiLo>ZY8FDQDr0ZF8 z!1)#{9+0Pbk_Tj6)2d#-CJIC%vQ}Xik`TwE^0K(z2N(z-ov!*V40}+2TB{Zs$f!Fc zvr21DrdqB<_Kur8nEmM$F=g3pz(OMjlNYV}ma0Uq2B#bz=x*jxH^y)XtDOt&gjK%$ zl!U*ic?w{QTA4X9*8dqcS}``3q3pMqwNRlOqaW8{M@r1s68KKXQvTRr4}TCCs!4jB~fqMVXhpJK;+p`tgj*z)X~4tBv3Grq~O7eFrz&y$VeL`HILp?pgB%` zZ!>)$S{qV{A?|Vzbn8ufB_Zfw#qkoohfc$-sAE?I!S(=Sna*I$F-b(`E7T}7qI^cG zz@WQo^-Q^Fdfnj!x-wWIejFlPBPHiiT|8*wbG0~%F{x$(!JlRbZ= zJ*t}rr6$**pnIzk|;HGk0+NOE|_NF?8H`5@3H=nnOCjM4yi^b z7EUAM6UwJCHEd4tE$JDZYuA$t6jz%=His%|D>2MnjiHEcKf)u;KS-C}WIYv*HSseCUrYl7k9=&Mf08f6_}_kKaIO1VOVf19 zm6vom{+<xnhuJdy^Sv$jv3KV2WzX376nn)Ml9qnB`bCNyFnnIIQER?abC@DuHiW4pv5w+^^JkK3R$- z5kbNwiCI{OWlGa+{nv7JTLGVJ)(?5Ikc+)N>n2T;IxL7VL<{N=Vds%f#jm%OwQZoB zvgY$lwclhJVE}7{jSOubA3cu|Z7MWy4p*RaTvc=ISE#V=yMBX+>;O)6T zw7(>SJeseNP=UTQuPR3mK524kp@>xWcsjNy5R{p+Rkhl1V3ZXMbOZEt{3X}j(8a^H z;!rNn3frY|R+YC9Gi*DV>!Vwy8ji!h-<8=qLt1dVot4G)g``Qf{b8>nP$;!SPm=pd ztj>Ku%HKBg+bq`)q9%flV@|>Z>zWFC7UkR3lmHpvjGXtP8BM|>E!c9CW5J;@T+Rh= z^2V=$?j>g}kg3}Kij%ligfra7kp{{P>_kFh{;SgpYocy$cHZsczm6zMcZ7sqcZ3gY#t_VVtM}ZeMh;etcnitxKr?yeQ3bHgw< zmoL=0RtVrY;pb)V=^h~f{kOjx84?rA*xy$4lFlC+HzHI=NXF8Ie_OzW(!?}PiG%Mp z8pLV~n7-3!YKc>~SBI{-3#aRT2%3bJKd3syj*O?2XOH_Bo49hzEEGy3e;DP#5~N?* ztT~0Qxp2aFDZ~iPa+()0p_+fHUx$xAO3LFqmyLp5AtL5e`H|mH?^!<<6NU~HIjVjW z&nxC9{RL4}$W;d4R#vk*ZNCn0Vr;B+Mbv19)&&clD)7B6ZPzcU%4)XC z$R`mZ$>kx~4SlwbWdgCB(t)Z2&e-5)#rEOBbjki!5Up7=<_AHInSdx>=XJ1KiwM5b znN``aYHcgMLw<6rYC>Qj)J?}46yXu0IgO}DZ;m^z$1NL? zjku=P5o_|eolINSC9Y6?vZ!|G-#LxRAEB{#$KAZ%hf1fWK->%w2K;|n#2t-N)`4b&a5ixt>5 zcH0zMi?YZ_>6Q|J#rK5a1GkX0E?cSVx!kF131&gyZO_3Is*p-NE#DGdj16tq>ZV%< zNHwUZTMt1$9DZ>S?G7Fh-E)Pu+#1hgyCk{mPzTZ8jI1x)-wJ6`;o>60h6bmGBofXbh7%9( zW!-kuDyOnpp`kt1@~*{2Q;HB%*5sJ(T3QV&HVn0WJ1n0$EcOo77l5? zVw@pO83?q73&|yzTL$X{&PeqI;Z0hPIH3glMaN0LB9AP}C#?)*Jw3B^-s9v3ygZ>A z&Ayv=O5Ee2PGLcijJPjeLraOYvR|nnuu}Nc(Ia=d(H^+D|By?tvSmqO?t9LdUSOgF zIK3}h$_`I=M_<0fw&kkJ6>ba!&=G4V$=4s*kunDA5sFf^`1`=v7d^RLKE-_(rm#I# z7(qs&L+Y_-Mbi-aQkrkwK?#GpM0o>Ky%()gjL^;StGJ$xdjjWoiRVw!fF!d8%++u} zAZMx7)iW&DNzOYyU+9g=S*c}x$ry81on!WveAJAr=BRgFr{TP!*JZa+SEr7dXT9ux zoCQK?9%x9k%MD<2)i-;Ye1=NK?fQf4@ph7&+P*4HuUUk9(3JqjRYSv(FLevPT8=WA zVRU{*n7ys#R7q7AC3)gBj=AAr9-l$%6m~FFavVjL*IBJ%-`sN!Hp{y~MN%!Mou9D; z2*gyCr&9uw#+{;_x-S7nes@ZBwOp~jsv&nJ-=S;tVxi&bRP7rm1)J=Bf~vU&slV#W zYB;5z^?-+RWFA@CmuAK9<61Y|&VS>2+=})bn0%>a%+RdUS&T43my&~JevmzON#t{V zqQ&G$$pdlppB0myX55caFP}n-k7WDhx7n1uB~xfoc5b5W_4KWhwY4m=N{%X&eiwiU zr_039E7Ov{alhzd)MUJtT93V?!ezk zwnf+cGADY2;J1Hp4!W@$^t*6u5%i#s8_t#=MxwTzh*xIx%Q|~>*pqafBeoXoES?0( z84TR1LFgpjTFavK$;YpN?5u{cqU{X$h!Cuyu~3=gG~b2l(YIu3vbj7TiX`%nC13R~ zSpK$1i@D{?^pKYS{A@$__!LU^6CEPu76D*cCP?r-K$KVwzI(-gXBQ5F3 zE=^pzrh+nvgwEeZdrx&7hp)@Aym;23`9G4+K5^f+Om#0T!X1Y6HDfMiKcSitBA5Q9 zIQH*GoIv@7>3`Ep{{Q-LivCZHTEaok;E+!7FZ&sEu3_UrZHP;)eP}w`Ib}3s6&i&H~gte&qId{dCJ&q@3)` zsmWw^TSpFU3$}qOuW1(Pyo>T1dL-v60nMGo6>-vD2e)4&FK3;$@_1%vt{FL9%T5$w z6khP=KuMxzHGKyTS^jMo@o93i|1`f$NOLRm)sNu(yP;B2FF)=JH_K(q32{-`{XoEh zRoYVSzT7o07Ygh^SjBNq_c0D)XAN5j9Ho?e#*`7n;+uvPtEQdhy~&=x5@czDItmse z@g%9;XuH5>wQ+E}5ihaHI2?ybWej2H9QbV%dv2Ed;?F7YJIogS$(ZPNx&yg!%G*?T zeL_->Xt#zZxfrZZj@#Yr+i>qux(~wG74Ik@yNGX~j^ZI3{{$>Kz4uSQ`e%graoeLF zH-N~LmOXaT@5z(d%0^9ei;YA#-}qm4y8pX}=6_XW|8G6)Ukb879rNEkH2-Rc%uF0W z(G)0%{?$8KfI=(-Fb5P#8JRhN0n|JHwgL7Lpg}7Ua10PJvjcTWpa#jpzzE0849o)s zT2`R=%ESs3V1ZgCGY3$dWddrZKmnEwc64t z8WE9gD~gFtM&^^7>idm<1XeK=WQ13XHuD-D$lnq0z>-(b;thoU$$lWJi-}K0XcO;lDieqj4TNBm6XQd?M z6P*^X;(ht}kByJ$xX5zEPjerE{?+cm>G4&F?(spSC)Gk+guSCz17ibl7kbd~a>PhY zP|-@LA`mDybKIdRG@pw2e5~%}L4re_R%sBZP;ZeB#BmU)9d94V?(025T}b-lcW?_3 zs6XC5_}#hyWE&9dgilae5dU7jZb;pj59kzZPy{3$z=`gyNH$ud4&b-mok%v$A~3V_ zB$7>n3C!#QM6#)%fEkiomb>EccP!7=5bv4d@LAx-uqSZCzapz=>3TeycaT-~vvj36 zt}XUGneVPRF~789#=Gp9+5SCGj%ln4`TDo=Ix&IFpQG=Ol7Y{3e>S>DHaCY?Z?@7e?5W?NansdtfSmy7->3`pZ_Ejn zc6AFBTd6U__$%V8dYPwMcaZgo)coX?4 zW-4`w6Yo4Hnga+LD^Ts;75DOi-}@zz&UxE3%iwRBI+?E3$;wD}Kn1mh7t~`d7dCb5 zfM>ka+DSNWx=uR5Z1&YEjlTOk>z`9uIGv~<<33f&{_0EcYu|z{KOU)5P?UBO<(etE z@X03=+9zVNmtU3kr%8hEUkBm6ODeIcm3=tF41TOWz)&J;pQoV3xEb-3B3Eq&B}3z( zVs6-5TW}`Ewd1K#e%MKiA%I|HHsFiXW*TdgsF%WY zqMxKJdckyrHxDNaP?jo*Mgf%>3Tc(V`*t;%7d&8EW-C4Ex$J{*ZERDVeQjd;uAjGz zhxAE_OkVsk1G+~EDBkH0zf5f#f1a!|@++Y-YCQ|Bm^48f1aOqi`j20RAscwB)bLzS z5dCbzx3gwTv^E5?hZM#cR@l9v<8;cGGze!&@)NlhiW`%6&t9p<@^c=HN>={#L#a{h zcM`U;erq`NS*|THnssn42^mHHDOxQ{y`n@fQOrX@>O67};}6ob`>wfHt~!F1qV!O2 zYbc<$b17U}30)wT-S?xY{O8@;^p2Mq_y^_j- z6;zl!h?8wI4(0j*jT4JssGz$J#v@Tq3_%suHHWRTe>W1Px(6nt35wIuEPE(O#!t;! zPi~*f$XB(TvS+T?Lh40b2ZppFy5b1`m5mcg6@=nfm_z9(x-U-6-LXUZCqYH`NTnyg zre5>&m3uPizqF$#= z`s)-Np>#<^%{%^IHLqrW{yl_>V&M@jbS&`2^6`Dq(ljuSX ztRd^BCL@Vjwq49J82Sv8hK+m|J&-(xIX`7rbugwof`w^ znJz`_1EV=?(hwn2rLJ2sWQ~g#me&g1mkOLte%v>Xm8NFYR~CIEV)DSzpwo+Og`_v| zla>HBt(+cYAT+&MIgk^5yDm0ynB!X4np$oo_ zTj)r?QBWQ^c0eY)Ef%2Img2HjS`w@4fbN;&mMlSRdbS3`_G*CKQRMi~NIN+hjgT}! z!mqG?N^=a2lVZ;RTPxX5C!)fe>d4vp^mwT6sRCUa%Ixu%a8qHHr#dSoeu&%0v$sKw zSAhlb`-Ho*4R9 zh;lxG@!S%(bi7(KIVVITQ}^vV~!=hqyEFxxYH(2HQ^ zZbp?^tA?;(xQ3|hOyynsC=8Pi@Yclm8=IZtyn6Q;yfX>%YabPB-NioTVRH<&dW)j_ z2T82B4oK@dL^u+I{I0^WCUvO zO=UFP&t~zv{+R*Mr%lLIXq%1ohIUW7OgpJHwfa)%aKMH#1#B*ndG5oc8eXIo5 z=#8<0Jk*q6!Czb_L2v(_pUG4`Thn-tN%@|R0|N6#j1Zp$2EJEzOjL63*! z*3mDnSEQ)^7&|+WJC#XcSA697ized8&sz0)sQ$hB2o0NymzV zDmu|n!aPBGM4FS=x}!0RiO3t&yG8lPjUDj?tvH~91$d1;eQ{Ywn9nF^ zrIKB`MiC5_e24}R$iX$=f$0OXL7p%A#OnkAcAwZb^*QO+Y=gR`q<;L@1}KU7R;>G{ z3sf<%N_=vLj*RD>+xm$lPubkc4H3NdGEh=9Qx2H zn8{!qPu)B+r`4|_dqWx?=`3kn5D>LbR#LIqrF+nR-!k%Q{U_J>_1D7^Bo`7`^HPZ0cDyh zT~|wOq%4VTc9a`jrN+)$OofLf-MYXo1Q|prXm<|{8Ga&m{x=vTz;z*?cOS7uy*53p z+EoIL?wTIbaj-qjYy#V+wF^BX8aA;mWm$9VhtPmQYeE?uqH%wSC&%(=eKRK+aavrF z?5$KEsYrq#gc^GYf#*=_jQ?``{<#ws2pQOX%Txpjd(E{};M_dL%c?~^h?`a?D*5)ipYgYK26jHIn^|zv zg&feWqd$uW*peblrKtyZf>Xw#p_$qd4Flr#4b}xLCYBpxGq%xphNA4>MpX8;$a&pn zR&LYGFyZg@N-Urovb*m|o`Ax2yohb5B42JxXhSSiFjBjs5*dFXuI8 zY4Qfxy*U0r<{YhVrv)6g=h!L}`HJx=oGz%|av?xKs^&+^!@}I{)nU$SHnZTxW|BqJpEsuU)ns1 z98fdyBn*w{i>}@lAofRnm3U|7t3y-96tc@=+cibANe#+#NEk93RE_AARA4ly28duN zr!!NTifuVO$hw(g16lMbf{&YqZiI%>eaSqwI}~hbWO>7GsDOz5F4{hsfJVHNZ9&0QMbol-=WlIxwQ#i}-vp6NOky-9bZ-v}E|k zbZqo9`ev&~hB5bPyLlTuJ(EBP3y6{4IE%5jwXSDdP;>Lr;Kn(u%RO!~v`-JKSWx=f zJby@5cI}n8W!WsMlpnzwW0nl@$+tUs9~quY;;Z(_uiU>TSR1QVJgZ?%3@Sk|>_F6* z+xWE{ zrLGo2yfEeKcQEYMc2Yb*1oQF4Lg2g5J%8?e6KfxqxG2i(>wx2!$-q{GQ(K|4Xb%)* zFcVw3h}79QDG(qm;+?3{na@sT3ChYTr9_5I&(iWB+X;BeXE&xij$A8v5U@qq->a%_ zz@r1%qDk~x-~xR^gmw|!)S|!lnH@Y>?Xwb+Q!T8nRP!XR_ch_iP_pc35(Xs4T1MxJ z6NpHsjILr=)qadN4V|CVXrkR9IL^peT9-V>s``x`8HQ0jN~!t~WK|E?nC0b!WokG= zE7-8Fi77A1&HgSt^m#zFVaSsA2i*;cZ}n6@n#0(1R%D`;3%9L_s-^iM|D+q=p>Iau zkPI{fv6(1cee=Cro*6@u5SM=8EJHRq=%KdHfv%3&b)siMq8Rn#AY;3 zVfg9m?fcPYuxpt>-jJVG^O>;U?h_}YD?o-11HB|42A9iC)S!{Js$YQOw)O2c+qid( z{yitAg5F%M+ z=1<8)IB=ucYEYIZQXXyo29T*WoXnC^V?AhFJ=poEqk@2#uyMSE__NWsEY!$RyD%Xt z1fs)rzr^N5XyH?vuLePh9g6q1*AU4RxgyNr^B$?90^QkUE#h-AjS+h~pNAf(^PSqH zBH#mR4jQgt3%2frc!X%HBvyQtzh(e$tN0NbGRc;gnNgvid zT4T&!SHTXpUCH#f)Yx{AB7x#ewmE!Tj{Sh6NjHad`*W63D`46q9A2b$18TW$W$?YX zKZ9Qq-!jN!XdHmZ3J$OrbwZO+tm0dfY9x?Err>2Y>kw3&W`@noy2zKr_@gwS6`fG6 zKaEuzC15@tuKF3+I z@4(^UG;(Ywe7b+2W_M_cx~KM7zuV}xiiJY4zS(ntuyH;FA96~)dYbFOIhFNiyWQbL zyzg;LHRlZP?r}mEr-;NJl>{g}_ea-?oSOYu=2u2&MCYT#XB-1tFKiFp2XD-ofpeXo z+c3n6e|42Cj9w%bzFtT-$-R@2dP;>7VT06PRktvg>DRE*w)olm6JB#xtzS?dp%$mR z)oHCt>_kHAJoiG;Sxt#2=~{K6;#KS{kHn_-{$P6@@%J=jC~hgHf1W_AM4efk^` z$IEZpAd7qyM`)F=ke9>xV)J3TE}@#ac6~dioUl3qPXc#z{)D83ZzSiW_6IJ;E$|Dd ziKdSX-on(!{e|ncV{y%UDC^)(TMhf`LpV8MUV!@Fo{t~!j1+TdKeKU(1l;mv)DF9v zQ}!IWa5kfE;fLHq{lsSZqmR!M8hoL3%P)E&zHbU}64Dq$4J}nM9{%z0j|S(z+^?kpHB=r7ofgOfQ42i zC%)!X4R~s_iS9qY;JzkQv)Zxy+}v2Nh`Z-!cfP6~1{-z9-MbsmU2c-h!_34mS~lwH z$({V3R@qCIfhUuZ;;i*$^3mlgFk`xn;>#kjCMc37m%dv?mx!Z?V(u@SFz!OUCZ0V` zrE}3$=>uD;SBupPm6^UVY%b>)y7lq_;_8bU0bkLV379XfxvzO-vS1EJyOmDgu0e(I z{;-Zw7@ty;&RTjcIWg`^JQiRZH|7`lFA=lfq?!NWyLP3OlcbptH?q=xIU|bQbkor5 z4txYzvE+;sCgMY7P8Mk1{IqN3q)_w0(qv0V72L@mn&|(OE<%&q~@Iq|CCG27Tw65 z^oXS-wg!D9t6ok?{SK{w#`U|T&lMzYiqKbY9UftHzM8VgSdS<%fOPO8;W=$*w@D-K zBaCq~Tl)-$}q!uOQKgi|ayvNe+bLPRx_PC8)4rRb*E!|x} z)QrV@2F>`l1eX$aw_ax!ONwB_y5Q8)|Lg=K#9Y4%I-uE+oGz%fFnA)hdx~7ZzF=$y zd@p}{nZUtv4-10%MwACG7SP?|${>I@%O1S!14h_H%)@*2TL6%P|R1s9i zh}wS^35ZwX7X)pGC`C`@Bi6*|o0v?aADsLlw|qm7`<}NqDe)Us-Gt(xt4k%)8T-s1 zD~xPr&4G@%MFdJxBdEYfybq5=>!!c}|3nE3KRLAFI50$B!nULssS9eQySmF&Uwrtg zAVQp+-MV=!(rtx@oo!h8e*03_m5`ZIq$UZ=zaVze!~?n47$lbYQe&)JSwg$v`&e*S z6zzzbR?VQAMzz4M#ezyW4``-%%%50}&Qva_A(~CYC0;L<040CAqCYN7 zrIW!c`YQZ0>}!|{*|&{Fl39he?L>+Xo-$&FYl<$+5VyjDyi9fxQGYmR9cfRQXLoXb zCsQxPt5d=>v~Y8m?;Wr;H9g-qYo#%J9jkMLOJ&fCSZUV~{^Wvc)&NaUx=E@F6b(nXWjZdmia`iWR+*;k1edjoru^ZJwRq& zfQE725+sTg_8aU)C$eb;6IzW?MZDQmPgH6eGGBE*EE2isr#q|$lf8xkQ=N;3_cYR1 zgstg8(kHO_#%)WDhCM!z>?9*Coj+C<3D)qMDE3WTi);rf+EY!w#CZ|;R>PXi0`Vz@ zCMx;OgPHeskhErDY`~A+Y;26^z?vZ?p9w&u;CDjXjw)cJzA@c_=hh%khjt0M#D0zUN`4f(XY0?0_OMa+fg?j0P&P z3~Z!B26&4R+g9&9uJ2dYDslGk|o zSKV-qzNxl?OhL|(CreVcvF`Nw2FC9f+}ccisFTYnic0Z|K5>qI@dz`&*u^WM zV%tou!c*0H)+dyF5>R`~g(ZeNqlBq*IRbv_YBf;@74RB!5lDkX(#;l#g>6U1%~sy4fsck39O&gWdMT?`A6+L@#^t~)WSZ6&JCYoU|> z?hs3Cuyyha&{cyHftc<&z@Rg`lXEVoWFHWxL6!Ur734mwsoK?GK5VUp=KHe|P;EdM zmcxU*RvGL>(D}+1!{qwwRfbXy#QTSD&s{PW71}B^q3%eGOaMn`{Q^hEBHiyCKo!4o zPj33xw_dGZP}oLI^-@3XluwoR%v2nCCWi9QiqQBOilSeWXA#i6osJ$iLN7CHYp_$J z$YUpz>RH-HG*!&+B1|f6NEow1 z-7u0_4h58~=lkySP<;(}#t3wvR{kKRxr5HVaz-hH%esN}8+^?io&rm>uMAbcnD%2# zZ?)=9hQeYEvVuh97@|5oe6?Sol9bfzvg7de$}F#>MBlCiaM4r3+c>No1{5r%jkSi% z#Z=bmm!u0=m{uJ2fzC`wSNo{LAq@Zg5jzTGi5t6lO)t~%oG&@!v$i$s2O3Nx2ncN zKY8-|6peSK1j|Eddx61|;m_pYE{u_HuZ&yp8RZXC+Nc^@XxzW{P)|j>t#<2i+mBK& zs2#)^5}4Z^WLeJ1dz3Oev>!dktEYv@V(_YqUK>o6+Eq5f?<)By>Cz=}Rga7VFJ{ju z&y1jt`)M9q!zlf<+G}I@Va4nUE_+3Ix#U}MY(15;t%Z=(&gWaL1J((YD6&-_*e%Ya zbtlKMpE8pB7`M{yt7e<|R=?eR5Sw&zVx&Yz*1*V+aiY&wJdGj7t&6Etk&#vC>%J+~ zE{m-v&l;)a!gn`*ktpJID??ZcZx4HR<$i?Ra30(YdH83Y^Q8)1@A|VXQ!^=L8BdA!cOox z4}UNyvTk0jqUouHI8o#3!FTI11uWDZZYdq|Q<@j=n~cUVo|~=vyqgE{ z!O<)5iH3RZu~%Cs60dR%Kepx?vt_MpyxgK3qjhl4N0(hK#hL~;`?(x8GT2t;d`h4W zenXdo9+Fr~5x!64mETURgH?Id{U&!V`T?JNrrCzCj@(}NLRh56SNMTR!ZCB})0VAN zTNC-~EGRU#aXm<*$$uczuI11_2_~OirK4hZyKGn|?ykH(ZT|tT!4?M5{6`n8_Oj@B zae57ko^dfbTwYPSQ{ncpku>%-Hmfi5-aK2ZC$D~6y!z#+kNLA?Q>Ifh@49tx0sHuq zwysGykZ&niePZYJ+m(9-%Gg(*x>0e{si>?iQu^y2Wkvn^jH%4z?0^CnCD9l`jLS%N zxo(|}8OfC`XD!pEq>Q~lS2 zIU`4&*T5NGzpmSGts!x}0%h==PM}J~P|RMJHVUnfmhLG3OCw%R#RU;j-!3Kk(~a;Z z##btBh*-6+oaON&87o!nR;nFN+l~o}YE!F+a^#!$ouqm{#dIy#?{UZ;r%wai=Q*j) z=6l>|KX0yri2f`}5fjT0$9ry%Si7~{d%G{yrj9f>dX>r@Mvi_jg7bjUj}Jn^{>ol2 zHVhhmlv9IQb^Yg;HEG`r2Q-durPXHOgR?uH%bDEX*md*NHI0Lhknuw0B`@7gKKZ^b zVRRm)9rN#!vu|u(CDhvJ^S&v5lx`;0W3yCS;5CLm-yGwzm$kzmGilNNB+g`FJ}v~c;~FQ2OalOV52#d zBI+%9H?m@yHdJAFE(<0Z5}X|q(WJdI%UTapWLI!TzSV}e`_&c8v$aB-Tkl@9Ia$hK z$vrY^{tlLVUL28e^h3Tlo3)!L55qY8NXmW63?{|38yuC^_U*>i>hCuTm>L&y8cvd& zcL@l2B;=lB_x`r8`;)sd`*=07_74r1bR>5>atKs9AbA}o0#k2Y)tO;>%Uh=G#eALn za7e>$!A%@=3ln0!UahGO<&p-Hw~^%*cOM+Sp6gBXfZk{>dRx#A)xAtzJ=Yh8H^#}nW zsS6+7(qBcz|EZDVj{j4*N5&N4rCT8zE(e#c^LSu9*cW{apT3bA> zZ%uix`RZ7OW+5saGw~g9U1dA&6yGZ?$f{TD?NOT8BauAy$mgCmyr%1U+nS7^%TAw@ z^v+PArMm(=Ek4%iW>)QW$H+ezSVd);Pese#Y;X*9D^VxNy5*b0nj;_F^ZIEzzSBrZ zJ~m} z!_k+n-)ftE^8TLeiNYbTBR#R6Dvdk!zYnYG(h0riHCUU$@jzWt?p4^K$8#TJog2iI zuMUqqfKzL@hG*ydmvglxz6{zlo+eB|X-2WOC?RQ;K=Evi>76aP!fM9sW;Dkmi|cl= zy-XB{z{2Djj$i$59rB5ylC2i0@@Bib<_`JI1C{EyeHe79##WYr)2!3gjA0Db8vera z&57$L^e^*oap7!)(PZqgHAcLU+dV@)&QMiXZMD@(;PCm>o#{2K8k9BfDW5Thz7*Ey zihbgDydjGzf@_N(Z;RvXmMzxuyz9ORtv}29L}Z(a)yt4xwZl%YzMVRSRAN$o``I^< zK9K!>RF<#z&~2J0k-LSi-LctJe6FY=@p0ZgnUs))_SIBeFKvR#nHzP>UHT47ij)m2 zc0At@cqlQ4`|U{fxH@Ol@r#^CEmT!2gYAX4s|;Rw=%M{$f_lGn^2fs|l;Y*aL840K zsflWadk>Y4-=j<4@_ie1hfbNiz(8zjhQaqv`K0KFU+f+@YwjHhKSFaYiLdagxcAIM z?>v!nPHu=Q)&o~R$ND;5x_SdUVjXy9tM5bAmRzmIiRz@6Vs~C+%F3vVv!vx@ zqY+y!d6m8B*_O!}o-1pRdT;HXS;;Rmf$i0l*fj#f$`O+H!{VM?>DYL~Z#FlZ!^-L1 zK(oNLZ;yGMtH*N&=sz-)Z0)}?^w=(zS`xR1ivBzk%9}TNO_hkY^7VI-xiHhZoT9?` z<2|20CwLh@Q?tEtl<~|hySgMd>Xh!yoe|Fsn6d&cP+46O!R#r0xXZnw^QCBC*7`~t z3FA|;Zk=z3Yv(K+rl{!;bu2Ve>`69xW1=CRTy2tf>m9F*>J6{dC#@e{gGUP5w}tIb zKny){q~UzVI(EMA+4^aWX~wCyvA4@^=ldt{xIQ^;d>Y~P4#|t$EVFLj#zfhppsnYk z$_0}N&2fci10^5#9sVk?K7oI2ZQFEP+oLPIO29(4v>b&?==d+qahX)|^gtmDfsnHW`- zD-|KrZiNFICatn%G4*VFxfAtHz``EUW?s746<~R`ti_sI&%mLFH9U!ds;k}!%#O$S z=RQ9ipC-p?rTpYl5tR8Reo2NwK0h4RQPu;RhI>@)O;@MwE#7Ivmt`7WI=tEnWdga)U|tBvtRXT z(smz5u6dOj)H!n9pRbsez1K_N1kVXhioJ$2*n3R<(ViF4=RMY)+d#qPr_)o}Gx@D2 ztesOV?NYqd){QgoOt>aoqxx32x=_{>1;KnI-$lrcJKR0CYr9luNR?jf{r*dhiFqe% z1Xj!5OmojD%X+{^$)S3^Ci2+hc=_1O_?DDI`;(-5V=p~FB=4myP+)|d$mymkzI*=q zHnZM3#msEWldGFT9J0M<;v@F3Zbunf&VT7=s))+X%SySEvB%=YS4!J6v+UP%d2PF0 z#tz*%GTnS3!&fSAUQ_E{ z-M;PI3)=ldyW)Ia&N=O`p1aN4NvX_t>s{aHr@4C(7eZH2`abvKpz^k7^E!OCtZ0G% zJebMeIb^`0;bj-5qi_5-N7k$JY0gl z-5k!)nqz5SuPF4Cb+z9H@BL-o+pKrJ z3^|ji@bsPHN7!B}s$A&`&~CCVaXHMfAtql_KswvJKI>!bw<4n*v3Zhy)&^q_35s#1E<-hB`KBvJxd-_4E=!J5a2r^*p zzJUD|Xilq<-R^@k>AFwN(gG5Wb*wi&@&1J_ebK7kQK66N-RCxJtaZ20dFPIHJbGgY zx3=9=%HZplldnJA^*HFYK5)GVgFTzF@_3(nALnPYGqggwj2uUg-0o%WS?Ax+5kk+0 zjW|v5Ro3@|{C%z-)?Hh(?cXt+wLky$g4lQvMREuKo?-DggYI>`CqG>tOT5j@ucLjD zD$>g!NI8OSji${yQy#VVdZ{WV+lxeKo`2mG92?R-5V|q_fj;}W{%=J)G7Pqz@l5s9 zjC*%5IAnKn#akV2cJ>WyUU378nXMz|` z7rfUOzr+?=nkya?aK&bf0id8AI$?Qsl6C4l&I9#USLTia5*KjFB3w=)jB<}`W%xU- zG1fJfuKWhcu=bv?#lhaXaktK;2xuZ)X7#;G`T{b97!U~1T1+8z+-0>V2 zrAl@6Hr>1GV9VhfsRC=M)>72P_+ORUbj+K1*nSOrd5^;ds$c`Xjb%<|W?C^%b3Lil zJCVxkt7Uk`Xt#JpKJ}IIKkgIL0O$NVu;GNPPsj!~yXw!keY&?EdtCf-Qd)CcaJDQb ziFLQ!FItj&TS<%H7xG07_;u)mb?|F`K4`M zq-m$pR3o+V&6v{8zNuMJoEPCA$o7Pe~v^MAoc8z!-N*`&ZSFd`%?@%w}t2GU$ z_m_Ns^OdhK?75b*VAJ8`H;Tdi>Y}V__Jb0BNT$uX_1$Z~oX0i?ylrUTyZi0sC!5OG zwjVy*1L|?wU1aYse$d3a^&*d%vQQuhmo8&Zo_eZQ^S2D-{ip&XIou&);{q1+(6Kjwb!ir9vf#EAx)eoNfo*q=B!a zKOew*GdAI+-KCGmgEkb|gEP4;b?PNE%ELw2Xg~OtteXC|lg9wIW{+1S-^d_4T=cxln7DlHQXy!q3)G@0>%c0|@NtO;H;;Xiz`Wt_isDe+&fXc?f5okf8^eEi_ zTEbI?JUvR%!PaakISOQ|5amXJN_~7#H9a^~CQlHCS)Lp9S7wwT3{9LFg+LP5@5F!k zv&<-bx(P`J3VHob6cX`onNe43?fW^l%1-)GMU;e8Q?$N3d^rh|n#4PkkUY7X)%%J~ zABA3}&d0AcFXZ%6Lyl5j-?7>3c~fg`W2nMBL$aS-h|mSU4KA_#@%su=x<4cB8ercP zn5*uIyE;caYipk@K^r+lCqaa#y40;HStz=?7-*_CfbW_?ud_p1!{*NTn}fX%`uDrcA9|O@ z&0JvJ%C$%QyKXwG`nRBYBSw=um*QpA+Od~u?wjzJtGo!$e)|ILQDIw-&ZEmbJM<`U zdZ%mSi!F~c&HSV@O$|*;kG(%uYVNltL@I>I?alg6>`|RV9!50&H50C*k)Bh+-(C%8 z4PNgwQmFk{znOVnmT5kz@=@6}&#A~5l}%(P>gZu2Z`oDf@h(sn;1AKCJ72m zLf;|bpqM071rxx;q5upC7913o1m6jQikfIaa33gai2=!A7*HS+4JvbD;aIAlBzEEZ z{qkaypxPyAu}M(flRUBOUyDt`LBUHDaSCFOuD6fIvv4uztnU$gRRXr_rVdb@;pnE^ znjI`4-taJ~H1e7zZ)nL`iT=L=i89x&MRv}|qT za=B^$CfT;dqSgK}#uxi8+0L-2>h_$)U^9~=UEau`xOWe-_a@S^F53Cii{>k=A=H7- z6{Qld6eVC`s?V7^r+03v8M=>7p8Ix@adJ)EuEPt~y$7`gdgk}dM8$Db8??O5OVQ|m zH_V~7ZM^T0JNMS_7WTKV-DwV)AGP1mQWyLD;DX<{z|i2uuYT7=qc6^L&qRsNv8}#% zV^v7p!K?3CnnfKI3{f<5DX*Gl)|AA@&3|y8j9*Z=ts}nkbLi6zmuQbT`r2{OGJBX# z$9+(FQXl*xRO;!W`=RH~C56l{jO}ZeX%5XFdij0CZPZj(hBG?FkE^BQQg_~I3JR~z z(_UfwtHvd0Vs85(QZkiA!@OdY)v?=?zi7lADnTR-#-z@T)5auQ9>2CTDd@Az2aWN) zY$*b-Y94h^cwL(hbUQdXHg3gCu|Vl{Mof0wb3t|n9>ekMv%RhzkNdgPQ(QkVim}sW z^@)`!*TzcDn0!IB$jx4p=!ry~YuaZ#QZqih_af}`5cgs4K6>wPx9oj)=tfv?bNEVI z$-Elz6T?0OGbLXdU$M<6=MqlrwN{c%@x6#$4>iDjZQI9Vw*=XMqzq_LItSNhV zZ+_e3@HT&AX=bdD=Eq^a%9jC02P^xz-MX0!XO9g9RC)DXEM}V&*3jzrU`ygddVIm& zYF`uEH65{i*1?5G>rTQGR48vMqM`PNCU?QUiN1!7nrl1e1fHkig5NXtt#+f|IdE&s zE3F>yfg`W_<@|XvOr3T3eJKjFgv2*{rfDWb?oaBTk1}KEc{fu#b+_Ryou@}wtt3~e zl!}`A)YyKnu&(Ds9@uW@ z>oiQ%O8&NIvLmHG)kyFuLv9glXsf|@pB=A94)ez|zDwKhGBqag#gAP}@N8P_cj`A6 z>1TLsl%mQe{a+iJ3ynJ7C_O*%t*gL+Dye&Th9Y2VvW8xaQk`aeV$m>ot^Pp6+$LW3i4irg)kX8% zzBKOAjFGp`U+jJT?X&Wi1esA8d-whpw5xX3-3*l&9T--X!y7jPph4dfiY+Ib~6j{X|%DkU1`P@S&=CLT25)`F8 zu(i)Zoeend2-r>tMK`jy?tAKcJ)z!yScuilASyJjfa!7l!;=gR8GK>F1A%54%6x{( zRSg2x9Er?9TkO)cO(%I?dd;tQN%3)Rke_ zs(!H3C2u~a_WkAP0SZegZk9E)YnZF*0`>-NI%ab0Oq4c!HGQ6C&pFAc2ZxNr+?y(_ zQU=8aC>=4o9hmmxuvZi>vPFqVU&macqBg_Dr(i$t2&B_J>Q3n*bob)5&?ljLGx95j z5R@_HkAjLHGM{|BA$3f&{p(EhrwF^P#{0v{^txNyxtU8nZ=~pjB-Fdk9gn%_^QQhP zWs#JhA=ir`+sdO_rzdZjzR2u7?d@_?q5iDypj}yh`Uw^JquuQu-)|+0Q@iiGDC7~c zn>(QYL?~T)`E|=)>r&2ex>l~V6LzY$mu4Lgz6o+0Kv@eonibEpok+L$dlS%JK7TCv zI=9A-@u83WL)61CQQ?BA&ae#==Qhwxq7phcv_t1VUYpMn$i2@_VxhTIC}ZBc0SDPBiI?A z&88jkX_haP#naQ#*vBUEXYV8IP|uOvrk*+51#mIR8LQT^23p@ z=cUgZ^l-PH?N3*Z>!GFdRCZK&nxXtvFvZ@r&x+C)gy6!81xX&RMKt ziu3SUt(doccdyrMj7+=V`c?0LgTAfdNpW9 z^u)a?9&bN7aZR_N_?)_w-jNWUdT$xjhPwA3-a68BHrq2C96R3b)8ty)!9BP(&Nmkq zCDiTkagtsC(*ZY~j^n^-sc`Dd6EO8s+ggpYKG%Sy5GZf2R+LzK`m)IaGb6B`u!K%qSCEwfWaD`)*UZP7c zb<+5!zQlY>-Thxv_P<{OIXeEyMIuG3E142O~0u`^mZ&>==E z&|N8}vwhf;v3@vqp@_Nzv%f-`YT-VTMnHZ4X{xe_%TX z*w}(lvhw&@~(Nmi=75-Ruiro`$28qLbIM!d*{p>+DF3W`aF(^6%}57&^$of zAE=$4{>iBDLz;O_B!78pmWz2iqmlnu&a?MZp>G`g`*N@yui589raq!$lH5DoyJl|k zx;ns$M&>=oA8DvWPj0^Et-yV1M8&!s8H;O0$oD+1cMNwqH+*SC?O1oWX=Z%b4ztgC zsptJM;ci^+`w``G70Kcu+rkax6%r$=8Pv{xJ~43HX;eX9`J#(-*OM^ueJ9orl!6K6 zBM0jr9eLEcH}fe=y%eoL`~l2?5%mv7hl?*9xF#8#bvwM;Iymx;ta)4|&mH;c%t~~= zY{6lD1(qXOl{^7u93yY@)qM@RgmfL!!lsyYEgvd%9eJdp;KP@pP;<4JM#MfZR`<2o zz7cC{MV5NKwVrPx6+o^=-=zG&YOy^h=n5<@^o|LQTDI|xFn<_nZn`3#r`F~AC@%7T zRH0?mUc)WLQe8A3>zS{5?3vC(2V+-nk#AcgGFV~J65AbdfBO`Y_TFW2OP`^ZDu?;7 zO1+bDVIDlw&b^0xMD6O?IyMOmtL*zS98=63yrV}q;_zM7z$bh;hm~twX>Z=j)96A~ z=MP-L#k`1EOKYi`(UV=NqiNx(+r^rzXBayrn^5Vb)uj)1iA3N+BaUL3uCueH=T|YA z>kVB#y6fhIU+|F+a(gjq$>?1tn9X&{_)iG+9F4nzJAJotNFiF@qCbSzQZ063lGakA zbiyv!nY$)}FK5U7gI)T$EuRiW%VG2$R5BbWG}x1~{l1b3OL+5R+FsK^Hd;p2_^+#j zH^q;+(=uLu=O)>ulf7`ElJlC?RqtnqJL?7Z7FK*>-y176UFg2o@KDn9gYS*7sO*$J zP%vE?=(zwR?sNxwnrD3-?I>4(^T~|quWN3eRaQNg9=2tJ?b^CJc3PZKbLb|04wpg3 z`>HQ|kA5%-DC2cZJ<79xSbx_7=2=u=T#6vZa?|uCO%+l4gsn1nLf5PrxtYs8XLx?i zq{hA$bbb)U9hL;&H_-k4#D7oWRuui9W!75BsBui88x z4X$qsf4Gb4yg~3W<*g-#!yDQ~zWR*qXmhUcHpFgg-WZ}I`X)bjwQ2DTMf{w^0P0|f zzra&V*Z2-@YfH*RegC|v!o8TUtVYK(lx{CX6?hFaos2HpnVV@9cb(6Kt4a3)>xkl6 zGg~-3XsDybs-=r(=*HuSSKZhbF8#-?vl6{c=n9I)7LZO?HJp%lJ9uyVb#4d@T6vqrQnEC+hsRhG@(l74R}XG;PtK z6ej#FtSvtc7^N*B)r67ezSbSsIf16S7w^h67c7(AEb8WyX2j_V#!4GmW+=Z&KQ?HG ze+|)fwNuI{6l&Z4rLQ9i6saGd91pzR)6!CUi7KNsMUKu(jgR(x;O={Yr?$7ulwWd$ z-8!3~doV<1O}VNAhf`i-hv(&O6|#F9wqJTGd0AC;)1+0-U|3<&?F>nqjg^wVaK4v} z4K4dF*nSzHc0Y3_oBhT%yWV4aS!n`=O*-dGKUcoa5nUT!w~GFB{PFwg0%@+&k}$>w zw}DqT;Kn|__9^kgTl-c=)EzlQ*CYdDvZisR`L=F%Z&hYvTKa*sQ*YxrwQUsA(jxgX z(+u=WK8l2&STA+_IhUom`tzZ%`jLTu;~3v|X2dkgAeGErVvRWP`-b&siJ4 zo;%}a)f;Ws|5QtVuL0fWK>i5kPDSZ>I~wW7t1F+aHDv!1eJ*m6WmV;Sg&pp`xfM#g zDt7U+KO2hM7iBZGcR*S|xxCSl`{_bBGe7Fvmch>(FA8Vp-WJlyxi{&y_g~G!8`Gh)>f_+nGLd zrua75;*D#v&C5pRo$n0CI#aL(G1&Sk?cqs}D=r~C@&>n9Bo2qy_+2+Ptf?D9tkxzGMR0Q8Aw7t$@?U-um|NmxxJOoyXKqL;E~Bep1Dq| zbN20LligP-sfgdWIeY#qc7pA`&VvU-2hH4Uv$KyYHz}iHj8XA}lCyG>TY_RYrN$3- z>RCj}hB(-8yAG`0|Lm=nE1Onftm@4>GCivwzHO0KHvBr$a9#K6^Q#|@Mm#7?5|cAf zRLoFMzbp|s`f!x7dY!-ENMhIF1LES}%(mtn5Es@e$&DC0Ge#x0<5srnNq>3XjPPS> zXV+~`S(kU1^LgIJVg1Jxx2X3QJ@B63=al8+Sf5(5?X&DHR&&vJ64=w4<2PQ}aLMST zUcYm_`Wo}F&oJj$a9`+Un+|cd>bQ-^u41?o){|M$sF*ySfYGk?($qw z^9^lIf0zDIXypiLa^anar8pHd=M{g8#VKNw;%bvis?_+|ZYAjPN*_rxctJ%_r`5&^7*% zHQh94!Gz9$6UGQ)Sw!idf=9v5By%iI=Zzo8*j#0w~`Y zY|(ALqkEZ@slS!@txP-YUzDTJTG<7 z(j(n4iC?NQf5yjk|B-;UTMS|H25AgV`x-c}Xs4Zhc~>Nuzan^MlNE=IC*O(PY!hQ4 zl~szRXGR@@bvD`1oYXyZz>=0S4?h1o=PK8kwC^9UJBwvy#qB+R{%lL%I{mczBc&P9 zUDKMSNf$QGD^-O$cEqXLA8{K|y=H)*?_t^?YmY( zucVnE^@^6O37MVJxj8B*f;|&qdab0&j{`GGJxeve)j2z|S(|nftL~MOYu9`4WW?3Z zhtKJA&nu3`9iA7sQufGiH}&^3b4SPhU&P9}_U(IRJ|H*Xx$C>-F6yS<>^JASaSrdS z1iwka1GmR1e4xc$nwejn<XCCsvaT9#8ssf)w%ZSYlnkEmTQoO@3$ z^a^t|2^YsPJ6o2OyZ0!$eNuW_q_aoH*}A<(E6Jv(h)Hg~aVqSGUg#}C);y6((=qoOQp`LDi{X^-7HOU9xLCU{3JuWZEydB|Hqiw-J3*t4ziq z%bp{|TD$j-bJbm4&2;Ov*z^b1JEyjP&{og<^5{OD&(5dlVV*n6t|vbQ3~+3EuIO5w zP;FY>ZKkzTO)TX*-;^bo^4W5lopOPq=fE@A{B}pS?v2CU*PW>o#~$30I~cdRJ-$ue zv)Zp`Rf})+*W&H-n-ARE?|nk+?s=uEpmu#um7J4E88uBrULJ4KumGC|TK@0;!++!%V3>7Bn0r>??;JW}YCTm77>dVSJqrneIJ zF2x*E$-R2i;S6UpeE3;&w<4uK#rHVwNYS$+8XruV78s_G*T?9OU#MSy@#N066S-oI zp`NP?PrIIUu*Aa4KD%>SgonS)vWRiv`@HIqxi{<~W8>}X=nY~gb+!$QX49{yaSXYo zthy?nO|y>S>RG;H+P4gzXC{gio_p{zB3u2?sLtvZNv(DA@SA5b7n2f>Tt6S-A0E;; zH+g98-L)sBx9^yFs=YcQGhK6@S0Utu!ui~^kk{$w8>)AwaqBwDynoEY8=~*o!(U@w zS6mYl;c4!v8}-DbASy4{`9S0YkfBKs*pWeRfKm6tVm(hM+ zR~^?rS8KMn1-#~7en|Aatj0}D9d79gZBhA6vm_snX20lX8Q9sNp^1y!`MQ=tE|xbVk&_l#nQVu3Q`?1aXTKGTQ!#qg z*43jc)}$}`eBqwc@k|w?$K`X*z72P?+U~Z-q#H1bslBSa-K!wSz(4#sL}YbITem~B z$UzR=z^i(%HS)P!!c1b7!$_J~qiTaI1Xtj)98k zs^{74+M80!=7gSYeeic06Qm zWqI5MdJyrm5|aoHIDUPHWF?in#v}squPdox5;kYRNr*$!+nw7)dDY^v+s>PpOBE#* zigR!!&@{+1b(i~hz-{zC?+S>VEd8kD(kklu@v2|XF>ghfm(vA>qwjW8<2=>P*VnbW z+$nB-C!KWm>pjlSwpUDFbo;O)5tS^_I}MnI?~Y$&%T3v+%x)*}(8%=r;~o1Y;%`u} zUUI6>3l^}DjY(DLt^8(Hv|*Idqhq&ZxT|ND$>|DC<`CQCl1CV2)=o^caPOV07d~g4 z9~a1}b2!)Q_|Us(&?5sL<;89}whpRL}Jmu193a$7D+L87vZvOs~r$|3%kI3RdX z0TTZwSfU37A@P5rfI2Mxi3Y8U_X6d^E&d6P;{00AqzgbzGOu=Y#1!cz}cdI?tqqQG)7 z{sFv70MhYS;NU^15iDEdKL~FD3&;2?{9C9%tx)_G;Vr=W;I9a8At(cC0qfNwGu=xH%)BYH53Ec)DOCSNh$ZPl_v%yj}o;3I( zyH`vMD6tBdNlXpIoyC6h=cplw3=VePK%#?#JqU!)#dc5xmT*l_iIr1>R}^AuAOL@y znnmov&ISV3OP@>BEy@h+b|8FDP~VkPh35_tRp2nw|9~n2mT*w47mqdY?}X1q8G$_= zglmF~;3&dK$;199(< z6GOmSa8VM7Mah6;U-3jBmWW)EAVDuzE+PE;i6sO9_~S$oL;|)55r|k+Lr@1Ax?VBz zpnmjni69|3e;j!Niv<_^3PBBi18KZ~i8u~6T>S?~6Z8W_9t4grstch*g1wQ8eFW^2 z{5=WanLF3h$ivV8Yc%)+CG~Sm!4c>D zfSF{tsydmw{ov&y;-n^vfY36;NmvPhV{wZJN`t=vLU=^cKSu`K&JPGCLWZ1I5E9Ek z{>3Z2)-CZ0e?h`4zz4iUAszvVLOj9%m=K@v*PtB>@e}$1(gnx9MUjvMM2*ajD>qYPaBn$-1fy@)$BteP`;RE5dWU~HZ9HBofnIvcufC#H)DuzdK zk!@syUII?b@LkR}1cU-4J4kMjzTMDN6=DSF)ll#JH*AoY<(jmF55Cte$pLTq5QKS#WynEJ=HFNXX%j$*px#R?!4FS= zI0_6jvqQ#`MHC1kT10`=5+d+3HUA3=5PueX8+u8RfAq8;Xc4^TQZIwzk-tNWaOWag zr11m-2DSVmT9CMijVD2*KTsod>YwT{iO`5lC4vxAEfX5_qJKdR@8zMc1a&P4El7Zf zpQD0+W0u)%5@ZOjdy!B0j<5`wf3e$m^UB!Eaw;k z4I|Mrg1ufe69hpK^o$@VVm%|Cfc;r~@V_z;A2>n22gGqu|0D!QKbT3tXi+Co7&Jey z5<~`s7-7O#W*LrTrhX}!M-WDJOKON$kL7BJg78`Fs7pQ&3hMAa5^9HhB_s&Y29yo| ziEo2K`hWDF_`&Pns4ZaxqD~0W7IkmFgWb8IFJM>Vn+b-^_Ithz;6FLr+(-=WYQq+Ksx`! zcq~T-g+l)mhlm{kVajEhs{AjG0E%rOWnS{%5HbKUXjB4??jUjEM=sFk-yjL1n14c& zlu3jox<$$TSnF`6B44wk68N!b2iW>!)ef5IQ?N2~*5e?|S>R0oSl5Px0Tww3ANURp z&cMT8EzYSePHrwv*y3j<)j0?jkz;Y5ozPK0Y9{_UkiZGO6Tl-FI5?V!zxcHwVlwb+ zi2@p~CNAKhKLJH6dm8~s2PZRgC;XBl=x*v@{ZkJNGoaK>6kr*&oPDa>CSOcMhovPQoElt3v01}PHgju<5JFEv^Qa%p%> z3=*;oE9@?4K@6luaEQggK>nphc$4s>yWm4kVvs~p<*!nS#=(FR!9k}1dEA0vu)oCG zFH1ylCQDQ<4QPphuFMhkcW+4W-GAo3q5+w*3Jvf+ng$e;6ekjm#kV}J0VxYfag-|%i=)vI-ohZ<0 zmYf;E%P!HmG?*j?x-u(7pcI2$bY`H;0_ZkNR%rR~hMc)8vq5ke1Puk8CVtx#^f%}? zOFFb1=F)JFn9!A(p+%@j6r@IA_YF9+_lFWKhq*M2BZj#$JG2NBj)U|F2U&U)68=Mv z2r<%+AqM&z#s~=_O@c83%!Q_|mndE4wU-7s#6VYOjF6y{!U1{sU%;sVV+6sJ z0DJfdj@Z=2%E2D&=R2Y<5B+f48C%)9I0%`7y?e%{E(h&hZLIjM9QFfDh>=;Dk@}C2 zS(*9zkC0iJRr`;SS(&-}Z;&BA|NIwX!2bxDl?7`55i%>YoBt6qE3>Ho5i%>YwEqz@ z|CcN34Wa;e;A3CS=>L2#L6t~A4Xzj7WNM#u`mg8pG7Ru;SdStP&`(2C|t|1=gWi&p~AZv1GN5Dtce30Qzh0tY9M zlQ*m3>q93$Wgaw?$-3@{^x19M>rXnyE7aV0}G3T z*FQND;>|?A+*eQt$VMZF_54TJLZ=H1%MG0D8OL&=>Rgce#dKIKu-m0t4L^N3|fp@ zq2XInKU*v3fA+m(dCvdaB-f(#1A8TKU>OE-bO^*BK$Vo0_b1khA7QN^l}%!GDMkQ0NG01ZaeG0<=PtME}^^@%f)CrVHQO(O}y+ z=<~nd+y5wCzvHmL5eATr0O2s$Z3O>q%M0itQ>Wi?R?wCJXtf$j%z?H9;8vtgR`wPS z{}_&d^B`8TkBQJB2{9)Uq~3#bDprgi8QWGihqUP9ft~`k0fvEtDZtj4m9fp$-qF~~ zNgV1}@@As&f9_l>b5sO$;UEkFZUGD@K=~Ui@|WDgU*kstx@3G@nZF_+1`Ys$Y%K`V z0eZ-l*)m%PQyU5V()eGT1S4IrRQ_)){T-KvS4V=i0(%oyrj{$l9ABg0*DWm)hk~pS zaKm5-hk^#^7&PEHAxRgqB0qNY|70s79J#WYErOu2z`SFCQzh);U0HYei(RBTNLHfZ z*Ze&WXden}WkGNtz+R!1O|C%5X}Cb6+W)CLRiwNj1V08!urdbGv8|dCo zB)F6eO0*LMjxSpB>p-E6MSwwI8Un;{z=nX|V9PfMjQ&@!zh(Tv8WvC-U?G6{$F9^t z{g4is=KPKqK!B~hkTme)WE9x$wUVLezs0i1l^K436^J@O1P3$)AJ2kKj=vzXl^Jyi zD5Ro5F@H>SfWH2}>dEieV{r5oq$gm{=F0ssG_D|35PY?wU+*)ER*%31V0J^xv9q%|jDKkX z+04q>6wC}b379xpffI9_$+)?)X(=Sw*bNW^84tj5;bT>hezK%jQ2+ShxImHyNDCu2 zdSEJW<)J4SVF7+XVG}eaS(%py+w&F$NXCudirm56IutZPeiemV>6(Bs&?_>ue#c&8 zfSrN31)+rjo2ggk>VJyX%1kwsgak|>n9@XpN+|eYGqgGQ=h{P>3;`uQg-lgpo*cu z2EoBV{%^!d##?;B#TCE=ffi(o30@69=?(UJ|7&l8Eb`(y-~Vis@ueVt9Yg${cN7pi z*xV1M9f4&gY|LIk5JX~uz?uU|uah!%F$Oc@plT3sDoZ6&sRUFU&Fu+8KRsx0qRxTe z*>CS^Ys-QE1p|4HT2|)n=1w3V+`=3xfNJgx7ObSLoE>eAJ*6E?@zss+MNpwV(*i24 zF1A+o_?oMbrvgP^6^-pJxy{V^BsBLE@2W=N>wzsXjkrV-R3HJ$AO;0opaKaX0~LmX z(ovyQRH$YFl(-8LdY5vpNsHwmK+ZPw%u>qgQa(2RJzypd4W7sUfP3)wLGOi9TcM<2 z2rl&ZVk#{3iN6Pe3DRPJ{0-F|0{21JKgSKQ0*W{soR$hdNx)#TAQu`>#Ul0)X3!hJ ziwFt05akeLLGU!lA;s6qC9fL=0frcWf7Opn=0#+F!aO|F7C}Kdz4&Bfh)4h%4<3NT zC*DKv0u4}RG}I1~Y6!{6P!jwivG^Jv;2ld0!sD{Y@TKZS(0BND0230{(z||*@qh&i z=AP~#dDeM}g`~6rcH-X+;S7Grlw;|8Ko`VfsP-0Ou??bwjOL~LN$Fl{hj<6!04c-I zWU$CveBCZ7Cv#)4S6~r!^pdzB)-67cFZ=;YADg+FnlIgl0-*3@ERh7jprHJ4C`Egz z1kECQA<~hMSO7{$sE7z2B$%|324iS$X(3Q$1`ER=KrSITb6JoFhS&##?St&ZQek2b z(4(nfV1^z>1zxrI4@_vFL1vK!2fhv1ZJ=o!`0qIE32o2?)OVqOL~Q^&@-}E0VflSX zfDd^aRPl7#eQ>bx0T?9WHh>Eb3eAbzVBkKeq~7v2gdjB2Lfi%h?r^BCFL4_T_ebBDrWo;<9Ae8Y%+y zb$J`e2!)aA8VrSjBEaR(LN88-4VYJz{Nme5pf%IACw2YyiE`ZRYoOl1LcDSq4M0z+du{!DGU^_8|3#PN&7S$ z%xghYEF|xPPMRid!;r}h1;_pbt{^#FV9m(z1NB?T@BdG0u0DWaX|p@M%D(E zgeSon0qO^kwc((|*5&jf1ffj2`!)l|PBQZ0}+wR9E3ik{u0EFg5>H%c$Ly+?sXg!%Luw=F!4FxNt&w?PHOyx1A_CsJO4X*NLda(Y3VAXM9BS)T#h*h%9~5b%Sbn&dt(|4SCHA%G5%_Fn`V zSSQkFF)-5c45$kQB3Y9AfP~0=Jm}J7z8h2*fa*vtqXTRzfJ(cPw4unyM_{l)_AHor zC*>6wS&`X9uqcQmdlm~ex{<=gB7brp2qehv!; zXbwd{9pp1Wo4pCMp7LNr7q|lah2}uzr8)FCM5K`taL^=)MaoFR;nG;pt%0BcNwOG0 zX)FfJ;r#n8P$4=n>ne5J+|VyDd&jf#Sv8inX}A6o=wapm-_8iv$Z2q-ZHt+@ZKzX>kHYi-zJJJa~Wr zAq2VoopaB5?;ZCYoj!WodGf1%wDGo6wzGBrU?(Ss=jH8bXXA?J zmm6<5>b$J?Z1s@a-tw!E!wFqPPxA*y;3Ea9(&~#xkw4gS?t>lb>d1x?3aN#GRt^&~ z{g`|1NM)^>dc9ueRM{vk2($yjw1?cCh9V$t-M*V6>%UPflQ;1v3Cseu^5D2Q4OL3t zqjD?jPsKE(u&VUoELZW%i8!<~x!jvJJGOlPKbgflvpfx9AWM0l(WO=EXP*RO0B$0l zc8_ce>uB5#ww@*mTm~!G&~g)|84o$r^IWYIWXm%bzjHY0;=;Luy!Gf;t?yR%;?>wH z>nZkdIVt+w{F1j6tDr@!hiWkGqoHmQU7MSU-k*=2(Nw4QBH`-1GA&&dHe|VO@v|D# zQ%0p^8<+DPk~$akYc}Pj9}h`6_So1Dgg0Mk{K0#jS2Ye)SUY9cJ(J%|yh;z-`56-! z@Ej0BN~$2>hiA3lxz<3Vv}3`rxv9rv1|?2hT^&->MKCReuH|OMZhKAc&(A5RO}8OK zzf+_*eVF%#UQAv%PPu{i+lD<|FpHkxqh22umCZiQ?hvjtUx5yOR+`CQ-4~`vjV0{=bw2NQVzK;fSQ5pjWkzWtAw$iD#d#^1w^|E=zOXFFSOenX%4-v4~o zaJ6x;<2P~o@E1y=0wVnCc1{kC-poQmqWp?Z-d=iko=Wbn9`0^-Zr;oi|Ajfxe=vvl zZ$QVd<6S>_4*pS6m*iTE1o=1cct1?aEU@69t z&=todRVb9A1%;3K8qA%O_=`!O+c`Mc*CTE1eWRMc=>dE0?mT_H;8`6&FY9|W^g$Aq zpU;TV&YyEU{DF3eNfI65N@v1Pj#IUxSWB*4Yle4Fy4R}5i;bU1eEcxW$u9$2b>Ww& zM3Kq1ecXK^j{OZ?#9ScdGJXaOx=Z$ezLSu);NB@V=2zpzgQLva0Q5e5sfZ0SrHx-n z)@y-A8`+{xpCO+wFx+2vwMo1}<^^ubw$ug|zIj?e8c_$BoFAdX5%IS$~~{jf&m&Q%uh-Z~EdI{NA& zTDVyER*rA|GXi6kRApVO%mFbt?J|vd$@aValT>XNupc$`o-ITr2)wqIvW?h(d%U9j zuyV0iS8qvvS7f16gR>WAkvrz_-~mmK#O(93y}R@TFO5K~P2>u^%gFe*x}PFa?lutO zD_4v7+1>b|r76Q70!%Je5XZAWhoXyDIv91+K2ln3nu?4oEDV-p&nZm)F+DnRviPbs z^K#&Uc}$ylOs?}TZWjKg>(Sm9Do(Lz!|*e%c?miQ|D4U*tJSh32}72_ds0nOc1 zJj@rZ@F+dw$CvX;Zr#8}5fST;Idn8I*m$_7xl0};f+25UB7YDo)=Q}RkM*an$PhWt z)n#%wjC4J6Z{4@3E9mVz7e9|yA;uCKzvMcmCJ^|HSW!@3e9?MU{-zdEdw8XU$wTE- zd20*n;#}z#wj!l~e03shVr&8|{7^xGEZY5jFLK1K7mi`rZ~25Yuy$^V>#D|yCUnKV zh{gZZsrAuSGvzcowBR&yG3T5;iW{;qFCVVS`6efPaY|f&bmjHW>E#|Kf%DPAeQ7VA zQsK|q`*huyU80;Fg1`YKH=v)L3uL-8an<4q62kv^nJLkR(gHVphbUUq?Pl1Vt$6|e zOg4W{7XNO?-3rF23N7pb^spPbSor$9DBQVeEScVW&PK}oCt{k_lIe%Fp=;Mo8QTOV zPm;(4ye-5_LRv^QrBIo-?jOlcrchzTUUJ{R-Y5T^k@8)PG76OXCuHxgI{)_g3e`1CI&Y7~A;(wN@%m?)-I7lA ze);&sz#*0NmIO3-ys+^;(m@S=>ulXpK=+Qu^bg&<+ev#VKjG=6&JRn;V&4KI+NL&ve*r42L72;BBC z&~@DPV~ox$gqzHkZw?EL2Vq*% z@R1FyxwHgH$XpC$Fm~0E6wzURk1YOa1}j%<4+ikXzrCbqP%dw`zOnY`?qv-GjR5-5<+!*9+Xmx=hF+TD`ZaLfuej$4tb;as8Oz z^}kpV6oo#tA0px}8%le-8N1{_8)bR(1q`d*Ehd>bdkGd|DdQIw0c-nS)5WtvzgFIc zbV)Luf5yr+sa*bXRhrF@&41h`2XfoaH|IBPeC~qj5qk0(N4>>Ws#vT^Sf-T~?{fHk z#l%ckoBYRHeRGFS%Qwjn+_lMp-1Z;iyt}S zuUw4ldG2nPU`!~j>kI~)Hu*1C2r~V4M%|`*E$lzYR+Vxx)X3Xsa&pvivghZv;lyiQ z`y+(qB`rd+r0d$;84-JXhu3LcEg}BLP)+eDUFfq3f+#djUshr3cr%zd3X*Vt#%Th- z8N4BM(bWl&`Ep7l$hbaUE2|f>USl{{D~l>Z=ysxa<5N0X5@lQMjy}1jbl+dVq9HL- z{B3((aH+Z$AHYNdcaQl<$lGAkKittce$^xPLQbo4uVYw0W5%B*VrxX8w=X7eGHvV{j`Q1MIRMP5B&{kolgb`mupQ%Q$^%a3>eEjsist4wqI2xR1x%zs~Qi)0I zNE{~hXOeLB)xYw_;%a7+(41+0<>mXG{q@s}ryOi7_Wr9swek)w*MJ>5m!9yzww4La zwGK_7kI}eCrI2#V0s#!NBKGNs7%+TNa8IoUc}s>W5SPwftC44I+})BX3KC!{kpt zeP+A;jKitQRHZuuzlhx)je8sh@ju{{5%BS|$f#&tkMrKx(BD5)-ciMw7iD+0J^09% zyqRK~l9J+5x3ek`t)VNtz`hfMAlp#WGhLC!1`_4pR*o;$g#x4MldIM?*KArx z71}fBp+7h`lPhyxHU(RjqkK}kI>iCs0U13Zrc#$H=Upk+L}vG-468OT9&XBcq0({i zu(NnF?+WhTf`THx77+XiIB>K3hndxI#5~VQUZiyK?e<3pxpecId^nFRq~H2V31!9V z(1%Kg=k)7KaGsSQupWFoTw+_>7y?YsFTc%^fa22N!pyjdo(?ps>qkUp)pHLJs- z%)!K#badvbZWFFGtJ=p>t-tvM!0VmZ(bDPsN9Y+C7RAZ|if9^vA%hs0*J#r3Jp5XG zPhhro-nDhj_t>c0g9kvD+Qk~!>(E?r*+7XT>X&_YOU8up(<&Azi*cjdW~9!}q+nNy zIY6}ugC84x)_io4R|$o(DQ4(sOws%uU>JPlqOVz%*iwLXWy3y^6=J%f@!e~%7_-Kj zs$hX6*z%fU+hUjsA|C)hZmISAu&RTq~}i6oL{M+cD79;n6Y`^!`rjaNbnb{jxJ{BBMmu3~UZI-~Z4UoOgLxliw1s_8O-7 z&t!GPz%@$$UM{TTZ`|4ewI&OK8MhlJPdK91ctI^FpVh2?qIn?q_??FD-0J_46AAad zUF+Hca<9IOA^jczHouT@SeuZ0DffcZ1^}mAak}t%599i}d)4*D0KJHOz9Z5C->I4# z15SycqYD#CagZ{zbzOJWu z5y>E0Dn97Vsf>#kxQ{S$sZuyx3iX{@-cM!2pbbUz*yrp`7Te?&SvDH_*Gyh)$3=&?)U{U=K*rKG@@i&)R1`T`Lv4s&-QgN z8psRmh?wWC_?AhRIF26C(Wrx18vq5th0Ls&A)}8JAfV(zY8ww%#=FB4U}oBd1IZLc zP_qkfSu+m>1G?JbZCgLy4~Y)Vr;(HMK^f5~AH5Q%TuL+XhmtHGtZ{<1v0PD@z65hf zZaQwjbhN{;ki*=(Zo2$F`c!JKF0E+`(g>R^Zxp0)f-^~?fsdQbkPktQ^%&>S- zF_T?-A+wW1#L@M0cS=dFN(v|^3y*ct&{d83{yXu-5SvetD#Y+ibMphmtR~SKPvY-t zSkQgx(ZTF*i_4kgc1qD{1o-XA*D-?+lJewoiB+Nd{)6HtIi}@|p6Q+0>ON1RK~||= zEQQPWzmDhoHt{9M#9<~c;vl{vb|#&%x;aB10U4ksF)LSjF`P~KPfTg4ci+U)9!aOHp5e(JoiDq? z8sINZI!S>3pAs*yuq$7jRQrIKxXT?9vdetBZnJ;9!m zy~$^ECs@46VJLr^ULY`EJuMFsoW$56OpepEh)_UfEf3msqFaU zrTvM(hIbNfw}T^h?TwPRQW5ZhTYqo*@~sa3^o~qj;DztV6J4W16%fukv1vKAwdjd2 zeMWCyxGBi9=H5HHa|1P5EvP@x`D1IP?~G+Oh5s?jTN8g#>pXI{)_<}(x>!j3x^)qCEp!8c-WI>ZPoWq-cuSM z23RhJ%|6-+=Jg!Ae_4pV)w&Y4=Z^@JxdY{P2!$MLZHkRg*d{;Mg;$E75G^|Je$d*f zB@;@>AsBMx?-;u4wSD<~12hENs%nO#HpOoI7Zd?>PmrbKN7CNZ%_xEXa<2e5;bTWh zl+_>@CpxZ^v-CiF*GBu|wr8U6eSjQNhNljOhV*f51xwMEqmilczZ;2Yf5OknkJA{0 z-upl9T)dTLEFX`TrYx@|K&GK!P{Lc3eXHhxpXk8|L_e!8ZA%V!z;bPlrKJ)eLv9jj zZSr@4Lht-Vya`G;|f3`vw$c6Oc zxjE#Qn@1x&;%J~7WnbGE$8gV+4@>a+ok&8~WOQQDK3JPScF$0bCq~sfmO??A?_}`d zhF|Ja-VcJJ$>cV0n!?1~Qsxl;n?7%3!Uy*U@ANBX_jsofDTqD)R^Dx;<(cN^lt{%Z zhFz;Hw134ONbl4v%2VT8b^C-@WB{S1^5E;GJqJ#Ec%8f0fl+ge!1@3=v zAzJ)h@nRHNb=fI(_&X!=OR5O0V_4?n00@%i9)5_bLNRVzdi+#SAP7>bcV> zVHuy>>-c8c_yDD$a?vT}buO$iwOUsK!x^c^+zNK!PkyJg*8WL_2*EsqIGBm)P7H;_ zpw}m=KMveTh$a{Ur25P0n#`PX6yl^Yx~0bI-Fj9(+*%2qNbW+l2jR1b)o@W#_n}Si z3D;kbfB%Z>knz7A2|c3(Vxo!U80=TNt2P6Udt^g8`GT%mtzQm`Ki!28U))IWz>9ih zcupYbP4fzF`DJc#WHx1r|3X;n=(KhB^EkG@8#s1Tko!P;4EuYWY+cyb@Q0C?^$GB6 zDaS1o@*b9GflcW&zcgQQ4l)bx#6P?6`@3-r%FsqB7yT6$6Li&~JEmDj)+VWNkJ0E= zmQ7hy97-;8%LnV$e+JCIYfhvl{Eah7ZazK=j1Si}kAr{C?|ukKJ?7N^JbgBD?e;y< zlxF48#$lN3<#Tkx5m2xY>nhLK35tItUk?j}IH=lq)f-xcbq-XJP%Hq6V$Iy_^~W4z$iSN$*&z_7MHMon!%a9Fc( z07Yqn$FSY6W&)dhBmAq53Z6vT(T*2i9U^ah0xFa6XH@O9-t5g6wvHMOW>o$pjRs-i z37K)u;-RfJ?h%oLa61p+Fj|JzxYhN_G9Ky!g3AVmJ=(IKaRLnf`? zdF3s}57ZUrphXtL6H@v3A=B8Hc;QOwd%ZA0x8MlwPtAgO_&eyWgNLb8{ zY8;$}X@%<(Q)p+bWjZ_}4rO^tjrg@Y&zo#HM5PH72Anu=_t*BihvfQ(B1O4=0Zmc+ z=G27ls-;^JAZymzeCsCxzsW`kTyNvLzsPx8e%SG!p*S&I`T~nM=w~ko%QSfwN23hL z85n_|_D{`cJ$lF|4Ere^A_tKJ zHzd0jJ51I>DEerPg|#Ws;P5#&6f!b|uTIWPSwE`(mU(B_ZoO#x%aL8#KtEd|Z42Ck zyyC{3@Y8(I{1@0`VsCK#S^<+#-!E!wa}pR2VLl*tik{`Pi=)SdZ3Sw-J_xu*Y*mG< z^{+lesLEdjDNH(F%G`J2inx*a@_Br5TPAeEc&@S~mL~hqg@sNn0_1dv9Y?zYUnT4p z+kA2zEg0JT@e)2qhQDeM$DeI&vfOe>e=1vxxi_ z=)XB=Mzb#M)kVkAFtZ#Yk9C*7_!tCz zqhn9%3lYQj@t@3Aa?-igH5hFaS4z{vuH#zTpHzt{>E`{X+G-*o7BU&=#Z7&qTy$chQJ!rt_u#rRSiGKB0n9eDp{I;E+PlaL_FZ?$MpBI-TJ23CjV zZ>)T_`hz*q+Q4UJ@SQxj?%EH;SFF?TX5yb$s32btHpOhnvfkgy1mS-#WryS}+=)(T zUxJwC*B;VkOrGY8E9}p)KKm{)u{ZRN9Lk3V7t{&G-pG$qM|sV&F1y+{*RCVJLF-xf z_qwSOmYcyG`@?)yZ*%9?{U=E$In`K+8a3CxM^dy(YCjpU98qX*FBya<2^v@34{>li z-Do!6Rb)x1M58B%!fIu;kEGL7?9NwNl$hN91kW_UA-V!&@MOc;sjRCwDDjMuoqm@! z)oo9cP#wSW^?O8v7RX|Gl(LU#LbX-6@h-2uLmuSgawWRy4DD@`IEBWv$UC-Kmk)Kt z1Vx7=pXq!8fEoexJ21zSOil1hoZt3WdFL?X%&c3z=xlv>LO!R;{;rY$`~Jnf``+@; zzm)gr??%DD>*OFA7OeokYXswtFB|=?FTOR17dB>PBGu>MTp(sCG? zm`qK1$eVVh6FdSLDPr!x!#COvwMnMGruC}F%PotVF_J?C5`(G5&oZjKJJNTTEBxPf z<-2drS0?;^SBgenxbE=}+)5S5ODG3c>xgbjXLecdy^rV18tpnjG0Jk1=M$jM>Hhqv zUbEXN;J4kJr|4sNBa2bs&TKtX@PJT0K3)pqEv6sJ)4y{oBto@#z+zqlbn}Iu`)miv z?%}24x~OD2NQSnGBM(!RNT_R8T4Bh;Z7A!Hrt${6Cnxj6g(!H`!6A^TJPvksIN7TG zV~A;`aTGxIknfuMQx5((X88kxfxuX29e-Cp@O{D>UqbR0e=2;;mT6|*cOf>HV!h)G z@l8R^;Mf9FJszYGe~pt3UwnLrG-n%<055o{ZdAS$&-(-)1P#hq?4rh)AWPI8HTVJ2!qj^+4OPz62znZhHsa8Wqy8>$bmPI z3>94cp)_EHRda^DfzSI3$`>Mej}=6^lzbn;vkPfj0W0s*tZ6lz>4%EW2r=A`Rw&G= zUc!44`YyUgY3@E3saw422GHBB3BH{geZD^-oD@j!a6#YLs*->GTrM-`UR+>_eQsz2 z_2b3KB8Wr^j?_oMT_~>u!+PL)^$D{1&=%S z6DPW*PjfI`0dGNYXVE@)FdMojxgG9VJc&3jujvJM5gq#ceg|F(7B$2B7QQiH-NKh{ zoYj@RD`|a*!ztu5Mp4A}$wIv6aN{kLeh97~TOmOPk4&+$NhO}SW`K1p z*-ZEKk=VH4o#&m;I*OHl+>c2dP65f&e#e|;5xej0zA8%p%?`s(9Cea~+SOVqm4C4G zeBFR{5d@n&E1$hVoD$I%K@8(d7Ni`nHM?v9oV_ecfA5y1WAsepdn{+>2b@b8 zyv72`YlPFWpzZktGR zCVQgYoqrhlCz`YQ^c>h(j$zjREiD z`GhV{X1C46)vSOr3m^ZP*=wHzvVrSZKzUn5euk_!Cux&r-R7JH&XarEJeDDCBo?o0 zN`7?kZM9X6Ctq9Z$qIb{_@a}5vLz;vRr!QZ)s}T&ZuHf3#am;~`N)re;o)4$YLm5A z?HPL9TZ+~gAQeS+p~C!-#>-^u`2x5FVRpYs!&}FsOZYEqC#J~-O?^O=Jc-WsF04cU z9>faWa6=tE5$R5k3p87+Ujd0{Wn`6fG&JTXb_R4+@k<4ps2SczC)NIvRd?PR@Zc|j zg$H*sEM0z1z2Q4cS z;sFGlJE0bk>V&ao z#whHA)xrj?=FQvoFDOQAj|nF{9aGu*r{}k+Be?-iW>il!H;cGi(%`3$C=%oQh5pzS z@|7#V>1zVyo~{d=E!wY>j~44}OcZMC!mUZR7^Z}+r7U^&jca>?Vz7atndrh_?@rj{ zwR#;Bd9~OGGJ78K@s-QeTGxHC%(gPEQ%E2BLY%ixk<1<&THa!;X&PR z&d*$3Xin}BT!$VwWDkdhe!IPEkjhHdJ_%kh6ss2*)*5aCxe=7hjpmJ!Ug$q|$oZh_ zbW*IDU{-C>{=JpzcX=&LS_I~dsV#5I8DD3Ob@F#t-VpqLq$@5`-Y@gzqhI2i_xtmoPTY*k13e(U?onfgDM`k+J>m4*FZCgJ2TKJ(< z1vyBMwitIpYa>T3niz^W-Ay+!h`pJ>R4qDG+8PN^an&?^r;ANL` zJ|C+8siPjpMS_`@zO>D~{i8x!EM=qCQM_BN&1H*iyLw$iPCDRQcC@4`gnip_0juu` zaH5l@Bt4R=rZxj-e3|=D$~~L`{P&5{fu_ev=oudAeBSq3+HSsfp=;p!Va>y@GX>!l z#FqVFdY~8;3MxC$4-iaE%g}h2F-n|?MAL8 z>6iT2EICSIXiSio{mQ zpy24Nr+-Sn0;`s@y*_Ijg~b`9abK42%;!p?EmJt+LTArq`-YgV6OfR*-OZm>f!7+K zCbLI>$J4@EQgXz@DTW&G-?%gW@l5<<#E=jX5dUv?hUCB88UNFw zEhzAhx8mQ}W&c;t#H!h70=MY1RTy_beCj$^cWFhb28Y6XpbZ=4X9|8?K+-#}kbFTKNYKF<`r+uqn)P2Rbd9_Gc`n28H{ZDnx(COKi^@`o| zDE%XVU)UWnzcrkXzk_&&!$aAd!TkDcONZe-(n&De9lTWOMvSu@bkr%Ad2xe0F|Txy z4sLjJYZO<>qGxKI%vIR%m9u_raE<+_|$ye`H3OK2qQTF(`1d|g3bf0aX#Q1`!0@! zft44)kJPj)3NPlTf*3d-PY>)hr@z=C=*5sUAxI`${DjZr;E}^!LBZGsCagbS$JtM3 z=JX-r_R6LxH2Phgz2g|YS~xCQ2dqA?Y`t8^D7mK!+_>bmt`Vwt?$UWBiwjh+Zep?q>vQm93`KK3xP9{c3;oCngO znDBsvJlWPL@}2;rx6+F4L&N^-*?$I(Adh#$F7${E--bn*NpT8y$kdlpRzFg4{7&g& zWCKb4`Zj19>*a*g(lE0Qh?u|=f=IPIOPEnrGMFRnHZB!agnZAE9+=^8quOo0Zm@k< z_;p(-MVx)#-Y`v32=wnOgz#Jt{>K>KArmXY6S_fTm;)@`?X<-5A_ z8AmP?-O9oZKlpFQ$s!WYl|v^kO^+_A+MUi(354N=S7i1g-?wG&p@|XQkB(*pM?FrkiOLT^Sl~gQMqF zks_lhO!;#+hDCK$C3qJ)m@ggix^q*$hsHnWv$tK{+Fh#2Pn`Lt$@JDirPu9kLtC>= zmDUDG+<>GaxH-AtqjP>r$=NM-jm+fd2y;jju{Nd}j(PT6Ts&7|F#A1%@}B&iY_QAW ze9Z^VrKqVZtuOqG3Ql-#KGqzw#_pcHi#cQF&=9Y^#UbX@$w>F3_CPRd%9}d0 z&6Md6y$E4z&SgI~Usoiz=t?Ml_855(k4fPd%V4)}2!cl6zWR#oLj33s9z7c`I+5;U%q;ExX;NGt3GUM_v!g29KrMiXG6Y1#HTpz z;lr;BT?5oP{4wV=bE(9x+~e*qd4D;*J!#1^c%^5T-I68KNoBf~G&r-#;bM~_`f2u? z;B1+oi5o_+J;f(8&OT9BM#a%jFHGDieTkvKC0g;kV{bpf{Pyp`KbF`uWnI4viMSd) z-%}cOV_)xe+d+@H)o*AB-M_G#^XqNSQ=b*-pXrs`RuQ|HvWeWXtug(AZ0oX+mmOmw zE5o)yahTxkh!x8TiY4lL?oz>E{r<}1`+-O8j>f+t%Xrm$&U0|ib0$54OQmH`R?iwI zPPIuUu7;1|GC#312q;cm?|^b!Qc;K0PIRKRaQ<`m=a1$BIW7el>_p0jcOss8kAPCL{{R3(&VKilHxJB_;mIJKO|D;ajjo zwsfO2CzzzX9v4S}2;p=rnVIs*_>e+|9%b5SByy}>?Vya5FKlLTEN^H8k&|pvC~}*N zjwIu4d)cj8t*W^i0-btxI_e%<@JHSA?dOE-O)It0FLH&&8ANq^mCaA}-`WLhTvrAY z9FY)@TBAf&h4M)Hqfgu`PI^NAP2KsAg7Qz{5fl{@{_nyg_U=R9}@3}5x$db!mVv(;tKDK)Z*3kE*AJrerBlN}ID*uQ;D+ia9 z2#UTb@O>~Y6Y`$%){Zyw(2G9kh63e-4Db4o&RhG@SLq>+y1<7O!gxgTg1~S8;?07CtWN*x%j&91iMkemI{KLyxt7Mz>eW8HeVt52kciGi{BIykOuF zQ2gvjjdQ)muFNZg6$U1V0RNy-js7|N?bWxFuAxtp;+16mzT6nJN_l%F$h~KVRHYp{ z`L6<(N%7H*Y5YR(+MrBi&*E3sQu6))-hJ~O1xjedoB5!w6GU8VI8V`PmFZG+oOY>gSV zbGVXhfH>{d`rekE-rFZTB4>m;6i`ON`PLZ)KM~gpled3_7+#q_p?1}icv+R4B%Z0U z04wxRAwLsd_DU+t$PUc{*GNED*e$6p&FJ4rSS-hK(yq09 zi*!9QsybyaJ%HXSpXh20YP0=fo_RUoOD)Qci|BGW3aV_JE3lizH~O#ooFG>-#bg7o z7J_Uo0ob2aq9YV*il*X|IjOjx3M!`<92$R`#>(N&*_Xv}J}R0X=XJ0lawR|{BX5>9 zJ~mdg4L+G%qc})3{SNL=?pd(14AVz-A;jvNUI+6}aKB;E%q7sWe=;y`K^;r5Za6?j zMv=titbMj)k>0C$?VxlZV0T54NPXvY74{r!K+lG*g=~`coEq!Vp3wgCm-GE=4ZO+s zPP|Z)nZgQ$$CgkRn%*zFVX(Zk^UQRZk(SmFK51P{;}<+}8bXLIoHlD<{FXm!p}Vz@jJD-`O~Jc(tM z5;PU8tw_Qk(6+khiVK(crirB=^R@SzD#6->>S@&(@6@UL&(53*#{k;WrA9r}Yew5I zSYe@hsXet^CPkw{cKTx7JPJ!ve`L#sod$9DT#VioLX0kb>WX-q^9d>k0#rtDtMF*! zAx76O{eM!}c^eHylc#2wcyzL^!4CEtX_8f~7wqcfU&5E~O0h=H^MV1kauZj@W;L1e zT_H`Vk(Y`d_HE2Q`!-+;U@qkG$k94Vtl&n@Zy001gXB#kfum>PVStMo&+2tc_*6DmC1hdi<$v*@x$2F$}#a zUX5yP)Nc9K^8+gi(5$Kw)ScL>JM$~f*n7-8`hEBlht|-{7Hb*%X(ctjP;J^HlGXvW zryON!23wLpXe}I=mpSLm^UFszp7*y1dJXOG>~9Lz3QG=h-}Oogo@k*z8#CHAFJ`EQ z*N4=~*(R;n3`pIOBc;TSdNBi}EWw8 z!mM-jsKZCNL8);X9BRYRV0nX7GkBfTikmL=`Ge+jlw1iL^`wk%2m$rFc){H(4oUiC z6uK6DF?gHa_UN(vin)I)Y>{d8hcAgX!FgM-s5_O*WY#76PMrv}4`4&Dyni7Z{|Za( zseqC)SJ(W8%x2x`idD9$wAsS0;|%@LfcKPB^IazxzWcMoHt5AcTaW=_r!br)XDD_= zzVoo>Lc$O6Zju#oFvO40&$EoyUQ~{zdlNyb`uUy8iULL|J$;LSB4uOa#lE^pOlB$Z zl+`y!8#jCPdSzzQ?#hgMQ^JASO|AIn6w*@(MlOpHjdhJGpXw^+pSBz#l|b>qJ-=LI zzs82A+h~C3W3ZMHW;2#-()Dh=UV|&HO3BW63nb&1HbgoI9?<;>A7A#+l^v z!KfOP_HJ+YU(!Jc;lzob=FpOVm;}ikVmJEV?=M$}G1lRw8J9&1IHQ}uT+0Q03x85! zg~pbNHpVs&tB8#9ebj|bH29nTYKT>B@b0hkKF7tZm(C9w|68E;B@b@BLfdK1+`*dl)}M18Iu2^5Tv3eJS@67*M1+^c zwnoL0-?QIg3}V;;lAr^Kjvw)me-dq2e$tMj{ny__vz0$^H>x<-e7^ZF{~D+h>E0-r z0?d_PC3*b`)fxPv_1T$ZfZ?DkkUNFF9i&ssOKI_BSF*!6Fc3@s5xnImfR#k9$~Uu8 zC;^n%lw?xYPY|6lE{n>foY>G5(hwnT5`U9W0b^yQ?k40HL{FA`nB5fV=+?S@sikkz zlQoUXU5TR7CBd=T$s8*~Iiw1FrQ3KR#=DufKySUDTraRZh!xJMK%te?pl>IS{xe;T znR!{J;f@`<_FKGc=~3*#QjJtl&`eLQxKXPA9Luv8Hb1x{Nx9y~DdwNOPEnU3E;7RV z@Sah5>2yzh{DK3!M|IVE{iX>LJc>^pLWXrJNEFdPDNSv*i%#GmVrz8X!B-xa{Z^WF z#0uk-3|qnxV|^o7=M)>99E4j1cuqV*%uz0O0FS zx&fXd^n$;?&|*1X#LL69EDVyYmfidCOMlpUXOEoi_Vs>vM!G1e-R2WqzaUA@Ql%GJ z!c3VA*@=tpy)$c%WTH(U5PnRnp6n)TK zSr>(tkjk)qDWsAUF7PYKNcrWG=AYfBm1HxvM`ag33#JJRFuRO~Uc9GI6**HS|5P_G zW}}*s?%PS7zm`BY*s5oIPo*vhB2@<{#7=x%GYx5PDwNQ@Y1*u562Q~U3FBLkPdZQ> z|Mp$!eRj!9toQ3l44)#NS#P+CpOsvvtvI=x_R^?(lVOGlXNJGZ#b%SG_-6BvG=S_< zllFS+RUw%um`J*=(W+B|T~pOU9(JT1#xhnCyD)gpjndxt7DOfN(T-Xyq_&Y59yr@2 zF&G?c%BC-q)vUEf%)j-F$6Ds%VBdRw&bUzGV}9M)_d24hiucRxWw_-8DM{9Q*Slnj z*kF@6-JR_`i)=3Rieaasiq?Amy3fn82+Q5diNw-l>8VzIiZ!)(hep=segj|%b;pPu zqm%uWS%Wsyi#j>-JRVwj)oLlELgJ+0dCd$<(@+n%@SzRiTb0FXzD}EXaG*(THY5A; zBB;{)ONc4aXm z{t$HZF%;*w$)hBzXx^8CcXiJK?i>Lfe-8Z!pH&JPYFDcurjcu~8 zvVfX4H>wM{$GcyqP1dAg^ybh+ltKL>d8t7V!z_63f&={|@0=n=VgfuaeqTuTqbrl! z@a!Gan1hdT2*i`cQp>36kg~ce%&N7Ndv$d5ERo~thQroMeVC71NJy8q@-qh6Cl1o< z`z;O2_FahjZ8g76m1JM3t6bDAC5PXw3*wRwv!X@2Us?pa?f!vD44a#<;+R756>$|j z#S~)f7f1VaVv;vE&vb<01mNQpz--*H@$)zFx zQezy?FzD6pWZI;@i<3AKbDz0@BIz6*)E{@+h?#k|c^k1|q0Gr2`D%Cg^4N%_@Lw-ZJM(RXtCfupB852DxX~19I)qfFo(p-2ghRKi# zdsU8C73#Oe@SE;LJa;v9_hIC65Kmw35qaObWOf6XA}EQ_Q0UjiUt7BdT~WB}?pCQ- zTC*UB#b-Reo0&{*-J5{oquO2SEQL0%XKj5?zv201yBU2u!_^+h=&D|pd-vr?^O7T5nS;vjrcp&7+R9KL%Z{BZpD&c!IFv0$`MT+fn3_#PO zvsLl&^vi|L;yDIvoYgO}Ju~WFwj7M|p6SYR*ObSKA(NXX7+KQJvkO)$yCwan2>y;h z5p3YX1|PkO@lZOvaWbkflE(7eoWhV9`<>2uq}ZQJSCwmY_cPkLtV%w6BCHQ%pyy;ZxOy?5<8 zr_NK@hws15lmA*BX5wJs{J#?=^XC=1f8OZ(=bAC|Cz=0W6Xh9TqFiN1>U>c<)E1=v zE)j~X4|OR*Kc%G!$_K{RVD6VoHKl$1z=If*`t}$H;)Ja%=={NW zS3(I~SH`sue+nZKS>v*KCTr#2pu$?0&gwLSseJ((K@rL2b*OV@{RtL+#gro zmU4OPseMpd0VKh(I6c-mIF{HKa19!V;eR)Yd&4t-N+~4h3GB_?!X`VSOZE$#w-@DZ8079ZBmD)0xG`~V)2h&_JxG(1ixy44MdtejjvV*Bh7=49XPj&2-pit{f@Ju6P)S^ce~26 zs$jNdvC2>gO0(?OmFNUTAYp!zJ1#7rn+}NSyhoz=oTfxf*G6%)+6#$a=hU-*yS3|S zY+s4q0)=*{=D$kKg}afj39^N-khWpYeBVC}%-W1Q=o8n3um+8S~*?c@Tvyo;8F__D0OmQ__ zn==VS;wuDUuZjbYH`&E$RZvyNxx)u+8CpUF9Z9j$Bbj@OR37=v{xvMY2Sf`W@}qy<6_i~UwJm3Zs{~ILRO>) zxuagG2~lIOVeTlqtrtnz(`|?L-1S-yb8@e%A9uL*v1!lIViEive*fV2wi(Xu=u)yj z;&G#;_CTzYQIKoucGq!KIRTPr(g+=N`QA7V`%%r*vfc{85*n}LGO0z~Rh?Cf4E6QN z>W-PkWQEFMAwTPdR$?${?U$mS*Ov~x+r1Ex>2-triG)mfKt`S1?C>9PMO^ z(X>vp;f**q1(kx1Q{M+;{CsMuh zY4SSZ))W_Xr006bUE=ejP#6v2Lm=pzKra}D!qqW&3cM&}WtHq9j6}--Q9e0DT=mn= zGQ^sG_9H^EN2REg)0aRT5*LZFK2rJY&STsF9W&vsAtRe^i<%#vc8aKvuZt?!;d=;b z`FVLu$4eutNY1RMTY;I)@QhHU5f@+`*Mpf1J3J3rt`VTdNe6Am0;z$IivMLw`1?)& zcQKcho$=pO!ha<0`PY>2H|@^qd;@ZRs6vf4Wv2hiz1QgLhwHx< zCyV3?YRvHTLL{b0tfKP6gO^9hw@2TqMEO-hid0O>#N~e0NA4qYZ7-Xx>V`{(?8za; z`(^b=UO@JPo6BtUWAoix^VKb5r?q#LsQHFBsGyVg?Ru7~d^_Ek(VcH^B0O4JFdo$_ zaMO*R%u%#kvxp32OHmLa_u5=s5IYT6CNgL%XWVE>*~oW7JMk1f-Ydglcqr0jEhwUe zbqKEBoi=EuKfMD>V}U&m0(?V}hxQ3q@+^L0xp>@&G7p=i!3{3W;#9Wbfk^TPc9}&P zlVaL$!5@5z^M$djl$V7o4&BRQrAS{J%;8Lwjmp_0=S^RIR}#uK^9yU8@yN6IN|`*S z4l@d2Mfn4Sy`8%UX;GNZ15Dk4;0Z32Kum=oa{;S&Xtj}8lO+9K+(3cg_qoXeQy(FE zAD1Tt-ftfli%tw7KH0zDU}<4#zk;MDb;w0!> z6oh}+!(XoP^;7``Jnfh!Rl02G2nXstYPL4JzKxC&$jdVnWi_2%V++Zd9!Q%U_~8li z0X2o8e}P{qgB`MQey|Q6#DCfxxZ63-?!@H_X|3;zq9r!i`^5J}VKWrduL;@_IBuALKP4SEbIE1>J1ZrwhW%1H)YZ2VL0wlN*Rk3vaT0ybZh?GW~w)B0f;15CHA2YX2dP_uH|0>xeXwM zYwbW*y2;gEs0n%FJmwzEzDYW&4gvi%cZAq0*dArOL76#RGB$w!Gehj)J&9fX&<1aH z8u=&OpM4;H-(AhI7)zKS1V1?ePYM2fW$`SSIt5&7qd)?GUO{P{olG-Wg`LcP@`aw% z8r}Oxnae4UL;v1hhr!X0&6GE|7wZ9<3&p0cO|PO5&6$p~D(+NIZ-W_4LZ0IG#fPEN zjSGi6!5kC{8TOEt@1Rd+McoIdaF;A63dtVjMf+a05KmFdEd`D}5mnUN>uvStVC8pY zq!J9Xz~lZ@EY@6Uyo0lUQcKHKvMi<6Plb!`m64XqM$VBlhm#pr#qzyi>NZYPS!c_h%4P_YHyQ0>= z1r1BR8U%hD7!;$Zg%Un*Lr~5C6`uh>yB?ZhzO)E>w8SdU}nLaqS%m#G>p@qR}tGd#~P&XN0 zwJO%>$^@(L2T5!NwtW43+IJqe7FteJBbq1EG`n3i}ScdpU>@tH^tc5i@3W#3)VKo^2s#=3L5=SJi zKzA!YEo^3de}@G@YUFq4R@^s|7kmLh!!|6wia_H4oPxB7DLB@pNMwT0?U)fY!lprI zH|B(QjV!H@G!GOU4hzcp&7w+6J7fl?`m>-YR16b@oCduRdsf}fNGaWrq`zY^RE*G6 zsiL{&TQWciyoM2|>CT3dl{%pziDSRGktR(hs9+9S!2VcfEvO!(=J)-k{@|0Re5;!^ z7Tbm36woyIKA4(YR;FR$YO8@UMG{RKbaFFxIO_bF*?eL+7L6As8y3;=z@q3BeeMPQ z6lM3+_&_2BT?EtOtK=XlMjyWAIVB29_Q)GLSVpQ6NmZU!t21sIWv!FyBX_jClrLu| z;$T4&28-vr)Q9lfQ#2yvo>5)m5m5{X1|;R|5|*U_UpSI@u$Y`t4l@_-^Yvvgtk7o^ z&pY7U$J}d&zut5B*##)1%$QRgVKtF<2pR9!ER4s0$eH5s;GIi!AXJyQ9fgj?TrX*t zsv&wLbjP$trYMKcr{N7-J8|!?N^b^tIISIz2(>fSm@WN6d|1@g5?6Y-TNy~iD~(H$ z;d5W1q92?oS!Cve#H|xab8IxUtg^zsSu>lNeB<*OgH*QmTp6|-Bo#dXy&@!y-qs|e zFX{u!$M9(+J_+VAZDw~mC)HI6LvCSB;90?OPr)p3RMwTT3*zC4wOrH^E#Z$1?U>Nyklq~7{`yP~ zjHE1{N5q=7BeoeiW-Zu{g4Y|5Z8GZ^?1x3HCidhs|Stv=KcUNx0BXgDBBE< z=k0-^_Y5&@Wb0JDqQx9A{rfK{&@_G19g<-$a$YCFN4`#}Ot+nSZ_3B-^#RX7AARN*ii~~F!bLY2@ zmKpauIW}9JJ6!~AKu6Z^-lvSCoatjW1IB(&4&Uq^3Dz#@9Xnol^llBqem*BShiO_w z%SYB8UuxYYn*~p-M9HWfVKqBPCpr+FzqDuRWe~Sy9^aI{^Q-0wXaZ`Mgt0 zY{bLHNc_v00_7bH|D>rDWOG`X9Um)`BA6&h!97EvpAbS=430Z911oEl3&C4pMUJHo zpySNV`n$yS@KKpx9ZNs1IwwPs(6vFx)8;trY>|PnffH=Vd$69_CvC7#z!r6Al+FqtQ#b-P_ zB2My?*&flc_Qh7QYP7hX30R}Nmwhq73Z`GM8}o5UFNicAJaN%rPLN;ERf2#s!`%p| zqabIA;IwTSBK&#fsrqV@8hW41kQeqz@bN00V54{6O|ez)=nONz9uSzNv2b_tdcP~g zeEWUNz1KE&->lqTI6F5RMkC-7xjXZ;J_dArAU35TnZzNB8~aMmq}Z!y2Zi_qqjR(_!g&>c=ZK8V^{vTGVcY)( z=XDOv;v>JtmzTLhHdUJQ-a!#2xUBl>x#VsCw(O8%@>`;TEY5p<6Tb|GLWM+RG&JZz5kH_M2j%AEJ zD2f6LBXn1}3eQVDch?i0cu0t;O0nWC7V;Jre7|B&AKYOjpF zyQG4@L*Vtf@cC<3o=?_0uXZK^ymI8=@lo_~2sDjZSrOueI|0Pz3nhjNPSjMJGv_nD zMN8M=FUvI(P6&MX4iT(lZAb6Nv!kNEv!hFAy0Y^XrJ)&r2~ZAP98I(dTKce`f>}|C zyLaa1*jO55dkmmIHTjE!r}{)|aTZ$tAnL-Ik=_d?DcqQR%|n;F>kwZ@(pKCDalb1M zS}Vma#ck`aleW%hnL1PvuL{7-0o~&iz|Gq@=C)G2PNPkrJE$7(70%}pC7Wb^JG244 z_uh$y^|>U;oF!@H8$A)MR@an^5>cwTd?S&5Q_P`HQ!6VebqrHmKz$k*7>tVRhGHk{ zP;-sroJIyuI>xi|KtKh5JD$RAg&kOGq`C28Nj5kS#^_{yr}d2kx0#}cBd^iTAy{Ub zW)2$T{gsqTd`xKFGOmyrgEfI zE8GwiGXui6-R?&X&ci*6=RBHg0v#;}j3bAzG<+o^1vJzPidP6YN;8G@CgeI;xz|qq zKwzq8UWKI+22vw)I$9O5P$K05;VvKEW+gSRjk%8l0>nygkdD_H5dH4azRh_C8X3_; zxn={>@6)q-(F${q9?@g1O5F$X^6XW+t)Xyul!oPlLG3P+*yh2`a zZ@FuI?UY{91XE`#dapGH30vW6leBuqLNm#yz8L;`Bq>7i1plV~AzbVoZM^1@ZtGz< zwtNdPg*h1{R)Pd*omRxu9xJtYU<3_gjJjPcv58md7;C&F|9*^DXK5f~R|iUQv4kzh z`buBj6z$RVUs4y>Bg|Pqv!q^?iH-{sT-&i4NKa813v8Hh-CJq!SM0x-YH|t*e}TYu zP?2Ca;&ygJ@fmIdjezMGGS7;Mq%E0}L4%(aG8)s7qs89FjpS-{qO>6)cZ}Br?3G)q z@&++7CY_Z-jwdNL%Cwewu|NlyVar3{E{%6oNi0qv-`8eT7obg4Afw|q77N#tZKC5^ zJC#!fyGF6mfTt{)ga29N8g$!7%9nnUmF~QWR zpbnDLI;OfH4C|dlo-X>689Pg&ez0fvZSFNi-F3ghKcA^pCC3L{GD$8?nk_QgE&5kW zo9oQm&-xFNye?y%aM#>Da2^5M9eNRxIp|5T!~@hYacq{BbTTJoMABeGVnR7zf7e_c zij3N=Z(3#A{;u+ewMZi!zz%#D8Z65&AJ(?bfn3;U9(dc!>*O@SYlURFcM8d^WI&MV zqd(2aQRNW1IkiY>%tEJH){F$JGsc}Lusa>v;7X0%1XrCXDLJh{Le24aRPncK932jf_%~GzCQH`W6c=1Va#uzkJufj&l_jJ0(-ZCK)(7a$wysNl!cDs9EqM$5)EiJ1vo1ik z!l@yFdJ&{QJdV$a%3MSf;&)P*nMoqzi)3wiI%l3!+fI`-LWgXQTKHZV^NpAuw4 zCDZ4Qk?pn#E{1-&EmlWCX~lu|mbLBAKDQ9tu;d_Q_yx`jzhcJGo*69tt!=>v$(lZh z%7rTj{EwLgmT{&KK#Ct>?do+AZ#O$^*m@G*`T6z@MvbcR{rgRf(T-F|Gr>n(y+Yqf=q2s*(Nrb&YXGfW%}ryO`Pv|RTrx{ z-oIZ^HeV|9=bPqz?6yb0{kN(1Uneh^I2l?0@0udZ=RJh~cbkdjbLZ)QO|@s*qfz_K z@av0eu6%-A3w^cVs4&UybhS9yezg9l%)bbe!G^4^Ut%S~xNj45nkZPxSg~~~Frq1k zLM6?MEMK3(npjIB0bR@UfMImz8y$djgPixgxVb_&^~cx z0SXjo%MU#IGDK=jcs7yGaYF~_vTUGT5C&9TI?2|!P;a(9rJEf{(e1fEYr_iOK3^%( zlWyn$SId%b4zzkRNSL|?|Gr{2WQ5jqON<@-eOua@XbR-{YG@7nDI`+UocR|w3^>ag z+9j$#>@D*g>JHup*~c#SaoX9l4XjJYf0Mq)CTZ*Aj!Z(=@JWfjI*9=>Ev*qr`rvcL z@R8Et@n}@u$NTz(2Zsg5P>LfjzI8TacLVLJiXK`%=;`HF?0#WQ^zT&3zv7peGc4>riseTJu zRSmvD*3Xq$tnFQ7x{)qtZUsd1o4A>!msWjCzG?Ot2)4Tp5UA>%7IaW^Mvoh-2uYMm zJ8z1I8t;NxHdP54R>9ewO2LT3c(=yB354QTLP=S=Ji>=dFxsBWpC%Yvf?iEmB*GRJ zLB9c*2Bp{9pp<2;N(0~#bF=msJI=v>uHe?}B4+O1PE^jECf}wH(Xi%MjuO^UlT!Uy zN}I4snc-`xmq#fj_?Uqup?D3K!Q)?Y(@s;heR$o)#Le3-y5N^YOV6QwwNtsumC<)C`CDQVQTAK31tnO;r}v@Yr_cJJKKl6%Fq{ z%>aNe5D+wMpx+acuq5#ONZA@9{MYJAde~k2nPDm4Q%VV%Is^zigpKOi0(zw2vm=fp zbmqJ(mYostPs&TBelitm4!y;y!A^+m30PwK+fT8j)e_JQM?dO#L)MlgGidsyHH~Nz@V4ZhatD5XzU(3@MMA1< z9$4Tl6s4bCR|~6-f@xJ!lByX0Wu?`xM`~P9V;?+2Sz~ph3E;v@A;fC-mqF@t7se&c z*{}JZSl|D@E|f#8ZUJJdZ>RHyybCxDK*K7og@;)_2Q*SDx0E038|$tK2*Np_b8QEi zq!x!-amrUceONz7i3du(2BmbGX9qPDh#kpg@)ywv`N0hNJBwrNpu8d7wWS5z~U zz}(#d+%IAQL}wnUx-hjfgTD8w0HAeXLHPW&s-*_zx_im#RF3b`K()2F`$ z@(Z(=1pqQ_4m4VX5mZPJ5gw`(9FBK*V`3Z(uS5(y1QV3k@pcWm)a};p+)s%4o6s@B z3lS91AQs*+r%RPO`PJE4L|bMnh1caoPnnnv$Hcfvf}|l2$F5k>`5tx?)|#xN$nKh# zWQrlc^z^m4x5)r`*iQWiBpT-v@W!R^X7tp#l%(-C)=6s7NH`FiE)Qm$pvTY-zie-i%c6z54_z3p>^Eo z{#{KXEKzcbYW>{o>mmwOz8!C>!-kwwU^yGj&?wAL*mDOpABV?v3c zldrOBDQNNIv0+QZE&z$r_5%EFwqHq%fe6;3aI_stvT_&i)N=bSjR^`{F?&bXy4PN3 zkk7*r(NBNb&#mDv(z%siw;!3%(=bPK*}}b!5aQW`|9$j~y3eBI+m@D7D>%Ya+~#<& z*BNgy8IvE{JTxEfH5q7HEQw0xOk6~__OYWNnC?~na&7Vm1u+)XTCQAU50Tzw^0Iy8 z$g@T(0%y0XQHd7y%@C()AEdMD#Eg0O^pPV102O5{u}0~93|X%`|0oa`P|$Emdl>BiXnU+&Q#X-bweqsP#K@jH z41_CQ#zY^H-nGPXE$>K^dM(%zMh0UqksdQ2Rx{?l7+l%3Byt994qhleCz%p^CDeurGMM+ps}7*nRRu zn6+Miy3^r3FdhehJS7=>4p8!kMDzX1!C63+M6 zRbxGf(7%gD8mwdq@!>LiptG|eaNR)jqhXT0N0+z-Yj4M-*%&x1hLqncL>fG&6LE0v z{n61+#HyV{$zS^l?U=S_+6@=7<_Vhy9{hRA^S??4Io+H&2HVkE!d)ivU{^LuE;JefnAr|HW-63u=|8tY`R)5JbGXB;PxtC% zV?t61!Clf6dC1!_nY)QN0G0+IxaFd-1yfN$=xoO<*Hvra3?0bC{Kh6Lh%zS$UfYft z=wjqb%=AcMon;-t#hc+llN%rm0+Ec(q)u_?HjCNf@?_ES8KyqF1Iei}EfWye8>c_w z;-{;c+#WugjMnw0e_!UKdvPe~TCn+^bdg2SH(NXHQomNK_z;(+^>TeLGfwcvqE!|k zpF_X1NM+|ge4^R(&Q>k>{NVpb;5gdlWp^LtO65gJq_Q1%ENx> z{XznTPe|PX{DDDcRum4B4ynZHd^`5o21Tp3kIZ=>e%JVO*95m})27YH zHmWo_8_)|p`aZu!URl%pk&bY9=<<3;{FyryXmLU&>AP4+?)vkdKfmt9xsLb#wp~J@ z1jpkRAT`~c9zADJRWrxEd?GJMTl-I+@Pqjx-JCCk>!$5%{?!{kG-#1kP5MChZ57O? zSsmy*wd+2+s7c%IKR~NDPkxtNB)NQuvuk~gtxz5vx-;0JY0CV;$%m-vvvjTYh?UiD zC$7I;KyP|8u)1Pwaxssw;z(9}Mj>yge!)I)<00eN;RiDhJr`MpAN-L?TYW5LQ&-i_ z?H~Q1hxh&~+y{((X)t&0ewh3jxo-2qc+avSSif>@tzE=5sUbWnqbXqY@|;9^Y18S1 z|K^Toq3DgD#d~|^E)_!mJo2;w0tPx^@^^=WJsR5XedV)HHFRIBHAA6Y+fG|$Wv$Ue z%K0cBQ7=@vxWojnrbUrX-&bDEW&Dn9UT9tV-XM=8B>omJNCnBNm5TRW+(YztijMWp zjqj@rE?|5lj5TL!E#uRohg8?FVhKeay_%J)UWM=WU#D2W+U#|`gF5*)ZGLAB2#8cy zshQh7Xf1z#--NQVohl67NPY*hu&9$}{+wzTFA=;l)mhj2wZpEWJ2*2V@+`q*3G}kW=v^S^um@GD>qBQGR zyG;s^Z?vd^Cy9sc^2)xFA1H$IJb&kchYQd<`2e;}E}?qeClE;y?9%fo(@6>QcJr>d zSi{JYVroI`LaRSzKC@Wgd`2Mm>{63|o4q1vIIRPv*aW>kn#XKeBB^!*WHlr+r@mgm1izWpGUXMZm z%*>kl!|VNysB#uPag@2GUb}a%iQD{nKLkKxTLK{7T1^NsX$`GA%0mpDY)R1{&T8>O zr?(WWWRn~zRUtzR!zaDI0%|DPLw4zMdSaJa2R@%U>Pyj0fe;~v-uxTL*tnrVw6@J; ztemLfCs&D6fY!@Ve`_7M|JKsA@q9kRDz;sv&1@aeD_VBE zfble8M)e;;2N^qo=;@4o!0;L}wXcoxUj&wBYUw5{LQKxQ+b5j3&oSFB0O{sncgM_w zd5H^Q=YUK2184zu3`NN^{T}`|B^;-ydvsitOidsYm8vBbc!;v&BL|dRZ~ww4ur=F= znf;eNm9yrr?p$I16+LzJU7j8VPgXQS)PU@Kpcy&TjLc>N4rGJ2Uu9vNyI{CD3A%t#aUYVU-Y~vef4Y zf2TlM_}E*1p$TofBMk{Fpzaeec*CWc38f4A3e1@yh1_9>}o-X{4OWHGefE=@}s*`RGbzh8%AWFp_OvOY0Q5{?Mu}^de0UZ zm%T|@mV!YxBd3D~pcyV+C3CurS`N+ea-|ySt_sjCk(}aoNe-#^zmpO>i9d&_59nt! zSVl%+#PIxREgC;Zf$Tp=0eIN6MtNfj#gsT1yYiisQStE{2w|D47&*P*mZ&Xc5}D8p zVaX_rYoFoek}Gtd0}zjIxlnWc9068L$dVm$%``Y3IBGXse~oUm|>`I6yPD2L;E3ktMqMjH&J16t=`6p>|Add05c zd-rK6ov9S8u)>Dj2-UiAiM2I}yQOLEt;t0~>D&&Hk)igqT=jBD4~xW9xj24tiiV!H z@dD>sMRd}{i|*GCksm|h6@2)8A`;E1hn3ZqQgEXw)!cXO3}my=zPo6hKfRk}mjkNAc%@W;_Nxo%XI+ZhBfMK^~Z^PBT;w zI)nk5nm>!Cagsv-5JTfqS@;1VMDJ3uu;dsjJ>6rN&K{bU!W_6JQnvmUGCi`_C9y7m z0*lrR(2#@p4*`>e*_s;wGt`WnH^dxYuRNWu-u$`N{VE_XVZs}qc}iVIio%38Q%zokx`_O^_>v| z{piuRV<5-AzTAO6I)OaxgCKxd{pc)PaUf-W1P^>)1cg$R`e+z108*XKY31*!LXGei z>PEkURsfTh_6O414}N|CEBH83^wu+@koZzghX8Da)>5GP6{3@exj*V7jT7eto*C6wtj!e7Js1lK1g+ z{kXkU3fbRP?3^U2cJlV}hLeAH+PMDZV-Mh%3!2mG{0o&@6ho2C>S7IhJo^7J@e=sAPbT>{fDj9IH431ttB z>!Z=Pj@A!AR&E|qEG7Pp?s`ASb~o1FUz_=+NBIs83QprE$USO*aPuY5Q71Bl=!z}` z*&kc z+U^oDhvtjt%UjJ%Emoj5HFNiY31xV#_KTUz+g;`PFH1=!&uAM+!mU~#BBTo+*rn#F z>n}CIlFR-Wo#*bm_+I57@tx1L$~}Fcx`x)K5mXxOd(a|SS(;X9jTou8V&qzRT>=pOeEDdMNhR}em)l*tOUNHf5bWr zhIU?tw6r(ObFZ!&nihBdc>Hh(xuRWl2EUUnFTqIf-}zqnw7%&>H^$LPB*HlIvQ&H5 zLJsoI`uv*s^=R=D{9AXVr7e`RyTfbeA8*O(EwAz0JK=}{i=_LPs$8x3 z9;j2F_lef=b+3jEiMOhpPIj@^bvSw-;8V|HA#P38 z6@7CgBygxjEm@ecMux(`x^MIj~#*Q!|b3tv8=*{b*p9mYnUXORZv23?=(>^!=k4L3Q%TinP;k&s<-t05Pw zW{q`BR+5Ek@C5avy{5;H!V$YY&hY3M;@ey#8_^>#8b~Ie%h5!(tb@MER|nNyvI)%s2=-}iMkM{LNn(@u26Xm}n`&NY@Lh;GaK5RA}v2Ffk2>=%rbyfn0LGw}ZzJmh~(oQ{)rQX75mY|FTO z(>>2gyAc?vlSf$FDLN8xC|jxeZGyU7`_~Z zK;pnGzQkV%{m2^e91+srEVLN$F{VdXO4DeQe{MT~wCi=^mwubuKm)d) zkQJP&!BjkZPbqlc>PMa@pu2k>P-H{OH34mi?NxFLB4~h5x6JtwP`CoYR~k)pGp)Cy z@%6B$hD6)v5Nf{b3$x9=G*`nMLArYGb6$aNmpb?T*n-9~c^_|z{Wc`iiG_klN9T&)u_=We5a92NB#{M*Ka8N?Y69QYg$Xo;3vE<>KklSfbUN0S z$h|6#di>BUI9p9LtcW9SDjt}^sh7O0aL&DD*8$14Srs5C%`ux5jABPH{eT*<=SHsO2PE+z6UGX{8?7&L4UA~{KW z;KKV0me*=+TDV3YKiIdo`>C8-{#P+D;idI&gb@+GcqVEQItgJ};rZ1Jtz`a?v@vmP z@1n#iQ#+aJzaZceG^*$WT4bPBbjigsSdK#_$`5-(`vtQpI-AP{JI2EJ=}m$$&jv8E zrZE!Lnfg&e{RHJbx7SDRT6F1GPPikJY6Z`K0Z;pY#-#mj;O(9s1l3=wsk5uiocW8Q zP(rCdU7CEOX!>(n7bFYzxfhw{{7KZ1a0*2)>|3_3=|C;Rr-EgS?{JUA$W+{QSrYjX z?x*2(s($V%Xg@SY;Fwmz876WWXlrt5D3C$@G9Py`K->ywF~$^4p)Sz%{6+LYkQ2iH z`~x#rExXurKTc-^?#tVb^!1^%@NfI&ObIwJ_Z?{jnD~VHwev(~k-h52T9TCT{;+|J ze^dcy=Z0-O7K|a0O?0{j)YBu=X!;PxG9TA4Y*5!IrJ(7kkH8sV7(O6`>X545ZUc0= z5ISEZER~Ff5dk{r61L{Ww;#~zw<|G|0w+>ibQ_4+K5Ets!0l#+PSQP{Saqf%K;O;y zxp=8=6fo1AyHT-->bfpo47Cy07!Cs*JA>SS7k5h<$;TY)jE5Fptz+mRz6k3Na~6oj z9Kv_y;M~`tuFIv7P9a+BZR;WVtm;gcfZIcC$ML_WPtagW1(y6Ywqq?%3NZqxYWr+e(+p_!(%Y6pco8NVHr))cam3Fh?;9aN z*PV0x4xDg@+Erj0bQ$5fnISq}I@wFfc~c zf>;J_gf08D-$o$=YY%hau%vlY*X$Ed({H*D!>;Ev@D;7Or00->jnnyP4}ckmKzJnQ zu7Ae@66*TZA#y<*pt!~};xSv<{|4lCWc-GA{lPs?3%iMdtWIw9W z8=DAmm=nP&&D#h-x6Lo;iPCK;sr%>KfkQSJtei5eJEt`7Oh{eUdqwg4)7?SHK^0<) z7yAg)+=1Rl=i5N0c^m(43Y4no`(fTRdnbAF6g8WwXra=+`4!cd8T{ar z&Cd6y?Yon{=x}JQ>B%3>o)ypVt(s*8YT~DdJql>NjSP1LX_e9IYk6f+t`>7_=_k4! ziu(tDlpi8!xY;c^c#jQKYTqSWFU{&4PYPV>otK{wUWmP8bU~@*?|-RZ=~>@p37=li zxG4cMzlgjUMK7PO+TO`d)A?=+utIKn1M=gz)|!0q5R|UWbvbL{R?}wQacy|i>JfOQ z-L-tZoba_pk{1UmiwMUvSX@M{QdlsYLnR#T9x| z=D4YoAHpLWFL7n}qq%G!1IE2+k=J7Cz6CxF)3IYTF{@>=GBW68=G{Hx!`-@Uq*&yv zPwLw5o{w9;GOlw6-cM_|ry=^5y!K^-dM4!s=vQ5Iq8Ur;4fK?lorK7@c0y1zU^vQ5 zOv-QYQ{g-!VLLIwxtzTaQlg+_6A-!c_@d!_NCQMAe*Q$IQ2K&bd*fjOJgrPXb_}=o z>z689s*0Okyi)b*AdHwmLPg%Ngz!KTBC%Q3zzc?;VUVDVaJSyDr2i=U2|R=R398xM z4+P)sON&XUyhmZ>+py%jvkep|!LW-uj`TITWr$AvM{cyq8t?RAEpTAZcVh&jkX;~Y zH%du9zi*Y!74l7?`M*Osz%)`UH5Xv!|=XHT;B37&+ zQ|dnPU|ea6_;!(o1+|MwVZI>9{LQntCDKx30{-Xy+r798Y3%KIKw{Db$y0me!Fa`` z`fP1(Dp=F&0eGugYS5TQsSj}oo5Ay(JqrevtOK8uebc&T&IUKrPcH4=)IX4NlpXKz z8V~DAKQUR11CwtG>&9kN5>c#NN#^Q6&cYNWl<>C<=SVn zX%D!TU&Ky9MOfw3Cw?%PBhMq|X?mgMk``C@Ffp1-Ge{yiJ6`ZyQj+(>sIp6qAB&v4E7xE;2X$jS>o8<^axeZz z4jmp3YilWqrT50=HFnqH%1jwK{43tri>$Gpk5G=33nsh}`@g@OWJK-R?~UI$3?N2> z;A2v7<^Lcefyq6;RVA@Urs9<7n9bUYN`LS|Nkfb_L8DSTR?di0jAnAX;bc>Xj4j$# z)@p@px$nvnzz})i%g77nr*X9#JmHy8=-}ZJxw9{*{;sYP=cy95=C7oz=PWtzp5}#X z=Gx9NRn-(N?Pg9Go@!i{OS<49=?Db)OyXf~k-^!1`=u=(-|we00|v%m2Vqmy4I)?d z8%~{-vX~U%^m2r5D-7JcI$F06Z?#yuJ7j7#V#T@7SoCK;aNzcN^O{=lj%``Ll%o7p zuE>;sP!GA;F;#$FwTdBG$#=5_gG1ymtszAs4%y)4`kcy=$IzONP@2_@Q~!stcL46R zdG<$R+Z%6e+Z)@q?Tu}3u<^z=Hnwfsw$1y^`<~x9|Ehcbb#K*EmCW=^Pxq&Ll4tsv z=`pPWa@^RGS*QXM3R{y5Sod{j43I(bGidsj@jB|4OYxg30uvDQnSek;45Wi7UWB8J zAS(I#Q%G@TnBBK5fQX5+#Yr6t4jL4(1NCj|sus9^HjqI>1U0P-=!9p`J(%V;HmN_= zn2rt>;;rXQuyA3& ze=S$`=8!{?7i$9qp+}B4TcI|K!yLrwu!EHVQ{Q%)8hK@{1-LD0aHW&mZ^h@c{ovi! z7>74o(*38cAJJ9RH$sCPMeEO9j1%8BE-$eL7x$aU@UIq*26Qq$B3@TEzg2WFckq%x zo_RuFrLxre`-achYVIgDPk)Q#?UNPj^Htv+3WrW{UCLBR; zo`F9z@2zN-@-mDX2GxM}o4$`=zCfQ2fBA*~-mv|&N4TM9lY>~}P0IY)+ z%7WG(=@i$<&YJDEJ5FBgztinUfnY%qL2R83#=>y5HB*U|EmZ*e8$C21Vkr)6QMuo5 z=h%+)Rc<;1LBOvJjmo}E!S2~LCExHEz_=G!-|2!K^aiMy1#LfkKc){EjshRS4=dXT z@?AAe9y{VD2)-Hv2g{8E$l4E*@Mv)&=r{HjIR+hWByfKquz03#(Vqq|Xbo&JREu3v*5 zMu{I_s`|AzjtD+X5rw5SniwB`z}?Nb_C27rJV3i}#+eYKJ@SJC0^3{QSYFlTk#^Oa zJ>s)ez5Bq_wrL!<;(oU$x~jMng^UDFnl`9-YwD|k+L#S#stk0z>aeTA!{mEhaf3B~ z99E*ki*60mmJT57;C6IVoD3ng7w|L0TKG{OrKMq&wgA`dt_9u>8MAX(Si=Zh3O*QU zb7DoH!rIKLIwdPAlbxl9wcWmz7 zIGJ!Y>90({aqH|XUutoa#?7iS@#w^-pM5uZUJzJ%*wsH>GkGJ+Ef`=$uN)q7ry4VI zwcoDTTi&pL;f_B9jbJV6*Ki zKMZ{7BpMZbfF0Y7MK^9gj*V634^^i|ePU(gzG!QM7#F1R7|h5mY5-7atG&a-ZHm*04M10iF zh0wE+0zg{oKh+f}9@`SDV2OIO>J0akW^_S;MY`p~Jj137vm1EN}(h@otNjCg+8zj`Ers$|U> zQLf7ROV61pVE z>ge7)zbaifqP(BKc5ZxZubM30KD^U^zMZX)UY|uo(r+(&dtXn|wcgzf51OfYyFWYe zz3!6o>fL8mLfn_aSL~n88~45zyienZzt+CfB9Z683Or%!Rt;=xz3!^KBP+f3w!e)& z`g(c1f7~4weUP{w8p5BuuTao^G?m{hmf_N+p=DJSeLlO?b&_>gR2sIRD$wm1URH2{ z>+^4Z?1mqL{6M@0ax%c3(?*reP~+*KRI%hn*O)41_~k%Qc}wra&C(erOgPW2}h)#Q+Om-F*G7yo{VC{y`R zff798HH7K`!dE>?$2v4FRlp42W@%#$gpfvx@9epdM5eaCj(2l~!=hr&k}H&ks%>ww zV}JJ3kN76EA`b`Vl`BPoN|7*(RZGd-XHMVJ7tq4cA4O?L0Rh4{O`3sPoSe!?P&kH^ z*M9U{ZZ4S8lqVX#U!aS;1=kq_kT5C9@GFAVi$+{|nW*%l$c`qIOAk7L!P4V*GoQ-T z`?KuF@sE8gfk+ix2^;u&MZkD)&a}LcNQtS_o=Rk4%etl<1V1oyQW&597|--E02 z9YV=8EH;WRJ)nRwF{Y5whQc3=05po$+GPR})^N1H{Z%~>85vreo(}n^cBxJ}G9}02;RFKhV7$?F%+5{iUWCB##bl{f3B!t2gKUSFYmpSL3%)=1F zp+D7+5Ca%!ff`QT3Ew&lc|Zj`#*P?rq5B#5tSLYQ`TTEy_WT)zl}w?s>iZ45mdMbU z2byxQC}^f>2fnQX#@pIO_VQ}L)Jaei+n-l(cUIQLQ>%*Jnnwm~=Tj5AIx%nOqN<7> zDa*S#DQ@Gc)Wz#ABX)BJ`)V@n;mpI>BC_B57at(z1Zhh@R~}AcIAb#aQUw_&smcI4 zLB>3KoQRaT7-xxYnQVqUb(kVRT+LoI`A9xFOo6)prw}93RXE+STsF(Ds^omaHzM~u zsfS{zf#O8R^?!^zicB`eXqKX!4zMnA6dkxxtNfT-3jk}A@blyJzq}bgWhLg*n1s^F z8j2$R>QEStO#n<^DrG%sJK#daoQGH_ja18<&&?EPrj4v;Z6O3rGVl-%94K)5uVTDUA7F_74q@1`1~SW&|)I*12;oF_JW+(Fgz>KSWeK z;1d(mvCuCktwP1~2e@yH(U11FdSZo7< z`#sUbZ<$)~l898Y>U%$^qe*0K;Qkp40aPLNo0enV2pHq)sjwI!4+7Rz(m0ZY-Ge|zu$tMAUo;TC>_;GZQm&h9Xx?;yYK-!l2mYB&Q1Y34 z_|euQaB<^2UC@yNxEzS~mPQm1TuJWP0#>Eb2+-@P;wYd!Zy=O6tK|K;c` z+L#G2k&rU#I){M)R8GotGQ7yx&_6c%*8eX!>C>cKbEJlIJ97hH?v`={CI82v>`Mcr zVH}+rF&!pR+W)~6?`O#I@Gq+Wt0(?Tv@ql*rvXuL5Z(S_s+_#Efr<%{%f$Sm|79qn z++I}o0rbE5Y#}J(QRk>eWLy`U9z*ghq`icO+H!NVxxGH+Is*;8-Fo2dYPmn4iQS z>ZfoWm~dh^CrLl{CS z@qn!qDHf5OFTB`-iQ$Chnc_{?7-Y1LBomwnQs}o4pt(!aV|3;eprjdIiD2W7+wJ4m%=6DjxSu`mLx0s1h4PC?huiTh628Nz0)$D0v z>3-urpHR>@UQNO5kv`mX!(X-|F<7(|$P8#dgw6KI>5(i3B9p)XJ;|%oYqM^cMPW7H za3Tn6*l%J8kp|O&S9c^IbO$<2KC6R?0|1xKwaL;lMdTE`NF)?OQxy1fmWF58Jj;GrjPJ;?FqwqPr9q@cy3lDZHtm^nqnRfgK_u1QbqqD}0E#00 zZ!dB9?G*t&yf@dF#E20-ma-YnHpeoLb7;{T0uQxYN?w555S-o?gTmo7pU_kqp665) zRaxgE@Dem|dE&AMvxt0cxFd&rB$PYG0rdL!US^U49)?g7qJmeR!6GPGy7N{#Ta8Ld;Ikm0gE8xhRHCMD*~ZG$nD+j} zfn*UwRJG^xw zlJq|f0!nfu*i}GXgOi7$QaMS7n9&eG6+v49%GN6d)d4&w&^xT#QFPCe;URRwVJhpK z{Wv|}bZQ=zFp0qW7b!Q8Hcn7@j!^VH#&QDOWKxD{N->9dy27BclgJ)GrL)f20ntIX zXk0}9-qf447UXLD%SE%r`H~y%%s-i8ncHu7@UpE{p^L6!6!(n7Fhymw_fJry(wA_3 zsEzW8B~Z*fH!`a|xRWtGwd_hfe}78JaPou>!-JTUDmAH(`QwM=Ce;q^TeosLBiy$8 zS&pR3W%)gTS9yewqVj5qE7`Se1*huy!SviXP13T8&`!HBy~F-ApalT~vMnho7lZ8s zGEhYvMdfdtL#y{%;i%#ag3S@oNAEw>X*l#fjE>((he1LyW|vg5T|<^=LZ_Zb!vHHL zq8S9SEupjwe~4cq978unhlW~HR1&eP{Nbm6P>P?F7f?5sP^&4CppSa{Mn4Dbp+2Hf zL88pS3<;b=b!0%<6QB@a!Y&r2mU@3OGjM8JjI!fN#Zd5xzU?|7# zsjEIMt>wJFxv}7atb|&~wGEBguC7ZY9%s#TWleeocXL6kj#@kO@7(V0DiSAF7;z{7 zGmtpY=YtIrVFVwvXk2NB@~xylJwxBWAd3^CIS@b;GT7@{l{!#F7DfP`PiXdG0Y2YG zarO%`0{;RGm(G9ay8yTWr>eb_jKN+kgrv~_$whYVL>_VUZ-AC14DsN_AHNoauD^l+ zyyA>JAN4OnPJi8k5`~^6SVfR2Eujxq#sYYu|8KmgJa!3)Aeq(ft8uCG3kuWcC5a%@ zQULOk1Mo4c|2@<_hRYdLnjKp3maEcbm4N~%6o=-t&A^Bja|VLP35iw}QaF|qE9(rg zvKuox7N4e7_x@B`bX$aNe%UE$L5zq4rK8yifzVdb0c1n1j6OR3j(#Dkd2&6E9EFSi zm=Lt1uHc{s{e0kw3MjKDrThkzt)QP-5`?28TBQsbAw94pMG%_OEia-B_llc_jVu33 zn#l-wR?Fb&#sk`xNo1(5;#>C)DLAx-Q--6Xv!}<(E!zTmd&){nlovOh26seks7W6&lv!k#X2du{*1#76lB3*`LrC z5z(qJRCLA;-~dng4~O4^eDI`kc{`N}^5g)=F{{T06czx5e<1rRd?d)D-&H5*)xo%# z`F`o4Jfo7l_=BzUDsEk;p>$@YANT6M_YR^3Ge>ocE7-y_pbiDf*=aT}5 zBSZhcP7%rim7OSz@HYjN7cMvsw3FA*B1<0mo;l&T9NHYQy(G{EmwHL?k71`aLc4@f z1TKg&Qj!rkVETz7SY)&84Rxap!T{!06zL$_b-7OiTm=)-4GV}7l$?d2x0(RWsUlsrtUEnUMevd zi;^$TYU+kKX!`!2NomW#JP7~alkz7G3j2TjY=C?N9vP;{QHmEU>tI)UJW~w*&b`p- zw!}A+^66nZ|7s`8`}6nj(c4II?5?Z|-v}$z>~1LftmsJQz7LZkGqsnj%?(km7rJy& zM~ymrv)3UdZ!l!VC4O0t>vv{_zr&x(dnGHNe4>%IcDR?idg$e`o`6!=CC`juxCj}g7q2Q#aKW}mC(p7~ z*qL>*(SyS#Ydij}lJ^5Yw5At_$1q}5ID@zVxbn@0aiN8%H^9O}_Ax zE3K_+%#+nD?nkR1*!+#1BmHjUa$xr>h5T~2o7Zc>{fjoc>{*77Pc|Xa>(}i@7K3-Z z3aStTvW;bnX_1dE#(rwJ`BjT{GCg_Qd{-iT-Vw3V2hpx={EsTjp>3VVp9YiUXKqz1 zx2sdjuhi~Or4yd`9iD!AJKH66v*)2aUPXg;$J>|YjqWtQGjGcWQhz2uz1x`B!6o7g z4Ny_vJZH@jT)gx&RUIZbP~RQgm3ht}n-27b;#emm3B+7=pAs9lb_FxY-`Q8 z@hGpjUP*7-YiHl{#{>Ntunoh}5uBY%bpzcPV%WDyRa%|G*5VQO<-WE3r@{1`Vu z8uE^v4-bvy!=AFNw{p5OGXc}+V}Oj?DGW{qx?Y7$kV#%$TITU;PtT?&?SP|36dF%V z2(x8OgLJa%`vIPMSQmYMnhyR}qa2xsX-4oAnioR=*a-A(H17pG$>FJDX}`5`cyfNZ z>S}#;(#DzM-WcrDUv9-TkIeguy}2*T#D4KER=aJoH#Bfd)p6>I=!KhTu|t0>Apob* zb;UI>G{~xl22?pESkQDj*uQqpImeH35$T0JOhoz&)D(#MHlM7PLf9~uyKoA}uqRp- z*HF`g*FRW;!Wbj?x7YAP#1;_*<6tn$i?(aF_l|9Z=r7b?@ms39k8Ux&9@3N?^Rz;O zjRAg&jnXiw1=0SgF~J~(Cm6^=s#skbe!V?3&LpBwM81LshNZU1jB~Ug((6o=#z`$h z$u2RJcOfaIS}SV9hvv}e(I>J2TE8~s@M-%Td(7iPrT~1|tNeZ+lLwC}4t9;X_LwUe z9vsdent$s`^@EK{`c5`E+5E}#B#T8W370D07wZn5BF+EBJ6>#*F?a(>$#sbjQoX8mlMqo;d zmO5Novj6g3prC0<qLe_Z6MNxS!hgBI(`z;eT0Q4Nt*iA z%1vO5BXhz&v<&iL0)+DfAnW5J_QuygfQT0v_^uO>Zv%S>J`1~X@j;el;QRFV{xCrZ zA$bWX@pe5Ki-(ZlAc9~u7q0EM7eN8mt}l5r5`iCEklLnkj)i27^TpAK&|+jr;;FjX zuguK2%(8|IH4ssoGW1WVGO3x@$Eo1Iu_m`~0^{b3-+~vt5Cag+NA9BJPKiT|2PEJ` zRr8`Ti;3W-w_b7DESXO=)mgVKOPz<*O}Zl^e|f51F#fP)`8rW_I9EIDO)oEw@zNT{sB{~GjdwMTE3Em zo}oiE04a5IKBG*JZh&4>E`K&d&Zll@o2=<^465K9-o%zLxau=pr^9t59}O%Nih`Q4 z6Zq5_8A!#q-BxTi#t9wSG;zy-h488AICcADBj1rKjiD;MN@6c5{lqI4vKY6U%+HF* z3?-gaEQR_LU#shS;=pTuwv$4l$(h)=QXu>#6k{ zyx6qZU8n>6;u4W8v{#6 z+a1&HQHYjttH2V0R}=mPK2MC97rl^48xUN7Iti8I+kJmxdh4-TXTChTc2I`gXrLtAXP0j*4Sbx9tewM&%Hox}dTfTe9v$nqabT6g63v3Z3@Vy`2-@e12 z?{piqQ#n>21Ai@ysffLFUsetOmDO&sj0e>MouSTvh_Z3%W%6qf(so0k((J)B<4VT8N?VnD2){#Sc)kIg7A4?JX z^McJ5ScA5N;vMseUY4Ok#hh|MX4x)9DLLGSKQbQMjBfV`9uPQImCb6&9`JlQ-#us^ zG1EJ!Y1iL^$&-d*G5a@u_KwHD#S$pmSx@#MAJ4d%9yHz8n!k=Pb>&vEv(BRA^Pa=b zE(@G4l0@O@#{!O!Z(O~(Yq({*PeIjrwhl+-&UR<8V~&bmt4f-;-n+!pwihSg)Q1*z z=t;N4r`M|<_;S19|MD5_pRZ$Ir+wKtIR58e6qf(@jixOBe{M8A*O7_YZ*W|HteScO z_9pfTL-7{{y#Q?Bc0t4e0~9w*KZQ?8=>__j$U#`BC%s-c7rorT6&|+hC%1Yon*VH1RsT zzO!uc{7jGNqcaKX$b4|iw7I$vuXtgzYP0KUus%`dILYlQ<#nr^9Ka1OyzZ0EQZ8$& z>g-ij8tO1p>lOqjivM&TlmET#~1c|vwma7S-d!bLN1x~fL60s-4Gn7x;Bfl5Re z(@RO{NoEeUcD`3tKpF(q_P1!WcTR)P^lD$(CH|)%oztqzmXNbZI_Zg7=9wE+1q$=Hk%I96OHgHNM?|VHL@FfG z>|DaCI;43QOl2Wq5p^Xs^QUaXpRG}nDu0{j%vF?EXo^F^B6?!eU=C*eEg5GX7pw7^ z_U=Vk{B+L&*)P~E1K={e(Mx}b0_6iz?fk9Y0A<|EPT)8{^}~(|KpBPoJ{NqSS**aR z(3}2{C;+bu9d@mVZD`O=ZmBFg$3Q+eR5ezT6J7tt_EvMY!M6C*kAWE*>BrRB`$8H> z9RC|!kbzmth@(?<9_+q;8j(F*jXN53WCx-4RErm+Vv>wH8=i+a$6y@ozfS6pnj)vG?YsEVY5k&DwD*cP4d z3rJxzKK=r&j1}_dRGVj&;t0y; zMnxauj z6an^7m{7_jMatj*st6$Q@%xzmBX`OY6(N+}HHd%2UP46SsFo0tEC5n;IcE83Gv!tfqo@eWfqYQ?0~B{I;3JZOaF+%Awa{4V?eJWjAHYMHdc}zhjoB-ZkEt0+MHJu z0oAMYvGRY@72Oed{tF|1@JuWY0L7jIz@rDv&2XbB~1Mbb%C;2%ptXF~?=2Al;eyjt}?>mtaE#SlheM=1d(nMwnRm07-XJF4rd%a%Cm zmobSIkAoeIgV`j3&NqnGNFoPibP5ReJ4&kX$CHeVy4swcaqv+puFU!Fhv)g4A3xR) zb5CK?`93d@1oLJE zu&!jZZVtEqSxv}U^Yxf0TKePAE_v@Rt=bpn0kTfH+L@fPmrAN--?)<&KxE_mP1h?O zi4*e8sqFl@SOUTg-SHHfE)Jf9!|XThkI!*9qo|i2o0~qEfcOoScAM#!^YyYp2clne z;Y5Qcy_aM0_&pmBGRYOA2xRPCUGW2pGR|^Cv#e6P{HuLhN688J6G`81cOH)1hq@t| zhBMx0(&*5KX}t&w*TcEAOdJ1A;QhpUEfU^ewDTe=EK`w1edP7SGK1Qg;}y^_#>-)r zldg(xC)Gk8wd6G+W7tJ!)(9>Wg?|uh%{#LH5#m0u!aISNr6-TOJhr$O1W)EJ1&O;{ zdu52tLA~xLCbP{TqN`IV`d?#wIUO`!TE}==&&h%wg97inWW$wK0&9iP;1n~hIgx@Q zkpYA0?@mMx>TPb4c}i(`3xy#?H0RSgXbBkI2A5=kTDF<-`w5{Lj&%udtl!=v*V^6> zSh6?-#FWfd+ZQJgB3JFzW4jE{@dUzmXh$_le_5|;7nR7CdN;`s%$4-diN=lXc8k;( ziP+YdTxz&Gh}Ok?C`x-i2GZKAqu*Lf>1wo!oK>%Ucgj79dfBm13R&5!-X#kheq9 zR-FbW;iV-??l1UP5?g>I=TF;?KQ+QgZ{6$_&n@E8te0OAVw#9o23Pu<+F!ddn#v>G z8%V3l*NI#-&XKqjoW;Da&j_QTdbc!edL>&Peif~yD^t>G(h%A~~{M7!~mr~c(?)Z4Sl-n*kyh5A3_4RsR3|*{3^u+@UEOYn}v|rC8Sf4$~ zn&gj;H+sK2%UW1u5`ZRf}dyYA7Jo2ZspeT263XT7zXlrC1^B7IHOckS2bWwJV zKXU5oOde^3Vy?`aXFVAazdsqS`-*GnO=qA0!At!zZoVdF7IX55@u_e0XUD70J1^Iv zi`V7(h-*3wK#jef+r`gjlxwr%aZEBEcUQSwuA9W^!`5=46;Y0}{@O++FjpIh^~?#2 zJG|SS5roDF=&Bu%Lr+d`alCDXjOGs769<+U%;R;)Cq?8EA-(X4*Z2L1qK=z14~0L7 zaGh>D1U7<71%^pp1m*m_xSBD#a&?`C=fL&=yV6%S(Kfe!U2Hk&7ZhVe{XUxZg4I ztUua`VU#7&ocQqFR0t>GCE>iqWaKXefb+Anudla+fFblKO`f<+$`pH2CC!roQSfTQ+%uDBhhlQD6 zC2E8y92xs*wL%}?OXr9Tb7R7L5myOO1Ti&LtOwnB6i&?y;b6kI{2smXuST%8a&^?6 zMAJ-Y`+2WJnrxz17hR}qzBnUmi?7kvUapHRuV4)Q;DhR%IU@fP8pF@XOt9is`JcC% zKS&%9%bI^nW@UdufSPl&kU-#lHEfq;JaLMUbYvQ zV^U9N23@=;HOSq0gNG9VUA&<(PiobDau!>eEa__6mA?94qo2&xH#r0_uvx>fDY1ucbC7T3{vF8mhv&Tr@O`FqAsv zlDs{_|Ha&L^kOL~gIIFyHYy=(PxCqdQdlg8lCcV4=THLc;Y^!hT!jYbj5w4yZR$U8 zzls}FrZ`t2L@wnvX|ab$3l>|rqR9n*{WisNxVuD`q4@(wZBoT?tyWv{2PuE<6tut? zhu+at2qSKWC4HXCc*r>%MItHAaeuxpRw710G?(0#s;KZMm4Ij%8vDW@;BQOsd29<2zY2wQ?vtWIi_Ar2$oo%DNPu10adCFkuWo$j#h zD)uj{hJ-A+Vu&N-@*X3n_0Jq3pP9XN4hvDvrha4jL#N_*t_FgcaH2pTPOW@`ty^+- z5lGSz;j-_*at25qd`O8QP*6rU)LcV_$k(o|+JfnR)rX<;TiLv{n&f3jG=xzM*%Y;S zppNk>VOU6_H1Y|{(ZJ2aR6+1i#Dv94<<_AhGqsZsnILS#8WH%Cmea9)=f{2>zbswY z?b@scS8eJ(>!%h@``JpD>2Mz|ZQI!Uair>2Yg1$fBF_bDNljf!ZQC$s*%i%wjdEn_ zBH1x<-=3o#2| ze1Ap?*)P~gy2=qwHD}e|qJ(4G2F1hGD&7{F{=xQZh^&snOJM1?*RpFW6Qd$t#iLjw z2$>Jfq`^qQwgzS!v`3P zXHHOw-qw`?+bn2kjIK5#rsR^LpMh&;Z|E`?0xn-ukUkwmb=rn0{hwY)nHPqEN)zYjh5;D~O}EM2p!dvQXH%+1aQgpNrqU zkYP;I4SwI{3}WF4X1f0d(|Q5n8PA4|4L=WU3kC7=Tf<@I0tVcK(= zZJ}_cY0IuIW-Q|#NG^^B`QFgnKx^zc&YQ6^L?}-mb$G0m*<9!U%^V`B=UB06<$_Os z3_YP-{Ua{wecQbYmRDSAab~cPEN=Poy2`b7nxZ&bBGuIUqxE2q#rGAf>o50butHT- z7q}nKj2XZA=317EoIm}HY7F0Rv`1_j?drP8D=shLLg(-{sf}YUUaspSIM8q;{p;2J zcFsMmIrVCq(Vf?05PUO*uGLcm*vd)+sjep%=f~JPQx=g?dHVqH?D(IM$d4m zuj)6J6FtmgBp*s-U+W}bv$TRey*|gsPBu78<@JUW{Wo2ee;h^Mu*ZHB=E2-BRh?bE z*3L5deha_EW8qAdS4gFioq)$GRHHJ$Trr+tO?PyTVAzF>abm=XS4DffbUwI{bMo`g zJXev`y88)lXjSqwDR)6`0_z(2)Q{O{kAp}u*0F>?Rl&h$AbI7SKR)fR8A>qH=Dx{I z4$5~o0UK|2c~^8XJG|lh4O99|k0V*3Pb$xPIUc{QAg6#F^L};u7Z0#zAvdtj~PqL!ri&71|m3u zoKlSAP}b&wI_hv}v~$iwM)lz(Hlfq^S4xlIbFH3@V7x=b={)|sJ9NRgCRIPHce1Ls z2W$7?!o&Gd@6ETeLzmE$Wx1H=C0yJM63Eh(Z!A1{oQY^pu`7{5Ke0wb3s-jUr|y{e zhhGsD_(wZFzaOQ{+XGb)1oj>?^Od;_gjZzH#|!BlV3rXyzjnQyrx+Pu{}NLRoLal#v|0=^oJHbs$@G;yY+e=W7sA8{b?>ysngh`iDP5 zO41^vHBOD}*?L86_U**LXHb~l6JnEbysG>uj{JoO&Uek?f(}EP|BOZNaDVnOqs--= zp6SDvM-A^(Oyqo9ZR+WRj&`us>@RGI-0qJv$CrXc?-a1mP)J z;g%@DtL8>Tg1N&-|0i9ibDY!pLK3Th7Wgdi!keIlOR*@@`$%dMB;KXGZfKYY zEAsDUhOE!`aW|GM3X{;LiFgZQlwgV}eW+5WHMh(g}AYtdoGPbJH@#==ATu_v47XYa-S zT|22sJ>JjDp-H`|_Z*bFn@?mY6CzdW$;QSJ{dqml&V@%6-v>n*^77mQs-?cd8x`8p zQF=Be@com+8Z@m={p;<~o2!f5ndf_Ln4{bk+NbAA{%)W5GeMcb{+g5s=O4debSib7 zPo|~Qnmcztj+y8dti2{8zr9y~V|e#`t0#Yrefmdaa5B{)AY z)Lp;Ri+a&rn7G}|WIksc9`d%_Yf`66&_El#9r5I(AM(AJBzu0n6qB*Mx>pOq-Ds)4 zP*&M^ISwp3?09lwi+|mDjHhkY7ORiCEaMK^B$zzLdGV#R$-=Af_-uJ2aLSf0`rjhq z|H*L4%E7?=MgNM5!?674?xg?YK*?9$kN?jkAAm?WUh6MFB)r(!?}E~M9&*aO%cc>t z7FM4yQr{)snBfXXf5Y_SLwqO4iDLfz6tL3`ga^wOQ)TD7hyt3(`l@c$+Kn&bXKVTB zpRAeGOh6#~(TS$>V;_*&ME&Cs5D1^F^7UMrsd+u8q@8#r9Vnu8)%bV`g>*f0Lzc6B zG!XLSl79U*eL*XaQH^(T+=fC(Zwfra2OIkU3vA`KQs(zQBt!~)FM=U(t|DMF3DVRK zReZhyQn76NqDF&JD^knjx&#c~CO(Z|zW87u0K)&3MV-aE9{&%;zFM;s66)F$QrtP5Yz(S#LIHz`zde!JG>-QJMc zmI9vbjY4>i36k5%7T1;{6Z9}FJj0iE^tg2IdG^BV@{Zs7v2VDj8DHxRUqr8@D5R=t ztmQL2Ns4A-`P^bn$$m`iu{WsB-DI6oC1qOSO(i0rm;C85l?`c30BFp{!%mh+x0RaK z#hnz8JXEq}X1+BNayXC=1N0UJw^0q0slCY4T-jW+-5e+c3_Q68w(%Dznm0FXwWw$b zZX;}^s6HurTu_jekgbv22o&bv0xhLZCp%Fr8$I&Z`S2W2;9qWVG8@3ZTp)NFwt8|Q z>XeigC753>{;K%?sx(Ya%ddva_bv%xka;d3?V6s;bn{EuP*GzQM}|D$XuT-&Sogo6 zzDwJ} zVs6R8;SQa6KeX-lb)5s zQZNiS{QwSoQciYr%6@?xsDq#MGk;e}cB-b!?rO5ZMDq)ib6%c6P|oUZy8Ndb0yf%^5YX@TEKFte?C(YOt0Np2stKL@LB{RE^ zX0B+E+B*mM27L+u0<~lVeXU6YBdZ)*USl2yui(1$w{RX=aZ}d^8F)NLc(_cWV+gosxGlf}b0P|}&`Fc_(25S64NB1LTH zcM7MrOOf=S&PR_^3JreFmU8m$O)z6nR79q9KYCZe^sS-$Fg_-$2utUp87pe(s|TI` zA8K-44Zu+5GZ8~2y**x~qX%453&hg-`9z90Q?F%otwuU7(G(8+0A-M~P8^>QobFOk zCY{|N`nDl;WG7qFaTR7-bmf7F_>O)rO!@77i<*F+1et!lT?Y5po>;9Y+jYxL5S)P_ zj`Go+R_ZMA;kgGj<4+djDtA=b^DiZZpLdn!J3r-&h{=wdECHmSm$`FlV1g`?Y^slz z48j6Q!kSb&(r{D;cluoov#nO0Xd5EHE_hv@g!u}CjB8;CWmlNffsii+l`rK)vVn9Y zO2PP>E>S*VPonMn)Gv8O5*?}>iZt@;uU^Y2$BNJ*%b?-xU@i5OgAU#l`pON$mfs8= zYeIEHEra=$etYixR;t2OxVFeq+}3{HMOl>hBC2XkM5bz>DP&+&T&=A)iNf} z;Z{ZMR}%L_!4Vsn;MP=&2r9~�^bi^9}uI?nMC=fKMQxHo2@I21zr$O8g~k@|wh7 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

    *`3cP7TnVwhx@5b*9&k2#TevYouiCF9 z9vWH&f068;>Mh(ADgshGOgFNXH3gwEHM&mSow zQ^+OT`O~)Qok^NC>6H9vLCMxMXTOz`r$IL_+GLy9>b~I)dGF#5<>&RoNsIXlggH7R z3x{t4Ys((eM1yiy3?bTGralgB(t?eZ;BGcKCxN=2Ct)?3Y^vd-p-p+HZcvn-Cfge` z*}IN??RC0*ztaZa%qs1;5b&}2oGGElvE^(cBdoQ`8u}ZzIhJF$>#QKq?c#GjV;&e~ zXV4UOi{p}$bGEGzoR9)AmH@gXTygk&WcolqXMRescO#Vqedx>)V

    yMn3LLfT#Gc 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 }nrkC%ot1{Nwx!P}6zZe|sGofUz zv&TvuZ!)@I;n-1I@>Fg#Vq*ATM@KIBYxKr(X9DXb-MT4n91uHv*@(3#YYl%cPdc|X z-moz=sL-vc6?asBa%!9W(e#Qtl2)9Jimhy05dF!5TV(=I^lems!(UYwoSxXM@bLbp zODw1qUV4G0;b#k~9I792`*4|?Lk?`Jyx{rEjq{3HKigs1JYe`I6XlPFt$qKSbH{Rp z_32Tu(B_DsLVuYOhWFk9wd8j6f6=$l=DvZ$6F+>>GrVy7?*re;H_+5hdVk@bg|qwC zH>R|Bcg7BLvD`cQZ(4im`X9mm5f46HAK?G&dEp%!)-}6c?uWoV#rH-1wx`+Y%WX}| z7L^_M=iNnLbc^~VZu#+2M{@hMXti%k=WY4+PVsB^)!Gi%_9Xdjym!Js&!&IREd1-q zdH-dbmR5Vx>h5om6&vKqGp^sVwTCzDxv}f%m4n&GRg2wUsmZMhbKl-o?WZ>n^tsq@ zZ^_B`tLoiQ3J3*(!V! zR5rL~zInTskKXf}Ur(Fq&-W7x_`g_{obQ*XQ<5h)&sHUSt86h7*Ali<gVdZTj5p6}dQmuE&q|FOa6Tb^xP|5WW4Gw*JS{A|lVoASnF z8(8!F&leBO`s8l^uKjO4Y2Rn?po&dL#9U6P`+Mo5E1Gv2W+)$>*djJ)={LvTm^CZ! z!lpljeVcr(^O}#wTZeS3Frw7{d4|0o6RxNe$JVAsPx`{O^Juf?EZIMa-q(v2R1(6&=5Rl zqILAWC4k?%Voi-YXMQ%yrIJUU7U+sWnZO-z=N>^VX=mCx1-N zKgC)sE@tw&FMXmO*KPautONDh*6ea}e%=FLJ^!qf@7#tnPE~5@GiYF`s9txWUe#dV{a{{Ik}&-}tQZ z&gHh?U*|07cYSWbVWn#f`0%}vXC^(r`Z(~zb#p2nTspUk@$=IKZ_c>&!y~TDIB<4$k-zRIC2noh`uFS8ewduQ;Dr>++c$fMF3cA6tiM!s@jK6JH?34j zcj@05JJ*(49&zQ#7m-nUpAR^4eR+rMvA6pDn)JhfPHRR^Ya1!WCd>IIEZ>>@(dI#s z3nNA^+ZgE+TzlLZ{h^=d|FkLSW$)J0Pb{3a@^IDAgFol9<@r4S2W$Ey{62Kkw7ZFO z@(*nJ=(}ROat`d>t4PNYFU?oq4_}czZ?Px82c0t9?BC`3tO1t%3m+|S|6u$0dnbP^ zF#TEbt>H#p$wSp{H|t+H?vdY-m%crBG=ACp!p?sOEys`1F9!U*Vad1CR#aVmd-k9n zH-De`eDuRXUAl!|zR_XHOSx$!Icz|;GnVH=B3VnbN^8+`c-uyXf%?~Yui{A2i_~7=R`MXB`+rOXx!Puy%4t0jLJacG%&P_k&&sod=n;A8> z`9wYMSjSrMkL^t>e7Cd2;Eq39-dkV&@7o)yk&{&CpTRjqs1JsEhg z<=oY8beg+)YW}P5bi4UMZF54e;gxFCIF@JM$Te~Lykpkq=&LaHZ_`iIF7==2|^G>8<{+e-qca zRkxG|fU|<(CGvY_T9J;>eT=!L1YeJ{+~6+^T$gm;JbD-kS4KEf?Jw`|wfod+o#W zn1A#uyy$G+4%ULX>TD>oWANCz*8I0dMkfwm)v{@;heex=hGbGD#^>m_YRZeQQ)ABm zP*;Ddz}3Vxx!)aH;@pe6@dHW^Z@6t=*RD~;ntylly@GG={%*(O7(@FrTN-p*bGy*h z+oRriD``j3>EV{xk4_&u@WIie`GShw@=1QH>Cd^JZ+g4>jH}CX-W)l!S48-%sK0l$ zY^!Vc!MnqKClx-|u;$#T+%>mnOWvKmeX;8^M}GUb$ZN@eH7L}3z=|CK#dj3T7yU*n@Zx31 zSD$hF&*aXrzfjJRTjKl<-}rX=+(iWzf4u15fRsTkH$9Ab`f-_mZe1hwz-ne_WO5wBbE;}1@zvQ*rttKRWesu7Owh#N(tp7oq z>OMuA6izJDs$4?yuM3t0UeEjc!-dPrwW{7HU&Ucz4@&P^q8nDU^N74F_nxZv=tby} z^FfOagpT;tC-B(QWBTsvkKLSbX4~)&Mnzuz`|Cluo>o42Y6(~EnT zk-B9oQ}<@V=SQ<$D*g9w?CrmE;Te)pl zs<)rp{IkoGBkKL~?EHxfHxeGzsF4tMH1bBiPB$9g*phr?W66I;Pk7n%-kFtW?iznN z^VN*4gR;Nd_j;up!$NI6HVyQB)M;-f}v@ul#_5 z4-U>B_4g-rS{!{|=lH_0Rlj(U-1Oo531gC`9n~i}LhIYA>Grmxx!yW2nFSBQFVx2=x zt8J-2^Vf?FN^fcSdr<4h*ACYRw9Nts)!i%OX6cJJzqEVz%=>)@JhwJ&UjA^SQfC7P zEWKCZQpp1g?*)W4yc1J*;LxWpM#fHDF?z(j8x!W1wiKRQ`u&ebbv-?5(5WA*eKYHm ztq&91lzP2;{6e&}w_jl9$^J zEPu4+=x%ZMy7h0qzUIN2rivd{2#Kwdvwz`RKrS8Ci1pYXEzy*YJXlz+Nhe<$?OCkJ1?-~X+Y1#>?C zc6qTC;Y06K8>(+RXGf#rV=rtBTX^wUp5%fpzo8r}iI7F1qg1V^fmH`y83Q?vvb0Og+c1+?VJ-b9Kpg z?=Byc7_$G!{W0}dOi!-9f6)h@t-F)gf9jR}*>c>B(!{@? z-_6zPS&yW@-+sH<=6G_^)tDa5@?o;kr(dN-DADv&)I^T>5c{Z%CKf6=5@KN)A?A#^1b^UW4T3;@0 zPHKFvL*MEJdT*Ls_05Xe`h7fU_>4;5E`6(LlP3kD!*1l-A5iAQQNDt~ugsoB zzV(-t4JMZ)N$|OOrR0|JHinHzDZqL-%TJ#jp44r{%Ju6@6FX`YgQY2nc; z);1fr>ks|GM%UVOzwOJ+l#Xi)-5BuJhSME)ytQFR z#~itP{o3*Nm4>y4KVKJEcXGuc?ZSR(@z#bD9ixY&6zRTtTj5+sy6VSmo1UxJnATsN z99O%}iarn5u38#>L=LWA;pp|1v#x$oWY(ptQ)ex{_VTq|Gm9lUbb~47^USiWc0Q-K zdR|@Xd~TQ!8qqnVPHaeY=P<`!XFYhZDp;TZm;`0|bP{->o%x+@X0yugYyh9Qs%#!S zXmI3s26vcVD4b^mM;7n!F&GSKd7j5tj~oh~=iC3}i#t`NeABs>_eX_o^WU&wO*P%8 z^K&1rSMb8NL1(1M;H$+4fBSgz#en#eRT3^v9C)c?|AzX0v0pc6eY`|2Yu~`IH}{{6 z|8e8V<24ryyScX1xl;!VUJtrvxjQAf$jp!16}+?L!I+{e7UpbJEXpsbL+G>Zh00W) zJN>PX#>O64ndsN0_N<>8TuFWuvEl7|1^S#RQDbsK-({VK>?l=uboZ_`S`?_2{o%tC zrAt0OP-$eysyV|;wSioWU2h-15D$BtfhWFfH*G<^*;QH{EB1Kkou}2LSJ;D6*v3D+gOzB{k)&g;AL`tH2GJFoA~>$~&%?!3M`ukX(5yYu?)yuLfH@6PMH z^ZM?*zB{k)&g;AL`tH2GJFoA~>$~&%?*32t?uh#X!7?@o*wg-A8t z;p6q)#l^>lg+!%>)=I9U7zN**W0Je?yCb}&_1zJ=Y2)rB2XS{0cj%3~^TyqI%`=Z(Ab#@%`2?!0k#-nct&+?_Y>&Kq~6rFYlCyB5lsYdM?NCn@W zW0GgWcPGZ(Nn+fcm{nr8n-bLDuoz5$_J?@bSjor5$%?$Y9)^ zW0GgWcPGZ(8N|3dgDUQ>wxpA-=y446t8LK9P)3jZDMO(=)@szrHuk3pIjNA)M(Qgi7OL&KsH$;nHu~X0NPl0$mc1WmA_^9o4p*uK4p{gHvly$ zeatXe`hK6PRZ~-y$`~|=E3a~8Ka6w)Xw>=a*Sc}1ZegME&|WXfs3TPz;X%J9u`!{| z!s3Jdn$)cA*F3CGJbWDz9_CMf)uX>^v{M7&J@8GSzh9G(*f0Pm8|eT8!{TBRVnf5? zbVf3yK)-;n&JiIsV)_K*2u(JV&T2HY^Q#^m9TOiH>|-Dikbydbna~X@7}kl6N$3H? zZRXb;DqhC*KmehA{rsEx)eP$u5gHa)r-olWT|7i^R;}vi54ZySI34=c164DE!(sD5 zT*#gntYjpdq?0JJ@SDuBPJ;4_03Ckg6ya|&8u(2p2*1g+!*AjqhTjxf$;94AsSEAw zeP;GPGkKp6ROO`arQCrps!Q@Ki(-k}G?JY8EyNRyGS(HValZ3v}`8BrBT* zE1Lx?qmq@)0$q2|kG;>v-e+U)v$6M4S>Yqu*!zIz2~}+DeKz(!Dg$(qjlR#Ir|&c9 z>H7?N`aS~{LplR3!3w|W`wXW7gBJTOcN2kv~BjN!KHVqPMXNyE;=(~>&d9NBBoL^6)W1wqWCsV4qzlNx` zQ4QCAfeK`($3&lji6ogZo7=NX@7Ab?i`?k(*=3ScW^2U#;gU719xig5=Z8zQColu$ zX_+Y+_lHeHf_m5}V>~}>DtTlkncN;OH5F9Dl~MG0ez;Up$V{NRKU^X})x$-yd49Nz z8JHe$f4Br~^>AN>ab#ddj?C1T`@<#bP&HhrX#Of@muf+oX|YO+*hOBn5D=p zN%x1#Yd5kn@%ZerZIXc*!0r#1*J?z|dw#f785@}0?)Gr0$)sWiVxf9|xKs%n*mlGH z;qqFIh#JoimznEym*l?POZU9$*?lEi%}C{~fo<+&_E|PkG~AzUUdxfax#wq_tZ6wH!Ig@ceMu4xOC{xIbK8%aNlB&kvVrId+iY z_HgL|ii#P?35w^3%d{Lje{p}fyp|&eJ02gd%#Lx`v61`3<+U8)F3%5_X*qV<<@Rvt zQdKbnk(8bvF4J=Ckk0+#@>-5)dCw1*X*qVb=>Bl|y&JJmJwIHg<=By^OgA-fs!!#y zY@}+$eKdG&Cy`yE=kZ|bjvev3Jzk0Kxm8>(kuwg@511)Db~c@f0rMJ9A}4j8A23sS z>`*-u1Lk#}WUsjB(Su8wDLv-HaDTw`7+uX0LVZ9_xGN0wFidA)&KH>+e+0U3C`T!gDXVNs5sGCVMV3Z%8A23sa%y-W;P(11iRd47hO z24t>Y_XkXl;ME>=Nyb-ue!xrvG9R@};p$|WnH~gcAbh4KiY!wWl4WWT$}(NVnLt#~ zoaEJ>N0ez!=9HJ|n$yYjrV;#R2pSlIY;nu<+6a74_ZKqL4>D71nLu37z(nwQ9&x6D z*{uYb9c9bx>W56FB_K%q$u!nJ6AF)NOtmy4cC6+oI*Up21p>EIZVb^O2l_RFyGJlavf4EmVT)!|W;;Se#!-ZfR1WxPM~tKN zXCs7Bk`dzQ;D`Ke)$5^)-e`dzNv}5n2Ka+*7Qo1i&%g(Z8U9Ahls4HJc4o85A$Cn- z!+O~%KvAXEg$7lXV0B1<8f-`~6hZ_xJS2)TRDup86b{)=6hIHBg0xkK-|*S~9U&M+ z+oYf1 zfY3NY8OPFSn)X`Nw?g`JQu3``}0G_(}4z@cie`2Uf7RK2PMv267Pyj8P6_*PlByq#(!yCN5} zU_u5`(ZW!Zt}|pp!rb^BGL%Y~W*z3{XUAx?aDtr94qNZM$z)WUOjLFo6{$we5XR|L zWpkVkGezV#E<2nhT>4BT;0%!&!)1+27W)!WpvYr(wKz=$%SNsi&eVyeRzd1J7LHU9 zYDY!YkfAUsM07r?7gQxMbc@aD@bqTw;-h+yv7Lik6lk@$Vmp*`iY!Cx1Sb$#jL9?S z6G-KydU8o$c#g}gh1my$ zQX1l5%l~jHh+)TUi&r-#2Fa|oAGA|KjaD`#M9pfZBrTH(sAvLm!7X%3HRKLlUdXFR zVWc+xO_mh=Mt&ydkez?2O_I92WV2RmYKJQl4b_Q;XsLohZSK&^5u9Lf#fxc<)GSL{ zUZXojxbly-sAk#Gi|d++#j$CIt<`x%5TGdmL&W6(?@N{LiiF4SV3`fpVb6Q56UhH3NPnY9wjK_XSMZ07n6p%XwPJXx(qcUB!DS3YQVnqGC)mupK~h0 z9e!7+34~MMeq+{#U8>N#XUyE7mw`B`f>c7v;4)M#MY5Mq)m+2?RGEuT_U&x;)oY7h zm{QL^8I!BohZ!bo2iFVEJp3q|5R?c+x+rT2eq);fnFSRy`;C8-AN<~Ke$eB>R5Z+H zgH|d~(Z{3$y{@Pkd0OTNjsQoD7@%xJ-hg3{QF9W)>4>qv(-9jDCauB5MocH3QJb!C z8fT;#ei|kN>O~ZzcAbbQAUde_RVJv@p@SrFK6D5%aX8s*=xWtYZw+gPo|bB7ykZwd zz|wZv>*9n14|Zg&x`)um(|LxI_z> zI~6Tvc-xIUvtD+!=G4ND#_nm*O2d%w1X^U>q727%3KT-ILzth*b2~G$K2E0ssBhFT zFh3O#tf<`xYZ+K=V9@YI%~YgiV8FPDxWQo~^CBuZ9FVGRO%pz+TF=S`&MEq+GeG>Q zIDxXPofAxE&c4#3uQobptdR!&w2Tghz6IAJ4jXvdPXWwN>J+f(a{CmR`STgg6i~u4g+(JRHB*p=wdB^C zb|BH+LLEh&MwwBKl&Y&Go7IK6LIX7w)P;RMiK2BueR4bs;)ZPLa9u0Z`d^7Upt?-B zL)kD>d6kO3$s)Uu^pw~N`b0`H z9n#`rZK2&shL32m;UZJIg$6w691Y0(;R+44l|p%0g9h3yF3_;M#`!gcOvx+_WKKlQ zDHVXLRKw?tEO^?*@ae=erV_%9jHJcY@NxE$63AG%9`J7%j>0&05s?veGy zlI+SXX2OKpjP$yrh8pQPpFxS1k>LW$sk6^g8rfB(8H^m~`h`xoGW&v-S4Vp}bPu9* z!Wn1Gqc9Uuk=TyZ0X2!=E0#Jm(;YjY=#r_>YOrg58fukF1=p54%hklFK$Mb(3TbG5 z6Wf+5!^d@CA3j4l(llheDQQqlf{ zK|w*V07!6%3t{cnb`Zq{prqJ+MCGDrz;;}VNHx{>E>TB4W~UyHIwX5@B`MX`0@Vp> z>Zv0)9ZE_VmrFgx))cY#7+ORLpdvu@pv@(7!uRmM3-k;wk8WvP52LIQ=xHP^E-0(4 zC8ugw*-J4?f~P1ECxE760y|uPh@zHx>2|}e>s%`ZrpT$pq!Di#3Z`|Ikp>Eif^a%? z-~bi#aYKhNeizI~38GL(IEzrn;W}bIV>*YPq4k8+fFBh~bcNWdA%P>yx%Ev6pr9mJ z9wgq=1;Z%}M7Dgmwh%>NAYA@xbcs_7B_pmQS7t1tgTmh~9%!gyV5(>|SzVGyeb_*Q zYc<@JmdOF|iF{xRh#WM)-^#55GJe)a+1@JTBHyLQR7V_fj-2Bt!|}IsYmo-wDl`*p z4t0FBBQ{J^NWkJIPHDsi|3;d50%v%i8fRijq|()F;GFRql}Aab;4By+BuL#ApS~)b zG^&gSeX4jB1hy+Ws?RWJRsapJreTRFys7Y^BkM!Wo5cFZHHtXrRl2#e%IQ}0R=i= zl`5-EaQ#gaO{AeeCAosPU?!2&L$2uW!FBG;3Piib1zly6EB(uMEL4ust6mzqrs0#x z=nhh$omx(3MuuyT-6a|am`Yn`SGDMQ2hAI$L02%TWaSDz%{Zpqi6eF?cP9?WKz5Q$ zE#cqrKQ%W{O(82_AN&0{iH0Yp4%b;=8@ud8Vgwad6jTlwpbJ*S2sI*x+4fI4dQsFT z85<0kw4<1IWBk11mtNyjhAdb*Bxc#5P${&Ph- zAOoUg_s$?XsDRQ~5!{B)z@HsyE}*N~3*HYSQb(E77R?xy)oh}fMd@lb(Il?iYDPA~ zRjYD_5wf5%L6R_h$fkm=EP@-hE4LxxS@_DnkyNdG8j7CYl}}S&syK^|UxS+VZhe}^ zVlYfHT-ZzC5G{JerB7q?Rd&A__HSzaNT-!W+nR*zHnhdX&=ix1%p99dvem}f##v{6 zapV>?2boQ&L!`#H-E@(-kXdDjWRWVgCMu56S~Hbt_)p+vRBpq35$_d~jmQ}aClJn1 zPDBU}_OY@c3Hw+)PICdlXBJ8?vCw&DE9jUKhTjx5n*9U%v!n=YJ-}y*o6&r{#h|^0q zct(qgt0a=tQB5{droyjTLZ|q?J;MANMnp&Y)rg7h92QHeS%BFc2&FZGtyW)y&I|{4 zHYlZF1$*2g!LGXf-y!JEE=;Jz&iuXqOvuBRU5nv z0Hz4bxWksf7b5A*7!>OSt`bzOfvb|v8Gy?Wme3c-5Qc4@!dHBxu7$-hYXGZuJ{bmV z0w<&e>-*qLy2& zJ%L5x>QPidVj*9%4ub^kjK#rK0#h|`Ga;~y#9ts;@U#x>npD2x&vKaAtcI(;KAlm% zGQt@G@D;q(pfg&)XQ9k92Um#~)xdR6WRZC`!orjw<**gz8EL3UENYvi(pL%8)WFSz z#Dc|DjeRl@Z&a5EvTAmcc4703%H z`39zz!c{z6CDu*@HxtqdQr!VpAw+-gCJfLtz(sDD zZ7{YJzT)93k!KpXnUGcn&1lq?H7A74VgWX0(LYy%c=OJ~S1s z5^bb`>z=$Kas#%4Kwqr+17-T`)O8m9qJfH%)XnVzTE)P}fTtBVrFQB%3q8@m&4jdq zO(+l-3^o7@n^1+g&O$ykU^5}C(7FI_GJr*AOEqwuMQLcDW z=a`481TAQwWKYv5)= zOqn6<6?qCxD>JA2NVZ5IS z3@nAK`1{DpH4+WnOh_sdHEV#kV2h98c1-#4aFwgxYPjl~8X1*TCfNLe83zHpCY=e+ z1{J>I;VSp9HE=T_t4xsF3Hizbd}RUy%g$HaCPBFWqv(bX?7Tn;ObVe|+6u#o&Dp!j&_+~;{;T9jHm5FS%K?y5-#luzZ z{A%E4LRvxARpcu;G=ehOsD&9nGvA(FZa7*;YL|D0=UKvQ5l|Ty=NYxI6S&GPS`EIL zkXJIvb!vb;ff2Q^0u?2Z%IT(Dbk#u3gtUTMSn_kq!cEG$MWOp?+fHNVm@H7$_3r-`!d`4C5 z46t&cQUf>>5(|&XKw??x<_NU00+_$?=3pt&%Fu4^Pz-P$391mN3*b>5I|Hm-Gt^+5 z37Li32sXZOz>eTSA3FoA-0{-@&VLXw- zpfoHh)X2^NE4SJ-fHNVsptLwrmz)FRsdg%JaTqJt%`|{BA-NgiS(*_s>O`>n- zEdDx@a_2`g(U}li^uR#^4FL{*)sX|cRFOK>%1s^(;LM0ESj50u;1C7(B;c)xEm{>l z6|N(dNQz5je5SF$3p^@=Sz!bf;cIQ@S6wMXRXsF5A|~3enO}>*diYa1DkP$Nd`!jA znCSSB(D=`z6CxvgBVx(``kEPVPmH~Skq`%VmY5S#;v;K}#68LPDyZY0EPNFsanGuI z6(e!a%zG6haZiB0ijlY{QD4PK+_MZ{#YnP@j3rf>vV>$)mjcSb`N}Jx4kTKe`FuYx*RM#iekXF|63VL?uup!K2axh z|BvS+%bdrO*k3oOL#}g>+l4aRfV07!9bcm>&q~+$_#SZ;{rs3q#gF%?xEVl#7yi)m z54X`gG!8fAtH;OTrUmQqakwd4Jv|OL15iB9ALLec7FaLptl1fnWge%Cn|7*k*Ag{B2U!`l>f_h>t>XU$K|Oy?eKp(A8wwudV0O66aD_D z^N~g5DM`+n1@x^t^X-31mn5@g{DT(9B3UtXL_NhAO<$t(W35`2Jz)q5lptpX39N+p zcgWWPfo4jC63au&LX;en);-aOfsG~xSAu*fFa{OebP?A*S%-NkjXIiYj-<*`<(f-J zq8&*1MW-t1)A(;%##dGLd_t`)1l%bhhUr;FBwJ|4!P1E)Y$ZdKvI!DH z+e25=1=c;wPR-3^mQ`SR>N=cc_e2#YnS=0L5{@lH8d3;ASBGP3VpknX4U#)E+PQ2f0sOgazAXVM5<5B+siX>83hCBn1;Z7B*%V*Yekl{`yGvXe;EDb10$E{8S z%7b-~&=2xEW&&TL_TZKQrphv*R$^iP>BwLR1@znm4El%aBFIFBIh-;kCEbh_qV$F0 z9z<4Ru&xCY!Z^X#L25AB&CnpI3WS;u6Db(sLWxCZO-)Y1rx;M?lu97e@ z7g0tM7&wZh!AlJX`8Z`agMMf}Y?{po^9z6`#GrOI%{;yi(%M2M6Swe{NofYy#S{H! z#cMNIZ_5c_2YGyDH$!@u7Q~ouFzGO%zHC)77Gk5yx8oq?s!S68XIyYlbz}mK4{4kr zvjOB?hm5a^#m>{%A>hoIR}?VS`>p^xQc1FVG7EFrLXsWGX8_4qKrz9;kRL_i>hxH4 zZieGfz!qRGFti9@6eNo9NEcxDOe_i*N}V8E5x}@pQcU-B0d{XYC_~zQD@jQWS*t*J zK^7^RB-pdO*s zTgw3<5&oT<#Mh7LQnPl~fK~wwJ2!6Bs7{v-kw!x;zp%~`@t<@J3+WsY9bToYZ&=sP za!91HXQ%j>uG}3vNWAZ+%pgb-83~1K5J@T}|1%`xLgk*e=#aR$h?qVClJ1$0jFN~L z&=Yg(VZ8?s6aN{KE-C4z^oJbVAo1bE0<aG=WRx=01;83SL=L(pDPB?y3GMD18tdD)hi`lge^u24 znLM?ovwui@NcWg`mU*jHO(KN$IFp9N69XULRPUzlUNB+@6t(wLO z@!cb$;VC1nZ{q_su%g3DcMhvivsM{((h-yTpt*WNeAk%R%C&3NhT=y?EQy76qo8;b zDbR%FuCOv2wt=aHMUjkH*$nH{DkZS6f*baS?@5s-D-=lbj|~fnx4+f|b*PjgZ{)R5 z8OdURZcSoiIwypN*}-F-B?Jd>NPp;O#M)6<0M0=XI8vS%YTn8CE&>u#u+$8R4=Y`> zBIHE3>Y-wgWRYwJeL21KnO^@HF7UAE&Zzl)`oxBH@c}yO%|3t?`w#M}!Xccli;lFx zCd_643gLgcXxfH<<7ox{r)q=J7-AbrMtGS?-3HzPJvtcG zZF&h3-+;E!wt@Z1^@C?kXkGICFyXVd&1mIez_T_?1j_ZZ33C7&G~_#VKky_#UN3E% z9{ORZl)9fD(thKGdUYE-E92%<-G=?}5|6gcYQuCs>Na@RgwjRb2JB!%TSU`lfd53e z7ED0H_k#ioT$_<3u~PQ~xHeqT>NY*tYZz*(ZG(cR91P$LJznVJ`|;z0qV`Z_SKAMs zHDIWf=2_^6RnxU?P`z4w)`%NgzMt?cq|`^HukHtM%>usA4+8+OD zcM4;+8U=izAC?5y!nN3Vz6ZF#&|*KlkfM3k0(r(bn!~eJ0bl56=HCY!aCBs--v=Hi z5Ww0tkoAyLm2WeHl-0Juvrx=N+Xn1n;rT#s)tgXlb8uz6q_1wnet0oT+h)|`;gh-z z-~uOT+w@i=upr-NG2@vF_bjL#ZJXX|0oB8`fyBY;_S~~pw0hKSFaMl%{^tpX2$ zh!F6A{QwpoSC0h_u_5ET&<2Y^XfyJ%1fB(BROn~Hx}O{jE1oTKZ8nnt7X=aD56XuM zFn~z>+=Cw+57o3Vz_=CL%>10fIidwG$8paJHZ>f8>qQulCscSAd~#wN9AEJ;3??iH ztAz_GG{rWHI9CR%I9CQ6&qJ{LfL#d>Lv}!OI6DygL5_UkS%FV+hvNW-m0zpS&t~G* zFRU0aVR#ru*dz*VAQFT&as9$l#a+5~PK{>4rjdc2#eO!yK7~y!9@=Z)XChT+xi$j^ zx^itY1{ZK`u*DVHU?U*3S@=B@P{`^4hE0S42Li(T%mxt#=wz{zK`@TjmBz+~lRF_iVhOGVoGv%ro&}QLnBw$_GS5z3^s`|q91Xv~ zv9_?z@u)z6A@0FsC=AKlb>oj;m?eqpRnhI783?8Yv&&Hf`Er?732YEZb63O z_E+F5Kv;kQ?qvZ6oIMD0Wi<1964?laAw(E9-qr(^0y}RWHLa}2BKY{krhsA__0{wkWpw8?OiAUEXYnH$ZQb?97qW7 zvx#!UrWa`rXEMTE*)m=z|TkHZ0?nbal|XZ_yajy@TG|0z z(WZvW6M}39aUj^cCTQaA5|aTqpC2=nR}uSJ1pNlb0>U2K1a)A9_rYnd@IKfw3ADt` z0Y4Vh0zw-IF`*3(8HF}DNEg~{A`DRcLO)Qp!uvp(iT$9q4G#m(q{V(90EK=QLAJwg zL7Xe2O<4OTlW;Bo#g5=^4-W$zR=oWOE*6m|O<+*+&w^|hXlaH@4MIPIU~?I47G4&^ zQJS##gIiF7eT8lO9v0e!^#R^3Jx?R_c=3Bb@QA>jHtm?PO@LuBTlqBzmXyE;&;~nn z?tNC+9PlupO@IOBxB$ZncY!$GkgQ;E@GxLED8PU=0S0Jk0fr4^6AuGSbP2Df(W)5v;pID^8%I>4+BcC!A4Kp58HS?g*Gd{_k$A;fybfE$gdd?&PLw;!#3V_ zgf`$dZY(%0{P^JLhWB-Vr7Y+&Y~#-;pavBXiGu-EI{EW#=qH>7f#r?$JT-P5w(+(e zw1IFE`U$$s0Nwa=AJ728J^nGtxUTov}9wr`&wF~{g(iYmF zjFHeLo)^RAUcsJ}OyFGPpEa2U8y!w<1zP|P*ZK7UmFIvY{QH3Y1Q1cEJZfc=8d51f!ZKf_VIz`J0*2zw@|a4Xp3 z;6fA5OTgq8Y+wUa?i1h|;Bp0z2d;j;4Y-3}m!N0_dZ15J>}L_|dvM(eeiDOGJo_>j zMV}!YHwpX#l8)Ei;1L$j`V8P~ * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "nuki.h" +#include "extern-plugininfo.h" + +#include +#include +#include +#include +#include + +static QBluetoothUuid initializationServiceUuid = QBluetoothUuid(QUuid("a92ee000-5501-11e4-916c-0800200c9a66")); +static QBluetoothUuid pairingServiceUuid = QBluetoothUuid(QUuid("a92ee100-5501-11e4-916c-0800200c9a66")); +static QBluetoothUuid pairingDataCharacteristicUuid = QBluetoothUuid(QUuid("a92ee101-5501-11e4-916c-0800200c9a66")); +static QBluetoothUuid keyturnerServiceUuid = QBluetoothUuid(QUuid("a92ee200-5501-11e4-916c-0800200c9a66")); +static QBluetoothUuid keyturnerDataCharacteristicUuid = QBluetoothUuid(QUuid("a92ee201-5501-11e4-916c-0800200c9a66")); +static QBluetoothUuid keyturnerUserDataCharacteristicUuid = QBluetoothUuid(QUuid("a92ee202-5501-11e4-916c-0800200c9a66")); + +Nuki::Nuki(Device *device, BluetoothDevice *bluetoothDevice, QObject *parent) : + QObject(parent), + m_device(device), + m_bluetoothDevice(bluetoothDevice) +{ + connect(m_bluetoothDevice, &BluetoothDevice::stateChanged, this, &Nuki::onBluetoothDeviceStateChanged); + onBluetoothDeviceStateChanged(m_bluetoothDevice->state()); +} + +Device *Nuki::device() +{ + return m_device; +} + +BluetoothDevice *Nuki::bluetoothDevice() +{ + return m_bluetoothDevice; +} + +bool Nuki::startAuthenticationProcess(const PairingTransactionId &pairingTransactionId) +{ + if (m_nukiAction != NukiActionNone) { + qCWarning(dcNuki()) << "Cannot start authentication process. Nuki is busy and already processing an action. Please retry again." << m_nukiAction; + return false; + } + + m_nukiAction = NukiActionAuthenticate; + m_pairingId = pairingTransactionId; + + if (m_available) { + executeCurrentAction(); + } else { + m_bluetoothDevice->connectDevice(); + } + + return true; +} + +bool Nuki::refreshStates() +{ + return executeNukiAction(NukiActionRefresh); +} + +bool Nuki::executeNukiAction(Nuki::NukiAction action) +{ + if (m_nukiAction != NukiActionNone) { + qCWarning(dcNuki()) << "Cannot execute Nuki action. Nuki is busy and already processing an action." << m_nukiAction; + return false; + } + + m_nukiAction = action; + + if (m_available) { + executeCurrentAction(); + } else { + m_bluetoothDevice->connectDevice(); + } + return true; +} + +bool Nuki::executeDeviceAction(Nuki::NukiAction action, DeviceActionInfo *actionInfo) +{ + if (m_nukiAction != NukiActionNone || !m_actionInfo.isNull()) { + qCWarning(dcNuki()) << "Nuki is busy and already processing an action. Please retry again." << m_nukiAction; + return false; + } + + m_actionInfo = QPointer(actionInfo); + m_nukiAction = action; + + if (m_available) { + executeCurrentAction(); + } else { + m_bluetoothDevice->connectDevice(); + } + return true; +} + +void Nuki::connectDevice() +{ + if (!m_bluetoothDevice) + return; + + m_bluetoothDevice->connectDevice(); +} + +void Nuki::disconnectDevice() +{ + if (!m_bluetoothDevice) + return; + + m_bluetoothDevice->disconnectDevice(); +} + +void Nuki::clearSettings() +{ + if (m_nukiAuthenticator) { + m_nukiAuthenticator->clearSettings(); + } +} + +void Nuki::printServices() +{ + foreach (BluetoothGattService *service, m_bluetoothDevice->services()) { + qCDebug(dcNuki()) << service; + foreach (BluetoothGattCharacteristic *characteristic, service->characteristics()) { + qCDebug(dcNuki()) << " " << characteristic->chararcteristicName() << characteristic->uuid().toString(); + foreach (BluetoothGattDescriptor *descriptor, characteristic->descriptors()) { + qCDebug(dcNuki()) << " " << descriptor->name() << descriptor->uuid().toString(); + } + } + } +} + +void Nuki::readDeviceInformationCharacteristics() +{ + m_initUuidsToRead.append(QBluetoothUuid::SerialNumberString); + m_initUuidsToRead.append(QBluetoothUuid::HardwareRevisionString); + m_initUuidsToRead.append(QBluetoothUuid::FirmwareRevisionString); + + m_deviceInformationService->readCharacteristic(QBluetoothUuid::SerialNumberString); + m_deviceInformationService->readCharacteristic(QBluetoothUuid::HardwareRevisionString); + m_deviceInformationService->readCharacteristic(QBluetoothUuid::FirmwareRevisionString); +} + +void Nuki::executeCurrentAction() +{ + qCDebug(dcNuki()) << "Executing" << m_nukiAction; + + switch (m_nukiAction) { + case NukiActionAuthenticate: + m_nukiAuthenticator->startAuthenticationProcess(); + break; + case NukiActionRefresh: + if (!m_nukiController->readLockState()) { + finishCurrentAction(false); + } + break; + case NukiActionLock: + if (!m_nukiController->lock()) { + finishCurrentAction(false); + } + break; + case NukiActionUnlock: + if (!m_nukiController->unlock()) { + finishCurrentAction(false); + } + break; + case NukiActionUnlatch: + if (!m_nukiController->unlatch()) { + finishCurrentAction(false); + } + break; + default: + break; + } +} + +void Nuki::onBluetoothDeviceStateChanged(const BluetoothDevice::State &state) +{ + qCDebug(dcNuki()) << m_bluetoothDevice << "state changed --> " << state; + switch (state) { + case BluetoothDevice::Connecting: + break; + case BluetoothDevice::Connected: + if (m_bluetoothDevice->servicesResolved()) { + // Services already discovered + if (!init()) { + qCWarning(dcNuki()) << "Could not initialze device" << m_bluetoothDevice; + m_bluetoothDevice->disconnectDevice(); + } else { + readDeviceInformationCharacteristics(); + } + } + break; + case BluetoothDevice::Pairing: + break; + case BluetoothDevice::Discovering: + break; + case BluetoothDevice::Discovered: + printServices(); + if (!init()) { + qCWarning(dcNuki()) << "Could not initialze device" << m_bluetoothDevice; + m_bluetoothDevice->disconnectDevice(); + } else { + readDeviceInformationCharacteristics(); + } + break; + case BluetoothDevice::Disconnecting: + setAvailable(false); + clean(); + break; + case BluetoothDevice::Disconnected: + setAvailable(false); + clean(); + break; + default: + break; + } +} + +void Nuki::onDeviceInfoCharacteristicReadFinished(BluetoothGattCharacteristic *characteristic, const QByteArray &value) +{ + qCDebug(dcNuki()) << "Read device information characteristic finished" << characteristic->chararcteristicName() << qUtf8Printable(value); + if (characteristic->uuid() == QBluetoothUuid::SerialNumberString) { + m_serialNumber = QString::fromUtf8(value); + m_initUuidsToRead.removeOne(QBluetoothUuid::SerialNumberString); + } else if (characteristic->uuid() == QBluetoothUuid::HardwareRevisionString) { + m_hardwareRevision = QString::fromUtf8(value); + m_initUuidsToRead.removeOne(QBluetoothUuid::HardwareRevisionString); + } else if (characteristic->uuid() == QBluetoothUuid::FirmwareRevisionString) { + m_firmwareRevision = QString::fromUtf8(value); + m_initUuidsToRead.removeOne(QBluetoothUuid::FirmwareRevisionString); + } + + if (m_initUuidsToRead.isEmpty()) { + // Initial read done. Make device available + setAvailable(true); + } +} + +void Nuki::onAuthenticationError(NukiUtils::ErrorCode error) +{ + qCWarning(dcNuki()) << "Authentication error occured" << error; + + if (m_pairingId.isNull()) + return; + + // If we have a pairing id + emit authenticationProcessFinished(m_pairingId, false); + m_pairingId = PairingTransactionId(); +} + +void Nuki::onAuthenticationFinished(bool success) +{ + qCDebug(dcNuki()) << "Authentication process finished" << (success ? "successfully." : "with error."); + + if (m_pairingId.isNull()) + return; + + // If we have a pairing id + emit authenticationProcessFinished(m_pairingId, success); + m_pairingId = PairingTransactionId(); +} + +void Nuki::onNukiReadStatesFinished(bool success) +{ + m_nukiAction = NukiActionNone; + + if (success) { + // Update states + onNukiStatesChanged(); + } + + // Check if this was an action call + if (m_actionInfo.isNull()) { + // Looks like this was a refresh call, lets disconnect to minimize the not reachable time for other apps + QTimer::singleShot(0, m_bluetoothDevice, &BluetoothDevice::disconnectDevice); + return; + } + + finishCurrentAction(true); +} + +void Nuki::onNukiStatesChanged() +{ + if (!m_device) + return; + + m_device->setStateValue(nukiHardwareRevisionStateTypeId, m_hardwareRevision); + m_device->setStateValue(nukiFirmwareRevisionStateTypeId, m_firmwareRevision); + m_device->setStateValue(nukiBatteryCriticalStateTypeId, m_nukiController->batteryCritical()); + + switch (m_nukiController->nukiLockTrigger()) { + case NukiUtils::LockTriggerBluetooth: + m_device->setStateValue(nukiTriggerStateTypeId, "Bluetooth"); + break; + case NukiUtils::LockTriggerButton: + m_device->setStateValue(nukiTriggerStateTypeId, "Button"); + break; + case NukiUtils::LockTriggerManual: + m_device->setStateValue(nukiTriggerStateTypeId, "Manual"); + break; + default: + break; + } + + switch (m_nukiController->nukiState()) { + case NukiUtils::NukiStateDoorMode: + m_device->setStateValue(nukiModeStateTypeId, "Door"); + break; + case NukiUtils::NukiStatePairingMode: + m_device->setStateValue(nukiModeStateTypeId, "Pairing"); + break; + case NukiUtils::NukiStateUninitialized: + m_device->setStateValue(nukiModeStateTypeId, "Uninitialized"); + break; + default: + break; + } + + switch (m_nukiController->nukiLockState()) { + case NukiUtils::LockStateLocked: + m_device->setStateValue(nukiStateStateTypeId, "locked"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + case NukiUtils::LockStateLocking: + m_device->setStateValue(nukiStateStateTypeId, "locking"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + case NukiUtils::LockStateMotorBlocked: + m_device->setStateValue(nukiStatusStateTypeId, "Motor blocked"); + break; + case NukiUtils::LockStateUncalibrated: + m_device->setStateValue(nukiStatusStateTypeId, "Uncalibrated"); + break; + case NukiUtils::LockStateUndefined: + m_device->setStateValue(nukiStatusStateTypeId, "Undefined"); + break; + case NukiUtils::LockStateUnlatched: + m_device->setStateValue(nukiStateStateTypeId, "unlatched"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + case NukiUtils::LockStateUnlatching: + m_device->setStateValue(nukiStateStateTypeId, "unlatching"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + case NukiUtils::LockStateUnlockedLocknGoActive: + m_device->setStateValue(nukiStatusStateTypeId, "unlocked"); + break; + case NukiUtils::LockStateUnlocked: + m_device->setStateValue(nukiStateStateTypeId, "unlocked"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + case NukiUtils::LockStateUnlocking: + m_device->setStateValue(nukiStateStateTypeId, "unlocking"); + m_device->setStateValue(nukiStatusStateTypeId, "Ok"); + break; + default: + break; + } +} + +bool Nuki::init() +{ + if (!m_bluetoothDevice) + return false; + + qCDebug(dcNuki()) << "Init" << m_bluetoothDevice; + + // If not connected, connect + if (!m_bluetoothDevice->connected()) { + qCWarning(dcNuki()) << "Device is not connected" << m_bluetoothDevice; + return false; + } + + // If services not resolved yet, wait + if (!m_bluetoothDevice->servicesResolved()) { + qCWarning(dcNuki()) << "Device services not resolved yet" << m_bluetoothDevice; + return false; + } + + // Verify services + if (!m_bluetoothDevice->hasService(QBluetoothUuid::DeviceInformation)) { + qCWarning(dcNuki()) << "Could not find device information service on device" << m_bluetoothDevice; + return false; + } + + if (!m_bluetoothDevice->hasService(pairingServiceUuid)) { + qCWarning(dcNuki()) << "Could not find pairing service on device" << m_bluetoothDevice; + return false; + } + + if (!m_bluetoothDevice->hasService(keyturnerServiceUuid)) { + qCWarning(dcNuki()) << "Could not find key turner service on device" << m_bluetoothDevice; + return false; + } + + // Create service and characteristic objects + // Device information + m_deviceInformationService = m_bluetoothDevice->getService(QBluetoothUuid::DeviceInformation); + connect(m_deviceInformationService, &BluetoothGattService::characteristicReadFinished, this, &Nuki::onDeviceInfoCharacteristicReadFinished); + + // Keyturner service + m_keyturnerService = m_bluetoothDevice->getService(keyturnerServiceUuid); + if (!m_keyturnerService->hasCharacteristic(keyturnerUserDataCharacteristicUuid)) { + qCWarning(dcNuki()) << "Could not find user data characteristc on device" << m_bluetoothDevice; + return false; + } + if (!m_keyturnerService->hasCharacteristic(keyturnerDataCharacteristicUuid)) { + qCWarning(dcNuki()) << "Could not find data characteristc on device" << m_bluetoothDevice; + return false; + } + m_keyturnerUserDataCharacteristic = m_keyturnerService->getCharacteristic(keyturnerUserDataCharacteristicUuid); + if (!m_keyturnerUserDataCharacteristic->startNotifications()) { + qCWarning(dcNuki()) << "Could not enable notifications for user data characteristic."; + return false; + } + m_keyturnerDataCharacteristic = m_keyturnerService->getCharacteristic(keyturnerDataCharacteristicUuid); + if (!m_keyturnerDataCharacteristic->startNotifications()) { + qCWarning(dcNuki()) << "Could not enable notifications for data characteristic."; + return false; + } + + // Pairing service + m_pairingService = m_bluetoothDevice->getService(pairingServiceUuid); + if (!m_pairingService->hasCharacteristic(pairingDataCharacteristicUuid)) { + qCWarning(dcNuki()) << "Could not find pairing data characteristc on device" << m_bluetoothDevice; + return false; + } + m_pairingDataCharacteristic = m_pairingService->getCharacteristic(pairingDataCharacteristicUuid); + if (!m_pairingDataCharacteristic->startNotifications()) { + qCWarning(dcNuki()) << "Could not enable notifications for pairing characteristic."; + return false; + } + + // Create authenticator + if (m_nukiAuthenticator) { + delete m_nukiAuthenticator; + m_nukiAuthenticator = nullptr; + } + + m_nukiAuthenticator = new NukiAuthenticator(m_bluetoothDevice->hostInfo(), m_pairingDataCharacteristic, this); + connect(m_nukiAuthenticator, &NukiAuthenticator::errorOccured, this, &Nuki::onAuthenticationError); + connect(m_nukiAuthenticator, &NukiAuthenticator::authenticationProcessFinished, this, &Nuki::onAuthenticationFinished); + + // Create nuki handler for encrypted communication + if (m_nukiController) { + delete m_nukiController; + m_nukiController = nullptr; + } + + m_nukiController = new NukiController(m_nukiAuthenticator, m_keyturnerUserDataCharacteristic, this); + connect(m_nukiController, &NukiController::readNukiStatesFinished, this, &Nuki::onNukiReadStatesFinished); + connect(m_nukiController, &NukiController::lockFinished, this, &Nuki::finishCurrentAction); + connect(m_nukiController, &NukiController::unlockFinished, this, &Nuki::finishCurrentAction); + connect(m_nukiController, &NukiController::unlatchFinished, this, &Nuki::finishCurrentAction); + connect(m_nukiController, &NukiController::nukiStatesChanged, this, &Nuki::onNukiStatesChanged); + + return true; +} + +void Nuki::clean() +{ + // Reset properties + m_hardwareRevision = QString(); + m_serialNumber = QString(); + m_firmwareRevision = QString(); + m_initUuidsToRead.clear(); + + finishCurrentAction(false); + + // Forget all services and characteristics + if (m_deviceInformationService) { + disconnect(m_deviceInformationService, &BluetoothGattService::characteristicReadFinished, this, &Nuki::onDeviceInfoCharacteristicReadFinished); + m_deviceInformationService = nullptr; + } + + m_keyturnerService = nullptr; + m_keyturnerDataCharacteristic = nullptr; + m_keyturnerUserDataCharacteristic = nullptr; + + m_pairingService = nullptr; + m_pairingDataCharacteristic = nullptr; + + // Delete handler + if (m_nukiController) { + delete m_nukiController; + m_nukiController = nullptr; + } + + // Note: delete the authenticator after the handler + if (m_nukiAuthenticator) { + delete m_nukiAuthenticator; + m_nukiAuthenticator = nullptr; + } +} + +void Nuki::finishCurrentAction(bool success) +{ + m_nukiAction = NukiActionNone; + if (m_actionInfo.isNull()) + return; + + m_actionInfo->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure); + m_actionInfo.clear(); +} + +void Nuki::setAvailable(bool available) +{ + if (m_available == available) + return; + + m_available = available; + emit availableChanged(m_available); + + qCDebug(dcNuki()) << "Bluetooth device" << m_bluetoothDevice->name() << "is now" << (m_available ? "available" : "unavailable"); + + if (m_available) { + executeCurrentAction(); + } else { + // Finish any running actions + finishCurrentAction(false); + + // Finish possible running pairing transations + if (!m_pairingId.isNull()) { + qCWarning(dcNuki()) << "Cancel authentication process because of disconnection."; + emit authenticationProcessFinished(m_pairingId, false); + m_pairingId = PairingTransactionId(); + } + } + + if (!m_device) + return; + + m_device->setStateValue(nukiConnectedStateTypeId, m_available); +} diff --git a/nuki/nuki.h b/nuki/nuki.h new file mode 100644 index 00000000..a4503c67 --- /dev/null +++ b/nuki/nuki.h @@ -0,0 +1,136 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Bernhard Trinnes * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef NUKI_H +#define NUKI_H + +#include +#include +#include +#include +#include + +#include "typeutils.h" +#include "devices/device.h" +#include "bluez/bluetoothdevice.h" +#include "devices/deviceactioninfo.h" + +#include "nukiutils.h" +#include "nukicontroller.h" +#include "nukiauthenticator.h" + +//#include "nacl-20110221/crypto_auth/" + +class Nuki : public QObject +{ + + Q_OBJECT + +public: + enum NukiAction { + NukiActionNone, + NukiActionAuthenticate, + NukiActionRefresh, + NukiActionLock, + NukiActionUnlock, + NukiActionUnlatch + }; + Q_ENUM(NukiAction) + + explicit Nuki(Device *device, BluetoothDevice *bluetoothDevice, QObject *parent = nullptr); + + Device *device(); + BluetoothDevice *bluetoothDevice(); + + bool startAuthenticationProcess(const PairingTransactionId &pairingTransactionId); + bool refreshStates(); + bool executeDeviceAction(NukiAction action, DeviceActionInfo *actionInfo); + + void connectDevice(); + void disconnectDevice(); + + void clearSettings(); + + +private: + Device *m_device = nullptr; + BluetoothDevice *m_bluetoothDevice = nullptr; + NukiController *m_nukiController = nullptr; + NukiAuthenticator *m_nukiAuthenticator = nullptr; + + BluetoothGattService *m_deviceInformationService = nullptr; + BluetoothGattService *m_initializationService = nullptr; + BluetoothGattService *m_pairingService = nullptr; + BluetoothGattService *m_keyturnerService = nullptr; + + BluetoothGattCharacteristic *m_pairingDataCharacteristic = nullptr; + BluetoothGattCharacteristic *m_keyturnerDataCharacteristic = nullptr; + BluetoothGattCharacteristic *m_keyturnerUserDataCharacteristic = nullptr; + + // Device information + QList m_initUuidsToRead; + QString m_serialNumber; + QString m_hardwareRevision; + QString m_firmwareRevision; + + bool m_available = false; + + NukiAction m_nukiAction = NukiActionNone; + QPointer m_actionInfo; + PairingTransactionId m_pairingId; + + bool init(); + void clean(); + bool executeNukiAction(NukiAction action); + + void setAvailable(bool available); + void printServices(); + void readDeviceInformationCharacteristics(); + + void executeCurrentAction(); + +signals: + void availableChanged(bool available); + void authenticationProcessFinished(const PairingTransactionId &pairingId, bool success); + void stateChanged(NukiUtils::LockState lockState); + void actionFinished(const ActionId &action, bool success); + +private slots: + // Bluetooth device + void onBluetoothDeviceStateChanged(const BluetoothDevice::State &state); + + // DeviceInfo service + void onDeviceInfoCharacteristicReadFinished(BluetoothGattCharacteristic *characteristic, const QByteArray &value); + + // Nuki Authenticator + void onAuthenticationError(NukiUtils::ErrorCode error); + void onAuthenticationFinished(bool success); + + // Nuki controller + void onNukiReadStatesFinished(bool success); + void finishCurrentAction(bool success); + void onNukiStatesChanged(); + +}; + +#endif // NUKI_H diff --git a/nuki/nuki.pro b/nuki/nuki.pro new file mode 100644 index 00000000..3e151aa9 --- /dev/null +++ b/nuki/nuki.pro @@ -0,0 +1,36 @@ +include(../plugins.pri) + +TARGET = $$qtLibraryTarget(nymea_devicepluginnuki) + +QT += bluetooth dbus + +# apt install libsodium-dev +LIBS += -lsodium + +HEADERS += \ + devicepluginnuki.h \ + nuki.h \ + bluez/blueztypes.h \ + bluez/bluetoothmanager.h \ + bluez/bluetoothadapter.h \ + bluez/bluetoothdevice.h \ + bluez/bluetoothgattservice.h \ + bluez/bluetoothgattcharacteristic.h \ + bluez/bluetoothgattdescriptor.h \ + nukiutils.h \ + nukiauthenticator.h \ + nukicontroller.h + +SOURCES += \ + devicepluginnuki.cpp \ + nuki.cpp \ + bluez/blueztypes.cpp \ + bluez/bluetoothmanager.cpp \ + bluez/bluetoothadapter.cpp \ + bluez/bluetoothdevice.cpp \ + bluez/bluetoothgattservice.cpp \ + bluez/bluetoothgattcharacteristic.cpp \ + bluez/bluetoothgattdescriptor.cpp \ + nukiutils.cpp \ + nukiauthenticator.cpp \ + nukicontroller.cpp diff --git a/nuki/nukiauthenticator.cpp b/nuki/nukiauthenticator.cpp new file mode 100644 index 00000000..26fe2853 --- /dev/null +++ b/nuki/nukiauthenticator.cpp @@ -0,0 +1,602 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "nukiauthenticator.h" + +#include "nukiutils.h" +#include "nymeasettings.h" +#include "extern-plugininfo.h" + +extern "C" { +#include "sodium.h" +#include "sodium/crypto_box.h" +#include "sodium/crypto_secretbox.h" +} + +#include +#include +#include + +NukiAuthenticator::NukiAuthenticator(const QBluetoothHostInfo &hostInfo, BluetoothGattCharacteristic *pairingCharacteristic, QObject *parent) : + QObject(parent), + m_hostInfo(hostInfo), + m_pairingCharacteristic(pairingCharacteristic) +{ + +#ifdef QT_DEBUG + // Enable full debug messages containing sensible data for debug builds + m_debug = true; +#endif + + // Check if we have authentication data for this device and set initial state + loadData(); + if (isValid()) { + setState(AuthenticationStateAuthenticated); + } else { + setState(AuthenticationStateUnauthenticated); + } + + connect(m_pairingCharacteristic, &BluetoothGattCharacteristic::valueChanged, this, &NukiAuthenticator::onPairingDataCharacteristicChanged); +} + +NukiUtils::ErrorCode NukiAuthenticator::error() const +{ + return m_error; +} + +NukiAuthenticator::AuthenticationState NukiAuthenticator::state() const +{ + return m_state; +} + +bool NukiAuthenticator::isValid() const +{ + return !m_privateKey.isEmpty() && + !m_publicKey.isEmpty() && + !m_publicKeyNuki.isEmpty() && + !m_authorizationId == 0 && + !m_authorizationIdRawData.isEmpty() && + !m_uuid.isEmpty(); +} + +void NukiAuthenticator::clearSettings() +{ + QSettings setting(NymeaSettings::settingsPath() + "/plugin-nuki.conf", QSettings::IniFormat); + setting.beginGroup(m_hostInfo.address().toString()); + setting.remove(""); + setting.endGroup(); + + qCDebug(dcNuki()) << "Settings cleared for" << m_hostInfo.address().toString() << "in" << setting.fileName(); +} + +void NukiAuthenticator::startAuthenticationProcess() +{ + setState(AuthenticationStateRequestPublicKey); +} + +quint32 NukiAuthenticator::authorizationId() const +{ + return m_authorizationId; +} + +QByteArray NukiAuthenticator::authorizationIdRawData() const +{ + return m_authorizationIdRawData; +} + +QByteArray NukiAuthenticator::encryptData(const QByteArray &data, const QByteArray &nonce) +{ + // Calculate shared key + qCDebug(dcNuki()) << "Authenticator: Encrypt data"; + Q_ASSERT_X(nonce.length() == crypto_box_NONCEBYTES, "data length", "The nonce does not have the correct length."); + + /* Note: https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html + * unsigned char *c The encrypted message (length of the data + crypto_box_MACBYTES) + * const unsigned char *m The message to encrypt + * unsigned long long mlen The length of the message to encrypt + * const unsigned char *n The nonce (must also sent unencrypted) + * const unsigned char *pk The public key of the Nuki + * const unsigned char *sk The private key of nymea for this Nuki + */ + + unsigned char encrypted[crypto_box_MACBYTES + data.length()]; + int result = crypto_box_easy(encrypted, + reinterpret_cast(data.data()), + static_cast(data.length()), + reinterpret_cast(nonce.data()), + reinterpret_cast(m_publicKeyNuki.data()), + reinterpret_cast(m_privateKey.data())); + + if (result < 0) { + qCWarning(dcNuki()) << "Could not encrypt data. Something went wrong"; + return QByteArray(); + } + + QByteArray encryptedData = QByteArray(reinterpret_cast(encrypted), crypto_box_MACBYTES + data.length()); + + if (m_debug) qCDebug(dcNuki()) << " Private key :" << NukiUtils::convertByteArrayToHexStringCompact(m_privateKey); + if (m_debug) qCDebug(dcNuki()) << " Public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKey); + if (m_debug) qCDebug(dcNuki()) << " Nuki public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKeyNuki); + if (m_debug) qCDebug(dcNuki()) << " Unencrypted data:" << NukiUtils::convertByteArrayToHexStringCompact(data); + if (m_debug) qCDebug(dcNuki()) << " Encrypted data :" << NukiUtils::convertByteArrayToHexStringCompact(encryptedData); + + return encryptedData; +} + +QByteArray NukiAuthenticator::decryptData(const QByteArray &data, const QByteArray &nonce) +{ + qCDebug(dcNuki()) << "Authenticator: Decrypt data"; + Q_ASSERT_X(nonce.length() == crypto_box_NONCEBYTES, "data length", "The nonce does not have the correct length."); + Q_ASSERT_X(static_cast(data.length()) >= crypto_box_MACBYTES, "data length", "The encrypted data is to short."); + + /* Note: https://download.libsodium.org/doc/public-key_cryptography/authenticated_encryption.html + * unsigned char *m The decrypted message result + * const unsigned char *c The message to decrypt / cyphertext (length of the encrypted data + crypto_box_MACBYTES) + * unsigned long long clen The length of the message to decrypt + * const unsigned char *n The nonce used while encryption (received in the unencrypted ADATA) + * const unsigned char *pk The public key of the Nuki + * const unsigned char *sk The private key of nymea for this Nuki + */ + + unsigned char decrypted[data.length() - crypto_box_MACBYTES]; + int result = crypto_box_open_easy(decrypted, + reinterpret_cast(data.data()), + static_cast(data.length()), + reinterpret_cast(nonce.data()), + reinterpret_cast(m_publicKeyNuki.data()), + reinterpret_cast(m_privateKey.data())); + + if (result < 0) { + qCWarning(dcNuki()) << "Could not decrypt data. Something went wrong"; + return QByteArray(); + } + + QByteArray decryptedData = QByteArray(reinterpret_cast(decrypted), data.length() - crypto_box_MACBYTES); + + if (m_debug) qCDebug(dcNuki()) << " Private key :" << NukiUtils::convertByteArrayToHexStringCompact(m_privateKey); + if (m_debug) qCDebug(dcNuki()) << " Public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKey); + if (m_debug) qCDebug(dcNuki()) << " Nuki public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKeyNuki); + if (m_debug) qCDebug(dcNuki()) << " Encrypted data :" << NukiUtils::convertByteArrayToHexStringCompact(data); + if (m_debug) qCDebug(dcNuki()) << " Decrypted data :" << NukiUtils::convertByteArrayToHexStringCompact(decryptedData); + + return decryptedData; +} + +QByteArray NukiAuthenticator::generateNonce(const int &length) const +{ + unsigned char nounce[length]; + randombytes_buf(nounce, length); + return QByteArray(reinterpret_cast(nounce), length); +} + +void NukiAuthenticator::setState(NukiAuthenticator::AuthenticationState state) +{ + if (m_state == state) + return; + + m_state = state; + emit stateChanged(m_state); + + qCDebug(dcNuki()) << m_state; + + switch (m_state) { + case AuthenticationStateUnauthenticated: + resetExpectedData(); + break; + case AuthenticationStateAuthenticated: + qCDebug(dcNuki()) << "Device" << m_hostInfo.address().toString() << "authenticated."; + if (m_debug) qCDebug(dcNuki()) << " Private key :" << NukiUtils::convertByteArrayToHexStringCompact(m_privateKey); + if (m_debug) qCDebug(dcNuki()) << " Public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKey); + if (m_debug) qCDebug(dcNuki()) << " Nuki public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKeyNuki); + if (m_debug) qCDebug(dcNuki()) << " Authorization ID:" << NukiUtils::convertByteArrayToHexStringCompact(m_authorizationIdRawData) << m_authorizationId; + break; + case AuthenticationStateRequestPublicKey: + resetExpectedData(NukiUtils::CommandPublicKey, 2); + requestPublicKey(); + break; + case AuthenticationStateGenerateKeyPair: + resetExpectedData(); + generateKeyPair(); + setState(AuthenticationStateSendPublicKey); + break; + case AuthenticationStateSendPublicKey: + resetExpectedData(NukiUtils::CommandChallenge, 2); + sendPublicKey(); + setState(AuthenticationStateReadChallenge); + break; + case AuthenticationStateReadChallenge: + resetExpectedData(NukiUtils::CommandChallenge, 2); + break; + case AuthenticationStateAutorization: + sendAuthorizationAuthenticator(); + setState(AuthenticationStateReadSecondChallenge); + break; + case AuthenticationStateReadSecondChallenge: + resetExpectedData(NukiUtils::CommandChallenge, 2); + break; + case AuthenticationStateAuthenticateData: + resetExpectedData(); + sendAuthenticateData(); + setState(AuthenticationStateAuthorizationId); + break; + case AuthenticationStateAuthorizationId: + resetExpectedData(NukiUtils::CommandAuthorizationId, 5); + break; + case AuthenticationStateAuthorizationIdConfirm: + resetExpectedData(); + sendAuthoizationIdConfirm(); + setState(AuthenticationStateStatus); + break; + case AuthenticationStateStatus: + resetExpectedData(NukiUtils::CommandStatus); + break; + case AuthenticationStateError: + resetExpectedData(); + emit errorOccured(m_error); + emit authenticationProcessFinished(false); + break; + default: + qCWarning(dcNuki()) << "Authenticator: Unknown state."; + break; + } +} + +void NukiAuthenticator::resetExpectedData(NukiUtils::Command command, int expectedCount) +{ + m_currentReceivingCommand = command; + m_currentReceivingCurrentCount = 0; + m_currentReceivingExpectedCount = expectedCount; + m_currentReceivingData.clear(); +} + +bool NukiAuthenticator::createAuthenticator(const QByteArray content) +{ + // Create shared key + qCDebug(dcNuki()) << "Authenticator: Calculate shared key"; + unsigned char sharedKey[crypto_box_BEFORENMBYTES]; + int result = crypto_box_beforenm(sharedKey, reinterpret_cast(m_publicKeyNuki.data()), reinterpret_cast(m_privateKey.data())); + if (result < 0) { + qCWarning(dcNuki()) << "Could not create shared key for autorization authenticator."; + return false; + } + + m_sharedKey = QByteArray(reinterpret_cast(sharedKey), crypto_box_BEFORENMBYTES); + Q_ASSERT_X(m_sharedKey.length() == 32, "data length", "The shared key does not have the correct length."); + + if (m_debug) qCDebug(dcNuki()) << "Authenticator: Calculate authenticator hash HMAC-SHA-256"; + if (m_debug) qCDebug(dcNuki()) << " Shared key :" << NukiUtils::convertByteArrayToHexStringCompact(m_sharedKey); + if (m_debug) qCDebug(dcNuki()) << " Nuki nonce :" << NukiUtils::convertByteArrayToHexStringCompact(m_nonceNuki); + + // Calculate authenticator hash input for HMAC-SHA-256 + qCDebug(dcNuki()) << "Authenticator: Calculate authenticator data"; + unsigned char authenticator[crypto_auth_hmacsha256_BYTES]; + result = crypto_auth_hmacsha256(authenticator, reinterpret_cast(content.data()), content.length(), reinterpret_cast(m_sharedKey.data())); + if (result < 0) { + qCWarning(dcNuki()) << "Could not create authenticator hash for autorization authenticator."; + return false; + } + + m_authenticator = QByteArray(reinterpret_cast(authenticator), crypto_auth_hmacsha256_BYTES); + if (m_debug) qCDebug(dcNuki()) << " Authenticator :" << NukiUtils::convertByteArrayToHexStringCompact(m_authenticator); + return true; +} + +void NukiAuthenticator::requestPublicKey() +{ + qCDebug(dcNuki()) << "Authenticator: Request public key fom Nuki"; + + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(NukiUtils::CommandPublicKey); + QByteArray data = NukiUtils::createRequestMessageForUnencrypted(NukiUtils::CommandRequestData, payload); + if (m_debug) qCDebug(dcNuki()) << "-->" << NukiUtils::convertByteArrayToHexStringCompact(data); + m_pairingCharacteristic->writeCharacteristic(data); +} + +void NukiAuthenticator::sendPublicKey() +{ + qCDebug(dcNuki()) << "Authenticator: Send public key to Nuki"; + QByteArray data = NukiUtils::createRequestMessageForUnencrypted(NukiUtils::CommandPublicKey, m_publicKey); + if (m_debug) qCDebug(dcNuki()) << "-->" << NukiUtils::convertByteArrayToHexStringCompact(data); + m_pairingCharacteristic->writeCharacteristic(data); +} + +void NukiAuthenticator::generateKeyPair() +{ + qCDebug(dcNuki()) << "Generate key pair"; + unsigned char publicKey[crypto_box_PUBLICKEYBYTES]; + unsigned char secretKey[crypto_box_SECRETKEYBYTES]; + crypto_box_keypair(publicKey, secretKey); + m_publicKey = QByteArray(reinterpret_cast(publicKey), crypto_box_PUBLICKEYBYTES); + m_privateKey = QByteArray(reinterpret_cast(secretKey), crypto_box_SECRETKEYBYTES); + + if (m_debug) qCDebug(dcNuki()) << " Private key :" << NukiUtils::convertByteArrayToHexStringCompact(m_privateKey); + if (m_debug) qCDebug(dcNuki()) << " Public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKey); + if (m_debug) qCDebug(dcNuki()) << " Nuki public key :" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKeyNuki); +} + +void NukiAuthenticator::sendAuthorizationAuthenticator() +{ + QByteArray valueR; + valueR.append(m_publicKey); + valueR.append(m_publicKeyNuki); + valueR.append(m_nonceNuki); + + // Create authenticator and store it into m_authenticator + if (!createAuthenticator(valueR)) { + qCWarning(dcNuki()) << "Could not create authenticator hash HMAC-SHA-256"; + setState(AuthenticationStateError); + } + + // Send the authenticator + qCDebug(dcNuki()) << "Authenticator: Send authorization authenticator to Nuki"; + QByteArray message = NukiUtils::createRequestMessageForUnencrypted(NukiUtils::CommandAuthorizationAuthenticator, m_authenticator); + if (m_debug) qCDebug(dcNuki()) << "-->" << NukiUtils::convertByteArrayToHexStringCompact(message); + m_pairingCharacteristic->writeCharacteristic(message); +} + +void NukiAuthenticator::sendAuthenticateData() +{ + // Calculate new nounce + m_nonce = generateNonce(); + + QByteArray content; + QDataStream stream(&content, QIODevice::WriteOnly); + // Note: 0x00 = App, 0x01 = Bridge, 0x02 = Fob + stream << static_cast(0x01); + // Note: app id (42) + stream << static_cast(0x002A); + + // Note: the name of the bridge in 32 bytes [ 0 0 0 ... n y m e a ] + QByteArray name = QByteArray(27, '\0').append(QByteArray("nymea")); + Q_ASSERT_X(name.count() == 32, "data length", "Name has not the correct length."); + + QByteArray valueR = content; + valueR.append(name); + valueR.append(m_nonce); + valueR.append(m_nonceNuki); + + if (m_debug) qCDebug(dcNuki()) << " Name :" << qUtf8Printable(name) << NukiUtils::convertByteArrayToHexStringCompact(name); + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(m_nonce); + + // Create authenticator and store it into m_authenticator + if (!createAuthenticator(valueR)) { + qCWarning(dcNuki()) << "Could not create authenticator hash HMAC-SHA-256"; + setState(AuthenticationStateError); + } + + // Prepare message to send to Nuki + QByteArray data; + data.append(m_authenticator); + data.append(content); + data.append(name); + data.append(m_nonce); + + qCDebug(dcNuki()) << "Authenticator: Send authentication data to Nuki"; + QByteArray message = NukiUtils::createRequestMessageForUnencrypted(NukiUtils::CommandAuthorizationData, data); + if (m_debug) qCDebug(dcNuki()) << "-->" << NukiUtils::convertByteArrayToHexStringCompact(message); + m_pairingCharacteristic->writeCharacteristic(message); +} + +void NukiAuthenticator::sendAuthoizationIdConfirm() +{ + qCDebug(dcNuki()) << "Authenticator: Create data for authentication ID confirm"; + QByteArray valueR; + valueR.append(m_authorizationIdRawData); + valueR.append(m_nonceNuki); + + // Create authenticator and store it into m_authenticator + if (!createAuthenticator(valueR)) { + qCWarning(dcNuki()) << "Could not create authenticator hash HMAC-SHA-256"; + setState(AuthenticationStateError); + } + + // Calculate new nounce + m_nonce = generateNonce(); + + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(m_nonce); + if (m_debug) qCDebug(dcNuki()) << " Nuki Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(m_nonceNuki); + if (m_debug) qCDebug(dcNuki()) << " Authorization ID:" << NukiUtils::convertByteArrayToHexStringCompact(m_authorizationIdRawData) << m_authorizationId; + + // Prepare message to send to Nuki + QByteArray data; + data.append(m_authenticator); + data.append(m_authorizationIdRawData); + + qCDebug(dcNuki()) << "Authenticator: Send authentication ID confirm to Nuki"; + QByteArray message = NukiUtils::createRequestMessageForUnencrypted(NukiUtils::CommandAuthorizationIdConfirmation, data); + if (m_debug) qCDebug(dcNuki()) << "-->" << NukiUtils::convertByteArrayToHexStringCompact(message); + m_pairingCharacteristic->writeCharacteristic(message); +} + +void NukiAuthenticator::saveData() +{ + QSettings setting(NymeaSettings::settingsPath() + "/plugin-nuki.conf", QSettings::IniFormat); + setting.beginGroup(m_hostInfo.address().toString()); + setting.setValue("privateKey", m_privateKey); + setting.setValue("publicKey", m_publicKey); + setting.setValue("publicKeyNuki", m_publicKeyNuki); + setting.setValue("authenticationIdRawData", m_authorizationIdRawData); + setting.setValue("authenticationId", m_authorizationId); + setting.setValue("uuid", m_uuid); + setting.endGroup(); + + qCDebug(dcNuki()) << "Authenticator: Settings saved to" << setting.fileName(); +} + +void NukiAuthenticator::loadData() +{ + QSettings setting(NymeaSettings::settingsPath() + "/plugin-nuki.conf", QSettings::IniFormat); + setting.beginGroup(m_hostInfo.address().toString()); + m_privateKey = setting.value("privateKey", QByteArray()).toByteArray(); + m_publicKey = setting.value("publicKey", QByteArray()).toByteArray(); + m_publicKeyNuki = setting.value("publicKeyNuki", QByteArray()).toByteArray(); + m_authorizationIdRawData = setting.value("authenticationIdRawData", QByteArray()).toByteArray(); + m_authorizationId = static_cast(setting.value("authenticationId", 0).toInt()); + m_uuid = setting.value("uuid", QByteArray()).toByteArray(); + setting.endGroup(); + + qCDebug(dcNuki()) << "Authenticator: Settings loaded from" << setting.fileName(); +} + +void NukiAuthenticator::onPairingDataCharacteristicChanged(const QByteArray &value) +{ + if (m_debug) qCDebug(dcNuki()) << "Authenticator data received: <--" << NukiUtils::convertByteArrayToHexStringCompact(value); + + // Process pairing characteristic data + QByteArray data = QByteArray(value); + QDataStream stream(&data, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + quint16 command; + stream >> command; + + // Check if we are collecting data for multi part notification + if (m_currentReceivingCurrentCount > 0) { + command = m_currentReceivingCommand; + } + + if (m_debug) qCDebug(dcNuki()) << static_cast(command); + + switch (command) { + case NukiUtils::CommandErrorReport: + quint8 error; + quint16 commandIdentifier; + quint16 crc; + stream >> error >> commandIdentifier >> crc; + if (!NukiUtils::validateMessageCrc(data)) { + qCWarning(dcNuki()) << "Invalid message"; + // FIXME: check what to do if crc is invalid + } + m_error = static_cast(error); + qCWarning(dcNuki()) << "Authenticator: Error for command" << static_cast(commandIdentifier) << m_error; + setState(AuthenticationStateError); + break; + case NukiUtils::CommandPublicKey: + m_currentReceivingCurrentCount++; + m_currentReceivingData.append(value); + if (m_currentReceivingCurrentCount == m_currentReceivingExpectedCount) { + if (!NukiUtils::validateMessageCrc(m_currentReceivingData)) { + qCWarning(dcNuki()) << "Invalid CRC CCITT value for public key message."; + // FIXME: check what to do if crc is invalid + } + + qCDebug(dcNuki()) << "Authenticator: Nuki public key message received" << (m_debug ? NukiUtils::convertByteArrayToHexStringCompact(m_currentReceivingData) : ""); + m_publicKeyNuki = m_currentReceivingData.mid(2, 32); + if (m_debug) qCDebug(dcNuki()) << "Authenticator: --> Nuki public key:" << NukiUtils::convertByteArrayToHexStringCompact(m_publicKeyNuki); + + setState(AuthenticationStateGenerateKeyPair); + } + break; + case NukiUtils::CommandChallenge: + m_currentReceivingCurrentCount++; + m_currentReceivingData.append(value); + if (m_currentReceivingCurrentCount == m_currentReceivingExpectedCount) { + qCDebug(dcNuki()) << "Authenticator: Nuki challenge message received" << (m_debug ? NukiUtils::convertByteArrayToHexStringCompact(m_currentReceivingData) : ""); + if (!NukiUtils::validateMessageCrc(m_currentReceivingData)) { + qCWarning(dcNuki()) << "Invalid CRC CCITT value for challenge message."; + // FIXME: check what to do if crc is invalid + } + + m_nonceNuki = m_currentReceivingData.mid(2, 32); + if (m_debug) qCDebug(dcNuki()) << "Authenticator: --> Nuki nonce:" << NukiUtils::convertByteArrayToHexStringCompact(m_nonceNuki); + // Check if this was from the first challenge read or the second + if (m_state == AuthenticationStateReadChallenge) { + setState(AuthenticationStateAutorization); + } else if (m_state == AuthenticationStateReadSecondChallenge) { + setState(AuthenticationStateAuthenticateData); + } else { + qCWarning(dcNuki()) << "Received a challenge without expecting one."; + setState(AuthenticationStateError); + } + } + break; + case NukiUtils::CommandAuthorizationId: + m_currentReceivingCurrentCount++; + m_currentReceivingData.append(value); + if (m_currentReceivingCurrentCount == m_currentReceivingExpectedCount) { + qCDebug(dcNuki()) << "Authenticator: Nuki authorization ID message received" << (m_debug ? NukiUtils::convertByteArrayToHexStringCompact(m_currentReceivingData) : ""); + + if (!NukiUtils::validateMessageCrc(m_currentReceivingData)) { + qCWarning(dcNuki()) << "Invalid CRC CCITT value for challenge message."; + // FIXME: check what to do if crc is invalid + } + + // Parse data + QByteArray message = m_currentReceivingData.mid(2, m_currentReceivingData.count() - 4); + QByteArray authenticator = message.left(32); + Q_ASSERT_X(authenticator.count() == 32, "data length", "Nuki nonce has not the correct length."); + + // Read authorization ID + m_authorizationIdRawData = message.mid(32, 4); + QDataStream stream(&m_authorizationIdRawData, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> m_authorizationId; + + m_uuid = message.mid(36, 16); + Q_ASSERT_X(m_uuid.count() == 16, "data length", "UUIS has not the correct length."); + + m_nonceNuki = message.mid(52, 32); + Q_ASSERT_X(m_nonceNuki.count() == 32, "data length", "Nuki nonce has not the correct length."); + + if (m_debug) qCDebug(dcNuki()) << " Full message :" << NukiUtils::convertByteArrayToHexStringCompact(message); + if (m_debug) qCDebug(dcNuki()) << " Authenticator :" << NukiUtils::convertByteArrayToHexStringCompact(authenticator); + if (m_debug) qCDebug(dcNuki()) << " Authorization ID:" << NukiUtils::convertByteArrayToHexStringCompact(m_authorizationIdRawData) << m_authorizationId; + if (m_debug) qCDebug(dcNuki()) << " UUID data :" << NukiUtils::convertByteArrayToHexStringCompact(m_uuid); + if (m_debug) qCDebug(dcNuki()) << " Nuki nonce :" << NukiUtils::convertByteArrayToHexStringCompact(m_nonceNuki); + + setState(AuthenticationStateAuthorizationIdConfirm); + } + break; + case NukiUtils::CommandStatus: { + quint8 status; + stream >> status; + + if (!NukiUtils::validateMessageCrc(data)) { + qCWarning(dcNuki()) << "Invalid message"; + // FIXME: check what to do if crc is invalid + } + + NukiUtils::StatusCode statusCode = static_cast(status); + if (m_debug) qCDebug(dcNuki()) << statusCode; + switch (statusCode) { + case NukiUtils::StatusCodeAccepted: + qCWarning(dcNuki()) << "The command was accepted, but not completed."; + setState(AuthenticationStateError); + break; + case NukiUtils::StatusCodeCompeted: + qCDebug(dcNuki()) << "Nuki authentication process finished successfully!"; + saveData(); + setState(AuthenticationStateAuthenticated); + emit authenticationProcessFinished(true); + break; + default: + break; + } + break; + } + default: + qCWarning(dcNuki()) << "Authenticator: Unhandled command identifier for parining charateristic" << NukiUtils::convertUint16ToHexString(command); + resetExpectedData(); + break; + } +} diff --git a/nuki/nukiauthenticator.h b/nuki/nukiauthenticator.h new file mode 100644 index 00000000..ab0eccc7 --- /dev/null +++ b/nuki/nukiauthenticator.h @@ -0,0 +1,132 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of guh. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef NUKIAUTHENTICATOR_H +#define NUKIAUTHENTICATOR_H + +#include +#include +#include + +#include "nukiutils.h" +#include "bluez/bluetoothgattcharacteristic.h" + +class NukiAuthenticator : public QObject +{ + Q_OBJECT +public: + enum AuthenticationState { + AuthenticationStateUnauthenticated, + AuthenticationStateAuthenticated, + AuthenticationStateRequestPublicKey, + AuthenticationStateGenerateKeyPair, + AuthenticationStateSendPublicKey, + AuthenticationStateReadChallenge, + AuthenticationStateAutorization, + AuthenticationStateReadSecondChallenge, + AuthenticationStateAuthenticateData, + AuthenticationStateAuthorizationId, + AuthenticationStateAuthorizationIdConfirm, + AuthenticationStateStatus, + AuthenticationStateError + }; + Q_ENUM(AuthenticationState) + + explicit NukiAuthenticator(const QBluetoothHostInfo &hostInfo, BluetoothGattCharacteristic *pairingCharacteristic, QObject *parent = nullptr); + + NukiUtils::ErrorCode error() const; + AuthenticationState state() const; + + // Returns true if authentication end encryption data are available + bool isValid() const; + + void clearSettings(); + void startAuthenticationProcess(); + + quint32 authorizationId() const; + QByteArray authorizationIdRawData() const; + + QByteArray encryptData(const QByteArray &data, const QByteArray &nonce); + QByteArray decryptData(const QByteArray &data, const QByteArray &nonce); + + // Generate 32 byte nonce data + QByteArray generateNonce(const int &length = 32) const; + +private: + QBluetoothHostInfo m_hostInfo; + BluetoothGattCharacteristic *m_pairingCharacteristic = nullptr; + AuthenticationState m_state = AuthenticationStateUnauthenticated; + NukiUtils::ErrorCode m_error = NukiUtils::ErrorCodeNoError; + + // For handling splited notifications + NukiUtils::Command m_currentReceivingCommand = NukiUtils::CommandRequestData; + QByteArray m_currentReceivingData; + int m_currentReceivingExpectedCount = 0; + int m_currentReceivingCurrentCount = 0; + + // For development debugging + bool m_debug = false; + + // Local data + QByteArray m_privateKey; + QByteArray m_publicKey; + QByteArray m_sharedKey; + QByteArray m_authenticator; + QByteArray m_nonce; + QByteArray m_uuid; + QByteArray m_authorizationIdRawData; + quint32 m_authorizationId = 0; + + // Nuki data + QByteArray m_publicKeyNuki; + QByteArray m_nonceNuki; + + // State machine + void setState(AuthenticationState state); + void resetExpectedData(NukiUtils::Command command = NukiUtils::CommandRequestData, int expectedCount = 1); + + // Helper methods + bool createAuthenticator(const QByteArray content); + + // State action methods + void requestPublicKey(); + void sendPublicKey(); + void generateKeyPair(); + void sendAuthorizationAuthenticator(); + void sendAuthenticateData(); + void sendAuthoizationIdConfirm(); + + // Storage + void saveData(); + void loadData(); + +signals: + void errorOccured(NukiUtils::ErrorCode error); + void stateChanged(AuthenticationState state); + void authenticationProcessFinished(bool success); + +private slots: + void onPairingDataCharacteristicChanged(const QByteArray &value); + +}; + +#endif // NUKIAUTHENTICATOR_H diff --git a/nuki/nukicontroller.cpp b/nuki/nukicontroller.cpp new file mode 100644 index 00000000..2bcd2b44 --- /dev/null +++ b/nuki/nukicontroller.cpp @@ -0,0 +1,524 @@ +#include "nukicontroller.h" +#include "extern-plugininfo.h" + +#include +#include + +extern "C" { +#include "sodium.h" +} + +NukiController::NukiController(NukiAuthenticator *nukiAuthenticator, BluetoothGattCharacteristic *userDataCharacteristic, QObject *parent) : + QObject(parent), + m_nukiAuthenticator(nukiAuthenticator), + m_userDataCharacteristic(userDataCharacteristic) +{ +#ifdef QT_DEBUG + // Enable full debug messages containing sensible data for debug builds + m_debug = true; +#endif + + connect(m_userDataCharacteristic, &BluetoothGattCharacteristic::valueChanged, this, &NukiController::onUserDataCharacteristicChanged); +} + +NukiUtils::NukiState NukiController::nukiState() const +{ + return m_nukiState; +} + +NukiUtils::LockState NukiController::nukiLockState() const +{ + return m_nukiLockState; +} + +NukiUtils::LockTrigger NukiController::nukiLockTrigger() const +{ + return m_nukiLockTrigger; +} + +bool NukiController::batteryCritical() const +{ + return m_batteryCritical; +} + +bool NukiController::readLockState() +{ + if (m_state != NukiControllerStateIdle) { + // TODO: maybe queue commands + qCWarning(dcNuki()) << "Controller: Could not read lock state, Nuki is currenty busy"; + return false; + } + + if (!m_nukiAuthenticator->isValid()) { + qCWarning(dcNuki()) << "Invalid authenticator. Please authenticate the device first."; + return false; + } + + setState(NukiControllerStateReadingLockStates); + return true; +} + +bool NukiController::lock() +{ + if (m_state != NukiControllerStateIdle) { + // TODO: maybe queue commands + qCWarning(dcNuki()) << "Controller: Could not lock, Nuki is currenty busy"; + return false; + } + + if (!m_nukiAuthenticator->isValid()) { + qCWarning(dcNuki()) << "Invalid authenticator. Please authenticate the device first."; + return false; + } + + setState(NukiControllerStateLockActionRequestChallange); + return true; +} + +bool NukiController::unlock() +{ + if (m_state != NukiControllerStateIdle) { + // TODO: maybe queue commands + qCWarning(dcNuki()) << "Controller: Could not lock, Nuki is currenty busy"; + return false; + } + + if (!m_nukiAuthenticator->isValid()) { + qCWarning(dcNuki()) << "Invalid authenticator. Please authenticate the device first."; + return false; + } + + setState(NukiControllerStateUnlockActionRequestChallange); + return true; +} + +bool NukiController::unlatch() +{ + if (m_state != NukiControllerStateIdle) { + // TODO: maybe queue commands + qCWarning(dcNuki()) << "Controller: Could not unlatch, Nuki is currenty busy"; + return false; + } + + if (!m_nukiAuthenticator->isValid()) { + qCWarning(dcNuki()) << "Invalid authenticator. Please authenticate the device first."; + return false; + } + + setState(NukiControllerStateUnlatchActionRequestChallange); + return true; +} + +void NukiController::setState(NukiController::NukiControllerState state) +{ + if (m_state == state) + return; + + m_state = state; + + qCDebug(dcNuki()) << m_state; + + switch (m_state) { + case NukiControllerStateIdle: + break; + case NukiControllerStateReadingLockStates: + sendReadLockStateRequest(); + break; + case NukiControllerStateLockActionRequestChallange: + sendRequestChallengeRequest(); + break; + case NukiControllerStateLockActionExecute: + sendLockActionRequest(NukiUtils::LockActionLock); + setState(NukiControllerStateLockActionAccepted); + break; + case NukiControllerStateLockActionAccepted: + break; + case NukiControllerStateUnlockActionRequestChallange: + sendRequestChallengeRequest(); + break; + case NukiControllerStateUnlockActionExecute: + sendLockActionRequest(NukiUtils::LockActionUnlock); + setState(NukiControllerStateUnlockActionAccepted); + break; + case NukiControllerStateUnlockActionAccepted: + break; + case NukiControllerStateUnlatchActionRequestChallange: + sendRequestChallengeRequest(); + break; + case NukiControllerStateUnlatchActionExecute: + sendLockActionRequest(NukiUtils::LockActionUnlatch); + setState(NukiControllerStateUnlatchActionAccepted); + break; + case NukiControllerStateUnlatchActionAccepted: + break; + default: + break; + } + + emit stateChanged(m_state); +} + +void NukiController::resetMessageBuffer() +{ + m_messageBuffer.clear(); + m_messageBufferNonce.clear(); + m_messageBufferIdentifier = 0; + m_messageBufferLength = 0; + m_messageBufferCounter = 0; +} + +void NukiController::processNukiStatesData(const QByteArray &data) +{ + quint8 nukiState = 0; + quint8 nukiLockState = 0; + quint8 nukiLockTrigger = 0; + quint16 year = 1970; + quint8 month = 1; + quint8 day = 1; + quint8 hour = 0; + quint8 minute = 0; + quint8 second = 0; + qint16 utcOffset = 0; + quint8 batteryCritical = 0; + + QByteArray payload = data; + QDataStream stream(&payload, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> nukiState >> nukiLockState >> nukiLockTrigger >> year >> month >> day >> hour >> minute >> second >> utcOffset >> batteryCritical; + + m_nukiState = static_cast(nukiState); + m_nukiLockState = static_cast(nukiLockState); + m_nukiLockTrigger = static_cast(nukiLockTrigger); + m_nukiDateTime = QDateTime(QDate(year, month, day), QTime(hour, minute, second)); + m_nukiUtcOffset = utcOffset; + m_batteryCritical = (batteryCritical == 0 ? false : true); + + if (m_debug) qCDebug(dcNuki()) << "--------------------:" << m_state; + if (m_debug) qCDebug(dcNuki()) << " Nuki state :" << m_nukiState; + if (m_debug) qCDebug(dcNuki()) << " Nuki lock state :" << m_nukiLockState; + if (m_debug) qCDebug(dcNuki()) << " Lock trigger :" << m_nukiLockTrigger; + if (m_debug) qCDebug(dcNuki()) << " Date time :" << m_nukiDateTime.toString("dd.MM.yyyy hh:mm:ss") << "UTC offset:" << m_nukiUtcOffset; + if (m_debug) qCDebug(dcNuki()) << " Battery critical:" << m_batteryCritical; + + qCDebug(dcNuki()) << "Nuki states refreshed."; + + emit nukiStatesChanged(); +} + +void NukiController::processNukiErrorReport(const QByteArray &data) +{ + qint8 errorCode; + quint16 nukiCommand; + + QByteArray payload = data; + QDataStream stream(&payload, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> errorCode >> nukiCommand; + + qCDebug(dcNuki()) << "Received error report" << static_cast(errorCode) << static_cast(nukiCommand); +} + +void NukiController::processUserDataNotification(const QByteArray nonce, quint32 authorizationIdentifier, const QByteArray &privateData) +{ + QByteArray decryptedMessage = m_nukiAuthenticator->decryptData(privateData, nonce); + + // Process decrypted data + if (!NukiUtils::validateMessageCrc(decryptedMessage)) { + qCWarning(dcNuki()) << "Controller: User notification data has invalid CRC CCITT value. Rejecting data."; + return; + } + + // We have the unencrypted and valid PDATA, let's see what this is + quint32 decryptedAuthenticationId = NukiUtils::convertByteArrayToUint32BigEndian(decryptedMessage.left(4)); + NukiUtils::Command command = static_cast(NukiUtils::convertByteArrayToUint16BigEndian(decryptedMessage.mid(4, 2))); + QByteArray payload = decryptedMessage.mid(6, decryptedMessage.length() - 8); + + qCDebug(dcNuki()) << "Controller: Processing notification" << command; + + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(nonce); + if (m_debug) qCDebug(dcNuki()) << " Authorization ID:" << authorizationIdentifier; + if (m_debug) qCDebug(dcNuki()) << " Encrypted data :" << NukiUtils::convertByteArrayToHexStringCompact(privateData) << privateData.length(); + if (m_debug) qCDebug(dcNuki()) << " Decrypted data :" << NukiUtils::convertByteArrayToHexStringCompact(decryptedMessage) << decryptedMessage.length(); + if (m_debug) qCDebug(dcNuki()) << " Command :" << command; + if (m_debug) qCDebug(dcNuki()) << " Authorization ID:" << NukiUtils::convertByteArrayToHexStringCompact(decryptedMessage.left(4)) << decryptedAuthenticationId; + if (m_debug) qCDebug(dcNuki()) << " Payload :" << NukiUtils::convertByteArrayToHexStringCompact(payload); + + // Lets see if this was an expected + switch (m_state) { + case NukiControllerStateReadingLockStates: + // We are expecting the states notification + if (command == NukiUtils::CommandNukiStates) { + processNukiStatesData(payload); + emit readNukiStatesFinished(true); + setState(NukiControllerStateIdle); + return; + } + break; + case NukiControllerStateLockActionRequestChallange: + // We are expecting callange message + if (command == NukiUtils::CommandChallenge) { + m_nukiNonce = payload; + setState(NukiControllerStateLockActionExecute); + return; + } + break; + case NukiControllerStateLockActionAccepted: + // We are expecting the status + if (command == NukiUtils::CommandStatus) { + NukiUtils::StatusCode statusCode = static_cast((quint8)payload.at(0)); + qCDebug(dcNuki()) << "Controller:" << statusCode; + + switch (statusCode) { + case NukiUtils::StatusCodeAccepted: + // Lets wait for completed + break; + case NukiUtils::StatusCodeCompeted: + emit lockFinished(true); + setState(NukiControllerStateIdle); + break; + default: + break; + } + } + break; + case NukiControllerStateUnlockActionRequestChallange: + // We are expecting callenge message + if (command == NukiUtils::CommandChallenge) { + m_nukiNonce = payload; + setState(NukiControllerStateUnlockActionExecute); + return; + } + break; + case NukiControllerStateUnlockActionAccepted: + // We are expecting the status + if (command == NukiUtils::CommandStatus) { + NukiUtils::StatusCode statusCode = static_cast((quint8)payload.at(0)); + qCDebug(dcNuki()) << "Controller:" << statusCode; + + switch (statusCode) { + case NukiUtils::StatusCodeAccepted: + // Lets wait for completed + break; + case NukiUtils::StatusCodeCompeted: + emit unlockFinished(true); + setState(NukiControllerStateIdle); + break; + default: + break; + } + } + break; + case NukiControllerStateUnlatchActionRequestChallange: + // We are expecting callenge message + if (command == NukiUtils::CommandChallenge) { + m_nukiNonce = payload; + setState(NukiControllerStateUnlatchActionExecute); + return; + } + break; + case NukiControllerStateUnlatchActionAccepted: + // We are expecting the status + if (command == NukiUtils::CommandStatus) { + NukiUtils::StatusCode statusCode = static_cast((quint8)payload.at(0)); + qCDebug(dcNuki()) << "Controller:" << statusCode; + + switch (statusCode) { + case NukiUtils::StatusCodeAccepted: + // Lets wait for completed + break; + case NukiUtils::StatusCodeCompeted: + emit unlatchFinished(true); + setState(NukiControllerStateIdle); + break; + default: + break; + } + } + break; + default: + break; + } + + // Other notification + switch (command) { + case NukiUtils::CommandNukiStates: + processNukiStatesData(payload); + break; + case NukiUtils::CommandErrorReport: + processNukiErrorReport(payload); + break; + case NukiUtils::CommandStatus: { + NukiUtils::StatusCode statusCode = static_cast((quint8)payload.at(0)); + qCDebug(dcNuki()) << "Controller:" << statusCode; + break; + } + default: + qCWarning(dcNuki()) << "Controller: Received unhandled notification:" << command; + break; + } +} + +void NukiController::sendReadLockStateRequest() +{ + qCDebug(dcNuki()) << "Controller: Reading lock state"; + + // Create data for encryption + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(NukiUtils::CommandNukiStates); + + // Create unencrypted PDATA + QByteArray unencryptedMessage = NukiUtils::createRequestMessageForUnencryptedForEncryption(m_nukiAuthenticator->authorizationId(), NukiUtils::CommandRequestData, payload); + + // Encrypt PDATA + QByteArray nonce = m_nukiAuthenticator->generateNonce(crypto_box_NONCEBYTES); + QByteArray encryptedMessage = m_nukiAuthenticator->encryptData(unencryptedMessage, nonce); + + // Create ADATA + QByteArray header; + header.append(nonce); + header.append(m_nukiAuthenticator->authorizationIdRawData()); + header.append(NukiUtils::converUint16ToByteArrayLittleEndian(static_cast(encryptedMessage.length()))); + + // Message ADATA + PDATA + QByteArray message; + message.append(header); + message.append(encryptedMessage); + + // Send data + qCDebug(dcNuki()) << "Controller: Sending read lock states request"; + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(nonce); + if (m_debug) qCDebug(dcNuki()) << " Header :" << NukiUtils::convertByteArrayToHexStringCompact(header); + if (m_debug) qCDebug(dcNuki()) << "Controller: -->" << NukiUtils::convertByteArrayToHexStringCompact(message); + m_userDataCharacteristic->writeCharacteristic(message); +} + +void NukiController::sendRequestChallengeRequest() +{ + qCDebug(dcNuki()) << "Controller: Request challenge"; + + // Create data for encryption + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(NukiUtils::CommandChallenge); + + // Create unencrypted PDATA + QByteArray unencryptedMessage = NukiUtils::createRequestMessageForUnencryptedForEncryption(m_nukiAuthenticator->authorizationId(), NukiUtils::CommandRequestData, payload); + + // Encrypt PDATA + QByteArray nonce = m_nukiAuthenticator->generateNonce(crypto_box_NONCEBYTES); + QByteArray encryptedMessage = m_nukiAuthenticator->encryptData(unencryptedMessage, nonce); + + // Create ADATA + QByteArray header; + header.append(nonce); + header.append(m_nukiAuthenticator->authorizationIdRawData()); + header.append(NukiUtils::converUint16ToByteArrayLittleEndian(static_cast(encryptedMessage.length()))); + + // Message ADATA + PDATA + QByteArray message; + message.append(header); + message.append(encryptedMessage); + + // Send data + qCDebug(dcNuki()) << "Controller: Sending challange request"; + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(nonce); + if (m_debug) qCDebug(dcNuki()) << " Header :" << NukiUtils::convertByteArrayToHexStringCompact(header); + if (m_debug) qCDebug(dcNuki()) << "Controller: -->" << NukiUtils::convertByteArrayToHexStringCompact(message); + m_userDataCharacteristic->writeCharacteristic(message); +} + +void NukiController::sendLockActionRequest(NukiUtils::LockAction lockAction, quint8 flag) +{ + qCDebug(dcNuki()) << "Controller: Send lock request" << lockAction; + + QByteArray nonce = m_nukiAuthenticator->generateNonce(crypto_box_NONCEBYTES); + + // Create data for encryption + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(lockAction); + stream << static_cast(m_nukiAuthenticator->authorizationId()); + stream << flag; + + for (int i = 0; i < m_nukiNonce.length(); i++) { + stream << static_cast(m_nukiNonce.at(i)); + } + + // Create unencrypted PDATA + QByteArray unencryptedMessage = NukiUtils::createRequestMessageForUnencryptedForEncryption(m_nukiAuthenticator->authorizationId(), NukiUtils::CommandLockAction, payload); + + // Encrypt PDATA + QByteArray encryptedMessage = m_nukiAuthenticator->encryptData(unencryptedMessage, nonce); + + // Create ADATA + QByteArray header; + header.append(nonce); + header.append(m_nukiAuthenticator->authorizationIdRawData()); + header.append(NukiUtils::converUint16ToByteArrayLittleEndian(static_cast(encryptedMessage.length()))); + + // Message ADATA + PDATA + QByteArray message; + message.append(header); + message.append(encryptedMessage); + + // Send data + qCDebug(dcNuki()) << "Controller: Sending lock request"; + if (m_debug) qCDebug(dcNuki()) << " Nonce :" << NukiUtils::convertByteArrayToHexStringCompact(nonce); + if (m_debug) qCDebug(dcNuki()) << " Header :" << NukiUtils::convertByteArrayToHexStringCompact(header); + if (m_debug) qCDebug(dcNuki()) << "Controller: -->" << NukiUtils::convertByteArrayToHexStringCompact(message); + + m_userDataCharacteristic->writeCharacteristic(message); +} + +void NukiController::onUserDataCharacteristicChanged(const QByteArray &value) +{ + if (m_debug) qCDebug(dcNuki()) << "Controller: Data received: <--" << NukiUtils::convertByteArrayToHexStringCompact(value); + + if (m_messageBufferCounter <= 0) { + // New data arrived + m_messageBuffer.append(value); + m_messageBufferCounter++; + } else { + // We are currently collecting + m_messageBuffer.append(value); + m_messageBufferCounter++; + + // In the second buffer message is the complete message length + if (m_messageBufferCounter == 2) { + if (m_messageBuffer.count() < 30) { + qCWarning(dcNuki()) << "Controller: Cannot understand message. Rejecting."; + resetMessageBuffer(); + return; + } + + // Parse message length + // ADATA: 24 byte nonce, 4 byte autorization, 2 byte encrypted message length + m_messageBufferAData = m_messageBuffer.left(30); + m_messageBufferPData = m_messageBuffer.right(m_messageBuffer.count() - 30); + + m_messageBufferNonce = m_messageBufferAData.left(24); + QByteArray messageInformation = m_messageBufferAData.right(6); + + QDataStream stream(&messageInformation, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> m_messageBufferIdentifier >> m_messageBufferLength; + if (m_messageBufferPData.count() == m_messageBufferLength) { + processUserDataNotification(m_messageBufferNonce, m_messageBufferIdentifier, m_messageBufferPData); + resetMessageBuffer(); + } + + } else { + // We already know the message length and are still collecting p data + m_messageBufferPData.append(value); + if (m_messageBufferPData.count() == m_messageBufferLength) { + // Message finished + processUserDataNotification(m_messageBufferNonce, m_messageBufferIdentifier, m_messageBufferPData); + resetMessageBuffer(); + } + } + } +} diff --git a/nuki/nukicontroller.h b/nuki/nukicontroller.h new file mode 100644 index 00000000..73d1786c --- /dev/null +++ b/nuki/nukicontroller.h @@ -0,0 +1,113 @@ +#ifndef NUKICONTROLLER_H +#define NUKICONTROLLER_H + +#include +#include +#include + +#include "nukiutils.h" +#include "nukiauthenticator.h" +#include "bluez/bluetoothgattcharacteristic.h" + +class NukiController : public QObject +{ + Q_OBJECT +public: + enum NukiControllerState { + NukiControllerStateIdle, + + // Read state + NukiControllerStateReadingLockStates, + + // Lock action + NukiControllerStateLockActionRequestChallange, + NukiControllerStateLockActionExecute, + NukiControllerStateLockActionAccepted, + + // Unlock action + NukiControllerStateUnlockActionRequestChallange, + NukiControllerStateUnlockActionExecute, + NukiControllerStateUnlockActionAccepted, + + // Unlatch action + NukiControllerStateUnlatchActionRequestChallange, + NukiControllerStateUnlatchActionExecute, + NukiControllerStateUnlatchActionAccepted, + + NukiControllerStateError + }; + Q_ENUM(NukiControllerState) + + explicit NukiController(NukiAuthenticator *nukiAuthenticator, BluetoothGattCharacteristic *userDataCharacteristic, QObject *parent = nullptr); + + // States + NukiUtils::NukiState nukiState() const; + NukiUtils::LockState nukiLockState() const; + NukiUtils::LockTrigger nukiLockTrigger() const; + QDateTime nukiDateTime() const; + int nukiUtcOffset() const; + bool batteryCritical() const; + + // Actions + bool readLockState(); + bool lock(); + bool unlock(); + bool unlatch(); + +private: + NukiAuthenticator *m_nukiAuthenticator = nullptr; + BluetoothGattCharacteristic *m_userDataCharacteristic = nullptr; + + NukiControllerState m_state = NukiControllerStateIdle; + + // Notification parsing helper + QByteArray m_messageBuffer; + QByteArray m_messageBufferAData; + QByteArray m_messageBufferPData; + QByteArray m_messageBufferNonce; + quint32 m_messageBufferIdentifier = 0; + quint16 m_messageBufferLength = 0; + int m_messageBufferCounter = 0; + + // For development debugging + bool m_debug = false; + + // Properties + NukiUtils::NukiState m_nukiState = NukiUtils::NukiStateUninitialized; + NukiUtils::LockState m_nukiLockState = NukiUtils::LockStateUndefined; + NukiUtils::LockTrigger m_nukiLockTrigger = NukiUtils::LockTriggerBluetooth; + QDateTime m_nukiDateTime; + int m_nukiUtcOffset = 0; + bool m_batteryCritical = false; + + QByteArray m_nukiNonce; + + // State machine helpers + void setState(NukiControllerState state); + void resetExpectedData(int expectedCount = 1); + void resetMessageBuffer(); + + // Data processors + void processNukiStatesData(const QByteArray &data); + void processNukiErrorReport(const QByteArray &data); + void processUserDataNotification(const QByteArray nonce, quint32 authorizationIdentifier, const QByteArray &privateData); + + // State action methods + void sendReadLockStateRequest(); + void sendRequestChallengeRequest(); + void sendLockActionRequest(NukiUtils::LockAction lockAction, quint8 flag = 0); + +signals: + void stateChanged(NukiControllerState state); + void readNukiStatesFinished(bool success); + void lockFinished(bool success); + void unlockFinished(bool success); + void unlatchFinished(bool success); + void nukiStatesChanged(); + +private slots: + void onUserDataCharacteristicChanged(const QByteArray &value); + +}; + +#endif // NUKICONTROLLER_H diff --git a/nuki/nukiutils.cpp b/nuki/nukiutils.cpp new file mode 100644 index 00000000..8296ed1c --- /dev/null +++ b/nuki/nukiutils.cpp @@ -0,0 +1,171 @@ +#include "nukiutils.h" +#include "extern-plugininfo.h" + +#include +#include + +QString NukiUtils::convertByteToHexString(const quint8 &byte) +{ + QString hexString(QStringLiteral("0x%1")); + hexString = hexString.arg(byte, 2, 16, QLatin1Char('0')); + return hexString.toStdString().data(); +} + +QString NukiUtils::convertByteArrayToHexString(const QByteArray &byteArray) +{ + QString hexString; + for (int i = 0; i < byteArray.count(); i++) { + hexString.append(convertByteToHexString(static_cast(byteArray.at(i)))); + if (i != byteArray.count() - 1) { + hexString.append(" "); + } + } + + return hexString.toStdString().data(); +} + +QString NukiUtils::convertByteArrayToHexStringCompact(const QByteArray &byteArray) +{ + QString hexString; + for (int i = 0; i < byteArray.length(); i++) { + hexString.append(QString("%1").arg(static_cast(byteArray.at(i)), 2, 16, QLatin1Char('0'))); + } + + return hexString; +} + +QString NukiUtils::convertUint16ToHexString(const quint16 &value) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << value; + + return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x")); +} + +QByteArray NukiUtils::converUint32ToByteArrayLittleEndian(const quint32 &value) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << value; + Q_ASSERT_X(data.length() == 4, "data converting", "Could not convert quint32 value to byte array (little endian)"); + return data; +} + +QByteArray NukiUtils::converUint16ToByteArrayLittleEndian(const quint16 &value) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << value; + Q_ASSERT_X(data.length() == 2, "data converting", "Could not convert quint16 value to byte array (little endian)"); + return data; +} + +quint16 NukiUtils::convertByteArrayToUint16BigEndian(const QByteArray &littleEndianByteArray) +{ + Q_ASSERT_X(littleEndianByteArray.length() == 2, "data converting", "Could not convert byte array (little endian) to quint16 value. Invalid size of byte array."); + + quint16 value = 0; + QByteArray data(littleEndianByteArray); + QDataStream stream(&data, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> value; + return value; +} + +quint32 NukiUtils::convertByteArrayToUint32BigEndian(const QByteArray &littleEndianByteArray) +{ + Q_ASSERT_X(littleEndianByteArray.length() == 4, "data converting", "Could not convert byte array (little endian) to quint32 value. Invalid size of byte array."); + + quint32 value = 0; + QByteArray data(littleEndianByteArray); + QDataStream stream(&data, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> value; + return value; +} + +quint16 NukiUtils::calculateCrc(const QByteArray &data) +{ + quint16 crcValue = 0xffff; + quint16 polynom = 0x1021; + + for (int byte = 0; byte < data.length(); ++byte) { + crcValue ^= (static_cast(data.at(byte)) << 8); + for (quint8 bit = 8; bit > 0; --bit) { + if (crcValue & 0x8000) { + crcValue = (crcValue << 1) ^ polynom; + } else { + crcValue = (crcValue << 1); + } + } + } + + return crcValue; +} + +bool NukiUtils::validateMessageCrc(const QByteArray &message) +{ + quint16 crcValue = 0; + QByteArray crcValueRaw = message.right(2); + QDataStream stream(&crcValueRaw, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> crcValue; + + QByteArray content = message.left(message.count() - 2); + + quint16 calculatedCrcValue = calculateCrc(content); + if (crcValue != calculatedCrcValue) { + qCWarning(dcNuki()) << "CRC CCITT validation failed:" << crcValue << "!=" << calculatedCrcValue; + return false; + } + + return true; +} + +QByteArray NukiUtils::createRequestMessageForUnencrypted(NukiUtils::Command command, const QByteArray &payload) +{ + /* Note: build a message for unencrypted communication with paring service + * 2 Bytes: command identifier (LittleEndian) + * n Bytes: pyload (raw bytes) + * 2 Bytes: crc (LittleEndian) + */ + QByteArray message; + QDataStream stream(&message, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(command); + + // Write payload + for (int i = 0; i < payload.length(); i++) { + stream << static_cast(payload.at(i)); + } + + stream << NukiUtils::calculateCrc(message); + return message; +} + +QByteArray NukiUtils::createRequestMessageForUnencryptedForEncryption(quint32 authenticationId, NukiUtils::Command command, const QByteArray &payload) +{ + /* Note: build a message for encrypted communication with key turner service. This represents the unencrypted PDATA + * 4 Bytes: authentication ID (LittleEndian) + * 2 Bytes: command identifier (LittleEndian) + * n Bytes: pyxload (raw bytes) + * 2 Bytes: crc (LittleEndian) + */ + + QByteArray message; + QDataStream stream(&message, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << authenticationId; + stream << static_cast(command); + + // Write payload + for (int i = 0; i < payload.length(); i++) { + stream << static_cast(payload.at(i)); + } + + stream << NukiUtils::calculateCrc(message); + return message; +} diff --git a/nuki/nukiutils.h b/nuki/nukiutils.h new file mode 100644 index 00000000..c14c576d --- /dev/null +++ b/nuki/nukiutils.h @@ -0,0 +1,167 @@ +#ifndef NUKIUTILS_H +#define NUKIUTILS_H + +#include +#include +#include +#include + +class NukiUtils +{ + Q_GADGET +public: + enum StatusCode { + StatusCodeCompeted = 0x00, + StatusCodeAccepted = 0x01 + }; + Q_ENUM(StatusCode) + + + enum ErrorCode { + ErrorCodeNoError = 0x00, + + // Pairing service error codes + ErrorCodeNotInPairingMode = 0x10, + ErrorCodeBadAuthenticator = 0x11, + ErrorCodeBadPairingParameter = 0x12, + ErrorCodeMaxUsersReached = 0x13, + + // Key turner service error codes + ErrorCodeNotAuthorized = 0x20, + ErrorCodeBadPin = 0x21, + ErrorCodeBadNonce = 0x22, + ErrorCodeBadParameter = 0x23, + ErrorCodeInvalidAuthId = 0x24, + ErrorCodeDisabled = 0x25, + ErrorCodeRemoteNotAllowed = 0x26, + ErrorCodeTimeNotAllowed = 0x27, + ErrorCodeTooManyPinAttempts = 0x28, + ErrorCodeAutoUnlockTooRecent = 0x40, + ErrorCodePositionUnknown = 0x41, + ErrorCodeMotorBlocked = 0x42, + ErrorCodeClutchFailure = 0x43, + ErrorCodeMotorTimeout = 0x44, + ErrorCodeBusy = 0x45, + + // General error codes + ErrorCodeBadCrc = 0xFD, + ErrorCodeBadLength = 0xFE, + ErrorCodeUnknown = 0xFF + }; + Q_ENUM(ErrorCode) + + + enum LockState { + LockStateUncalibrated = 0x00, + LockStateLocked = 0x01, + LockStateUnlocking = 0x02, + LockStateUnlocked = 0x03, + LockStateLocking = 0x04, + LockStateUnlatched = 0x05, + LockStateUnlockedLocknGoActive = 0x06, + LockStateUnlatching = 0x07, + LockStateMotorBlocked = 0xfe, + LockStateUndefined = 0xff + }; + Q_ENUM(LockState) + + + enum LockAction { + LockActionUnlock = 0x01, + LockActionLock = 0x02, + LockActionUnlatch = 0x03, + LockActionLockNGo = 0x04, + LockActionLockNGoWithUnlatch = 0x05, + LockActionFobAction1 = 0x81, + LockActionFobAction2 = 0x82, + LockActionFobAction3 = 0x83 + }; + Q_ENUM(LockAction) + + + enum LockTrigger { + LockTriggerBluetooth = 0x00, + LockTriggerManual = 0x01, + LockTriggerButton = 0x02 + }; + Q_ENUM(LockTrigger) + + + enum NukiState { + NukiStateUninitialized = 0x00, + NukiStatePairingMode = 0x01, + NukiStateDoorMode = 0x02 + }; + Q_ENUM(NukiState) + + + enum Command { + CommandRequestData = 0x0001, + CommandPublicKey = 0x0003, + CommandChallenge = 0x0004, + CommandAuthorizationAuthenticator = 0x0005, + CommandAuthorizationData = 0x0006, + CommandAuthorizationId = 0x0007, + CommandRemoveUserAuthorization = 0x0008, + CommandRequestAuthorizationEntries = 0x0009, + CommandAuthorizationEntry = 0x000A, + CommandAuthorizationDataInvite = 0x000B, + CommandNukiStates = 0x000C, + CommandLockAction = 0x000D, + CommandStatus = 0x000E, + CommandMostRecentCommand = 0x000F, + CommandOpeningsClosingsSummary = 0x0010, + CommandBatteryReport = 0x0011, + CommandErrorReport = 0x0012, + CommandSetConG = 0x0013, + CommandRequestConG = 0x0014, + CommandConG = 0x0015, + CommandSetSecurityPIN = 0x0019, + CommandRequestCalibration = 0x001A, + CommandRequestReboot = 0x001D, + CommandAuthorizationIdConfirmation = 0x001E, + CommandAuthorizationIdInvite = 0x001F, + CommandVerifySecurityPIN = 0x0020, + CommandUpdateTime = 0x0021, + CommandUpdateUserAuthorization = 0x0025, + CommandAuthorizationEntryCount = 0x0027, + CommandRequestDisconnect = 0x0030, + CommandRequestLogEntries = 0x0031, + CommandLogEntry = 0x0032, + CommandLogEntryCount = 0x0033, + CommandEnableLogging = 0x0034, + CommandSetAdvancedConG = 0x0035, + CommandRequestAdvancedConG = 0x0036, + CommandAdvancedConG = 0x0037, + CommandAddTimeControlEntry = 0x0039, + CommandTimeControlEntryId = 0x003A, + CommandRemoveTimeControlEntry = 0x003B, + CommandRequestTimeControlEntries = 0x003C, + CommandTimeControlEntryCount = 0x003D, + CommandTimeControlEntry = 0x003E, + CommandUpdateTimeControlEntry = 0x003F + }; + Q_ENUM(Command) + + // Data helpers + static QString convertByteToHexString(const quint8 &byte); + static QString convertByteArrayToHexString(const QByteArray &byteArray); + static QString convertByteArrayToHexStringCompact(const QByteArray &byteArray); + static QString convertUint16ToHexString(const quint16 &value); + + static QByteArray converUint32ToByteArrayLittleEndian(const quint32 &value); + static QByteArray converUint16ToByteArrayLittleEndian(const quint16 &value); + static quint16 convertByteArrayToUint16BigEndian(const QByteArray &littleEndianByteArray); + static quint32 convertByteArrayToUint32BigEndian(const QByteArray &littleEndianByteArray); + + // Crc calculation + static quint16 calculateCrc(const QByteArray &data); + static bool validateMessageCrc(const QByteArray &message); + + // Message helper + static QByteArray createRequestMessageForUnencrypted(NukiUtils::Command command, const QByteArray &payload); + static QByteArray createRequestMessageForUnencryptedForEncryption(quint32 authenticationId, NukiUtils::Command command, const QByteArray &payload); + +}; + +#endif // NUKIUTILS_H diff --git a/nuki/plugins.pri b/nuki/plugins.pri new file mode 100644 index 00000000..7826456c --- /dev/null +++ b/nuki/plugins.pri @@ -0,0 +1,63 @@ +TEMPLATE = lib +CONFIG += plugin + +QT += network bluetooth dbus + +QMAKE_CXXFLAGS += -Werror -std=c++11 -g +QMAKE_LFLAGS += -std=c++11 + +INCLUDEPATH += /usr/include/nymea +LIBS += -lnymea + +PLUGIN_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/nymea/plugins/ + +# Check if this is a snap build +snappy{ + INCLUDEPATH+=$$(SNAPCRAFT_STAGE)/usr/include/nymea +} + +# Make the device plugin json file visible in the Qt Creator +OTHER_FILES+=$$PWD/deviceplugin"$$TARGET".json + +# NOTE: if the code includes "plugininfo.h", it would fail if we only give it a compiler for $$OUT_PWD/plugininfo.h +# Let's add a dummy target with the plugininfo.h file without any path to allow the developer to just include it like that. + +# Create plugininfo file +plugininfo.target = $$OUT_PWD/plugininfo.h +plugininfo_dummy.target = plugininfo.h +plugininfo.depends = FORCE +plugininfo.commands = nymea-generateplugininfo --filetype i --jsonfile $$PWD/deviceplugin"$$TARGET".json --output plugininfo.h --builddir $$OUT_PWD +plugininfo_dummy.commands = $$plugininfo.commands +QMAKE_EXTRA_TARGETS += plugininfo plugininfo_dummy + +# Create extern-plugininfo file +extern_plugininfo.target = $$OUT_PWD/extern-plugininfo.h +extern_plugininfo_dummy.target = extern-plugininfo.h +extern_plugininfo.depends = FORCE +extern_plugininfo.commands = nymea-generateplugininfo --filetype e --jsonfile $$PWD/deviceplugin"$$TARGET".json --output extern-plugininfo.h --builddir $$OUT_PWD +extern_plugininfo_dummy.commands = $$extern_plugininfo.commands +QMAKE_EXTRA_TARGETS += extern_plugininfo extern_plugininfo_dummy + +# Install translation files +TRANSLATIONS *= $$files($${PWD}/translations/*ts, true) +lupdate.depends = FORCE +lupdate.depends += plugininfo +lupdate.commands = lupdate -recursive -no-obsolete -locations none $$PWD/"$$TARGET".pro; +QMAKE_EXTRA_TARGETS += lupdate + +# make lrelease to build .qm from .ts +lrelease.depends = FORCE +lrelease.commands += lrelease $$files($$PWD/translations/*.ts, true); +lrelease.commands += rsync -a $$PWD/translations/*.qm $$OUT_PWD/translations/; +QMAKE_EXTRA_TARGETS += lrelease + +translations.path = /usr/share/nymea/translations +translations.files = $$[QT_SOURCE_TREE]/translations/*.qm + +HEADERS += $$OUT_PWD/plugininfo.h \ + $$OUT_PWD/extern-plugininfo.h +DEPENDPATH += $$OUT_PWD + +# Install plugin +target.path = $$PLUGIN_PATH +INSTALLS += target translations diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-cs.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-cs.ts new file mode 100644 index 00000000..6f8f31bf --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-cs.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Stiskněte tlačítko Nuki na 5 sekund k aktivování režimu párování dříve než budete pokračovat. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Název + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + MAC adresa + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Sériové číslo + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Připojeno změněno + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Připojeno + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Baterie kritický stav změněno + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Baterie kritický stav + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status změněn + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Režim změněn + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Režim + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Spoušť změněna + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Spoušť + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revize hardwaru změněna + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revize hardwaru + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revize firmwaru změněna + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revize firmwaru + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Zamknout + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Odemknout + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Obnovit + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Stav změněn + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Stav + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Otevřít dveře + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-da.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-da.ts new file mode 100644 index 00000000..e670822f --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-da.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Tryk på Nuki-knappen i fem sekunder for at aktivere parringstilstanden, før du fortsætter. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Navn + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + mac-adresse + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Serienummer + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Forbindelse ændret + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Forbundet + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batteri kritisk ændret + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batteri kritisk + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status ændret + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus ændret + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Udløser ændret + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Udløser + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + hardwarerevision ændret + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Hardwarerevision + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmwarerevision ændret + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmwarerevision + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Lås + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Lås op + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Opdatér + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Tilstand ændret + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Tilstand + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Åbn dør + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-de.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-de.ts new file mode 100644 index 00000000..f1ee49bc --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-de.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Bevor es weitergeht drücke bitte die Nuki-Taste für 5 Sekunden um den Pairing-Modus zu aktivieren. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + Nuki + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Name + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + MAC Adresse + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Seriennummer + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Verbunden geändert + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Verbunden + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batterie Ladung kritisch geändert + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batterie Ladung kritisch + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status geändert + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus geändert + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Auslöser geändert + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Auslöser + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Hardware-Revision geändert + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Hardware-Revision + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmware-Version geändert + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmware-Version + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Zusperren + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Aufsperren + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Aktualisieren + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Status geändert + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Status + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Tür öffnen + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-en_US.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-en_US.ts new file mode 100644 index 00000000..7b08d112 --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-en_US.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-es.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-es.ts new file mode 100644 index 00000000..00c3f6ed --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-es.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Pulse el botón Nuki durante 5 segundos para activar el modo de enlazado antes de continuar. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Nombre + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + Dirección MAC + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Número de serie + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Conexión modificada + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Conectado + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batería en estado crítico modificada + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batería en estado crítico + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Estado modificado + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Estado + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modo modificado + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modo + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Disparador modificado + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Disparador + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisión de hardware modificada + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisión de hardware + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisión de firmware modificada + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisión de firmware + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Bloqueo + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Desbloqueo + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Actualizar + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Estado modificado + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Estado + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Abrir puerta + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-fr.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-fr.ts new file mode 100644 index 00000000..5d8b8ad3 --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-fr.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Veuillez appuyer pendant 5 secondes sur le bouton Nuki afin d'activer le mode de couplage avant de continuer. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Nom + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + Adresse MAC + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Numéro de serie + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Connexion modifiée + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Connecté + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Statut de batterie critique modifié + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batterie critique + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Statut modifié + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Statut + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Mode modifié + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Mode + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Déclencheur modifié + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Déclencheur + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Révision du matériel (hardware) modifiée + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Révision du matériel (hardware) + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Version du progiciel modifiée + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Version du progiciel + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Verrouiller + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Déverrouiller + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Rafraîchir + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Statut modifié + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Statut + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Ouvrir la porte + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-it.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-it.ts new file mode 100644 index 00000000..1be93aa7 --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-it.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Premi il pulsante Nuki per 5 secondi per attivare la sincronizzazione prima di continuare. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Nome + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + Indirizzo MAC + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Numero di serie + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Connesso modificato + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Connesso + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batteria critica modificata + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batteria critica + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Stato modificato + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Stato + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modalità modificata + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modalità + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Trigger modificato + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Trigger + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisione hardware modificata + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisione hardware + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisione firmware modificata + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisione firmware + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Blocca + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Sblocca + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Aggiorna + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Stato modificato + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Stato + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Apri porta + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-nl.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-nl.ts new file mode 100644 index 00000000..1225a68d --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-nl.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Houd, alvorens verder te gaan, de Nuki-knop 5 seconden ingedrukt om de koppelmodus te activeren. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Naam + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + MAC address + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Serienummer + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Verbonden gewijzigd + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Verbonden + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batterij kritiek gewijzigd + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Batterij kritiek + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status gewijzigd + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Status + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus gewijzigd + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modus + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Trigger gewijzigd + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Trigger + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Hardware-revisie gewijzigd + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Hardware-revisie + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmware-revisie gewijzigd + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Firmware-revisie + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Vergrendelen + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Ontgrendelen + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Vernieuwen + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Status gewijzigd + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Status + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Deur openen + + + diff --git a/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-pt.ts b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-pt.ts new file mode 100644 index 00000000..bb4995f4 --- /dev/null +++ b/nuki/translations/e5806d75-a40e-4766-a272-5a3a8d3ed625-pt.ts @@ -0,0 +1,169 @@ + + + + + DevicePluginNuki + + Device is already in use. + + + + Bluetooth is not available on this system. + + + + Bluetooth device not found. + + + + Please press the Nuki button for 5 seconds in order to activate the pairing mode before you continue. + Pressione o botão Nuki durante 5 segundos para ativar o modo de emparelhamento antes de continuar. + + + + Nuki + + Nuki + The name of the vendor ({bf313b83-2ac5-4d22-bf0e-c13d3b4caf52}) +---------- +The name of the plugin Nuki ({e5806d75-a40e-4766-a272-5a3a8d3ed625}) + + + + Smartlock + The name of the DeviceClass ({4a1cc5d9-9b44-4632-8db0-66d64efd4767}) + Smartlock + + + Name + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {2477abba-874b-4c48-b543-7b911ff215b3}) + Nome + + + MAC address + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {30976794-6066-4f72-8135-6d50499247a5}) + Endereço MAC + + + Serial number + The name of the ParamType (DeviceClass: nuki, Type: device, ID: {ea51d911-f94a-4d2d-97fd-9f1d4c6519bf}) + Número de série + + + Connected changed + The name of the EventType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Conectado alterado + + + Connected + The name of the ParamType (DeviceClass: nuki, EventType: connected, ID: {d5fbd774-4e87-4c7c-8c92-f094352897f6}) +---------- +The name of the StateType ({d5fbd774-4e87-4c7c-8c92-f094352897f6}) of DeviceClass nuki + Conectado + + + Battery critical changed + The name of the EventType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Bateria crítica alterada + + + Battery critical + The name of the ParamType (DeviceClass: nuki, EventType: batteryCritical, ID: {e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) +---------- +The name of the StateType ({e9ffe14f-b71d-44cd-96c7-eb90fe243e13}) of DeviceClass nuki + Bateria crítica + + + Status changed + The name of the EventType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Estado alterado + + + Status + The name of the ParamType (DeviceClass: nuki, EventType: status, ID: {a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) +---------- +The name of the StateType ({a47dec8b-4df2-4acd-895b-bfeacbcb6f2e}) of DeviceClass nuki + Estado + + + Mode changed + The name of the EventType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modo alterado + + + Mode + The name of the ParamType (DeviceClass: nuki, EventType: mode, ID: {4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) +---------- +The name of the StateType ({4e291e6a-2b90-4e6c-bad4-5400e6db4f05}) of DeviceClass nuki + Modo + + + Trigger changed + The name of the EventType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Acionamento alterado + + + Trigger + The name of the ParamType (DeviceClass: nuki, EventType: trigger, ID: {b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) +---------- +The name of the StateType ({b67bc7a6-2d6b-46e8-8e59-e4eab2e5292a}) of DeviceClass nuki + Acionamento + + + Hardware revision changed + The name of the EventType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisão de hardware alterada + + + Hardware revision + The name of the ParamType (DeviceClass: nuki, EventType: hardwareRevision, ID: {b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) +---------- +The name of the StateType ({b1b0eafb-e5f2-47d3-bd18-74a21129f9b5}) of DeviceClass nuki + Revisão de hardware + + + Firmware revision changed + The name of the EventType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisão de firmware alterada + + + Firmware revision + The name of the ParamType (DeviceClass: nuki, EventType: firmwareRevision, ID: {9dc0115b-cdb4-472c-961b-b182f77a576f}) +---------- +The name of the StateType ({9dc0115b-cdb4-472c-961b-b182f77a576f}) of DeviceClass nuki + Revisão de firmware + + + Lock + The name of the ActionType ({55d25891-89b9-4a9f-a2b3-774eccf30183}) of DeviceClass nuki + Bloquear + + + Unlock + The name of the ActionType ({76e96738-5336-4b9a-87f7-1822307b5a39}) of DeviceClass nuki + Desbloquear + + + Refresh + The name of the ActionType ({7c9d5c5d-d8c1-424b-8620-daa3a757576b}) of DeviceClass nuki + Atualizar + + + State changed + The name of the EventType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Estado alterado + + + State + The name of the ParamType (DeviceClass: nuki, EventType: state, ID: {07a09bd8-b342-4e33-92cd-0af21f8689fa}) +---------- +The name of the StateType ({07a09bd8-b342-4e33-92cd-0af21f8689fa}) of DeviceClass nuki + Estado + + + Open door + The name of the ActionType ({45be8d24-17c3-422b-b264-381e673bb3c8}) of DeviceClass nuki + Abrir porta + + + diff --git a/nymea-plugins.pro b/nymea-plugins.pro index 60a276e2..b24bdf29 100644 --- a/nymea-plugins.pro +++ b/nymea-plugins.pro @@ -30,6 +30,7 @@ PLUGIN_DIRS = \ mqttclient \ netatmo \ networkdetector \ + nuki \ onewire \ openuv \ openweathermap \