From 882b7b9327edb3dd73fa3e82eba83c0405f91b83 Mon Sep 17 00:00:00 2001 From: Tomasz Sterna Date: Tue, 9 Jun 2015 16:14:42 +0200 Subject: [PATCH] Handle multiple paired Pebbles Moved Pebble discovery to WatchConnector. Removed empty DBusConnector. Minor firmware handling fixes. --- app/pebblefirmware.cpp | 1 + app/qml/pages/WatchInfo.qml | 10 +-- app/qml/pebble.qml | 2 + app/translations/pebble-es.ts | 2 + app/translations/pebble-pl.ts | 2 + app/translations/pebble-zh_CN.ts | 2 + app/translations/pebble.ts | 2 + daemon/daemon.pro | 2 - daemon/dbusconnector.cpp | 77 ------------------ daemon/dbusconnector.h | 31 -------- daemon/manager.cpp | 22 +----- daemon/manager.h | 17 ++-- daemon/watchconnector.cpp | 132 +++++++++++++++++++++++-------- daemon/watchconnector.h | 22 +++--- 14 files changed, 133 insertions(+), 191 deletions(-) delete mode 100644 daemon/dbusconnector.cpp delete mode 100644 daemon/dbusconnector.h diff --git a/app/pebblefirmware.cpp b/app/pebblefirmware.cpp index 4e0fc08..33460e5 100644 --- a/app/pebblefirmware.cpp +++ b/app/pebblefirmware.cpp @@ -18,6 +18,7 @@ void PebbleFirmware::updateLatest(QString hw) QNetworkRequest req; req.setUrl(firmwareURL.arg(hw).arg(hw.startsWith("snowy_") ? "release-v3" : "release-v2")); req.setRawHeader("Cache-Control", "no-cache"); + qDebug() << "Getting latest firmware" << req.url(); nm->get(req); } diff --git a/app/qml/pages/WatchInfo.qml b/app/qml/pages/WatchInfo.qml index af4a740..a1c421c 100644 --- a/app/qml/pages/WatchInfo.qml +++ b/app/qml/pages/WatchInfo.qml @@ -28,7 +28,7 @@ Page { text: qsTr("Address") } Label { - text: pebbled.info.address + text: pebbled.info.address || "" } Label { @@ -36,7 +36,7 @@ Page { text: qsTr("Serial Number") } Label { - text: pebbled.info.serial + text: pebbled.info.serial || "" } Label { @@ -69,7 +69,7 @@ Page { text: qsTr("Recovery") } Label { - text: app.recoveryVersion + text: app.recoveryVersion || qsTr("unknown") } Label { @@ -77,7 +77,7 @@ Page { text: qsTr("Running") } Label { - text: app.firmwareVersion + text: app.firmwareVersion || qsTr("unknown") } Label { @@ -89,7 +89,7 @@ Page { } } Button { - visible: app.firmwareLatest && app.firmwareVersion && app.firmwareVersion !== app.firmwareLatest + visible: app.firmwareLatest && app.firmwareVersion !== app.firmwareLatest text: qsTr("Upgrade Firmware") anchors { left: parent.left diff --git a/app/qml/pebble.qml b/app/qml/pebble.qml index 380ff7e..0643f79 100644 --- a/app/qml/pebble.qml +++ b/app/qml/pebble.qml @@ -22,6 +22,8 @@ ApplicationWindow recoveryVersion = firmware.version } else { firmwareVersion = firmware.version + } + if (firmware.hardware) { hardwareVersion = firmware.hardware } }) diff --git a/app/translations/pebble-es.ts b/app/translations/pebble-es.ts index 28ddd18..8ca8b7f 100644 --- a/app/translations/pebble-es.ts +++ b/app/translations/pebble-es.ts @@ -425,6 +425,8 @@ Si esto tarda mucho, comprueba que el reloj esté emparejado correctamente. + + unknown diff --git a/app/translations/pebble-pl.ts b/app/translations/pebble-pl.ts index 4e11b08..8d431d8 100644 --- a/app/translations/pebble-pl.ts +++ b/app/translations/pebble-pl.ts @@ -453,6 +453,8 @@ Jeśli nie zostaje znaleziony sprawdź czy jest w zasięgu i czy jest sparowany Najnowszy + + unknown nie wiadomo diff --git a/app/translations/pebble-zh_CN.ts b/app/translations/pebble-zh_CN.ts index 092ce00..655d162 100644 --- a/app/translations/pebble-zh_CN.ts +++ b/app/translations/pebble-zh_CN.ts @@ -405,6 +405,8 @@ If it can't be found please check it's available and paired in Bluetoo 最新 + + unknown 未知 diff --git a/app/translations/pebble.ts b/app/translations/pebble.ts index 843ceef..0479dc1 100644 --- a/app/translations/pebble.ts +++ b/app/translations/pebble.ts @@ -404,6 +404,8 @@ If it can't be found please check it's available and paired in Bluetoo + + unknown diff --git a/daemon/daemon.pro b/daemon/daemon.pro index 40d3290..4520b57 100644 --- a/daemon/daemon.pro +++ b/daemon/daemon.pro @@ -16,7 +16,6 @@ SOURCES += \ voicecallhandler.cpp \ notificationmanager.cpp \ watchconnector.cpp \ - dbusconnector.cpp \ appmanager.cpp \ musicmanager.cpp \ datalogmanager.cpp \ @@ -36,7 +35,6 @@ HEADERS += \ voicecallhandler.h \ notificationmanager.h \ watchconnector.h \ - dbusconnector.h \ settings.h \ appmanager.h \ musicmanager.h \ diff --git a/daemon/dbusconnector.cpp b/daemon/dbusconnector.cpp deleted file mode 100644 index ccc127d..0000000 --- a/daemon/dbusconnector.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "dbusconnector.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -//dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.ListAdapters -//dbus-send --system --dest=org.bluez --print-reply $path org.bluez.Adapter.GetProperties -//dbus-send --system --dest=org.bluez --print-reply $devpath org.bluez.Device.GetProperties -//dbus-send --system --dest=org.bluez --print-reply $devpath org.bluez.Input.Connect - -DBusConnector::DBusConnector(QObject *parent) : - QObject(parent), l(metaObject()->className()) -{} - -bool DBusConnector::findPebble() -{ - QDBusConnection system = QDBusConnection::systemBus(); - - QDBusReply> ListAdaptersReply = system.call( - QDBusMessage::createMethodCall("org.bluez", "/", "org.bluez.Manager", - "ListAdapters")); - if (not ListAdaptersReply.isValid()) { - qCCritical(l) << ListAdaptersReply.error().message(); - return false; - } - - QList adapters = ListAdaptersReply.value(); - - if (adapters.isEmpty()) { - qCDebug(l) << "No BT adapters found"; - return false; - } - - QDBusReply AdapterPropertiesReply = system.call( - QDBusMessage::createMethodCall("org.bluez", adapters[0].path(), "org.bluez.Adapter", - "GetProperties")); - if (not AdapterPropertiesReply.isValid()) { - qCCritical(l) << AdapterPropertiesReply.error().message(); - return false; - } - - QList devices; - AdapterPropertiesReply.value()["Devices"].value() >> devices; - - foreach (QDBusObjectPath path, devices) { - QDBusReply DevicePropertiesReply = system.call( - QDBusMessage::createMethodCall("org.bluez", path.path(), "org.bluez.Device", - "GetProperties")); - if (not DevicePropertiesReply.isValid()) { - qCCritical(l) << DevicePropertiesReply.error().message(); - continue; - } - - const QVariantMap &dict = DevicePropertiesReply.value(); - - QString tmp = dict["Name"].toString(); - qCDebug(l) << "Found BT device:" << tmp; - if (tmp.startsWith("Pebble")) { - qCDebug(l) << "Found Pebble:" << tmp; - QBluetoothAddress addr(dict["Address"].toString()); - QBluetoothLocalDevice dev; - if (dev.pairingStatus(addr) == QBluetoothLocalDevice::AuthorizedPaired) { - pebbleProps = dict; - emit pebbleChanged(); - return true; - } - } - } - - return false; -} diff --git a/daemon/dbusconnector.h b/daemon/dbusconnector.h deleted file mode 100644 index 6b48f99..0000000 --- a/daemon/dbusconnector.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef DBUSCONNECTOR_H -#define DBUSCONNECTOR_H - -#include -#include -#include -#include - -// TODO Remove this. - -class DBusConnector : public QObject -{ - Q_OBJECT - QLoggingCategory l; - - Q_PROPERTY(QVariantMap pebble READ pebble NOTIFY pebbleChanged) - QVariantMap pebbleProps; - -public: - explicit DBusConnector(QObject *parent = 0); - - QVariantMap pebble() const { return pebbleProps; } - -signals: - void pebbleChanged(); - -public slots: - bool findPebble(); -}; - -#endif // DBUSCONNECTOR_H diff --git a/daemon/manager.cpp b/daemon/manager.cpp index 93b6b13..179d05e 100644 --- a/daemon/manager.cpp +++ b/daemon/manager.cpp @@ -10,7 +10,6 @@ Manager::Manager(Settings *settings, QObject *parent) : QObject(parent), l(metaObject()->className()), settings(settings), proxy(new PebbledProxy(this)), watch(new WatchConnector(this)), - dbus(new DBusConnector(this)), upload(new UploadManager(watch, this)), apps(new AppManager(this)), bank(new BankManager(watch, upload, apps, this)), @@ -67,8 +66,8 @@ Manager::Manager(Settings *settings, QObject *parent) : session.registerObject("/org/pebbled/Watch", proxy); session.registerService("org.pebbled"); - connect(dbus, &DBusConnector::pebbleChanged, proxy, &PebbledProxy::NameChanged); - connect(dbus, &DBusConnector::pebbleChanged, proxy, &PebbledProxy::AddressChanged); + connect(watch, &WatchConnector::pebbleChanged, proxy, &PebbledProxy::NameChanged); + connect(watch, &WatchConnector::pebbleChanged, proxy, &PebbledProxy::AddressChanged); connect(watch, &WatchConnector::connectedChanged, proxy, &PebbledProxy::ConnectedChanged); connect(watch, &WatchConnector::versionsChanged, proxy, &PebbledProxy::InfoChanged); connect(bank, &BankManager::slotsChanged, proxy, &PebbledProxy::AppSlotsChanged); @@ -79,11 +78,7 @@ Manager::Manager(Settings *settings, QObject *parent) : // Set BT icon for notification notification.setImage("icon-system-bluetooth-device"); - if (btDevice.isValid()) { - qCDebug(l) << "BT local name:" << btDevice.name(); - connect(dbus, SIGNAL(pebbleChanged()), SLOT(onPebbleChanged())); - dbus->findPebble(); - } + watch->findPebbles(); } Manager::~Manager() @@ -100,17 +95,6 @@ void Manager::onSettingsChanged() qCWarning(l) << __FUNCTION__ << "Not implemented!"; } -void Manager::onPebbleChanged() -{ - const QVariantMap & pebble = dbus->pebble(); - QString name = pebble["Name"].toString(); - if (name.isEmpty()) { - qCDebug(l) << "Pebble gone"; - } else { - watch->deviceConnect(name, pebble["Address"].toString()); - } -} - void Manager::onConnectedChanged() { QString message = QString("%1 %2") diff --git a/daemon/manager.h b/daemon/manager.h index 2079de0..a605ed1 100644 --- a/daemon/manager.h +++ b/daemon/manager.h @@ -2,7 +2,6 @@ #define MANAGER_H #include "watchconnector.h" -#include "dbusconnector.h" #include "uploadmanager.h" #include "voicecallmanager.h" #include "notificationmanager.h" @@ -15,7 +14,6 @@ #include "settings.h" #include -#include #include #include #include @@ -35,14 +33,11 @@ class Manager : public QObject, protected QDBusContext friend class PebbledProxy; - QBluetoothLocalDevice btDevice; - Settings *settings; PebbledProxy *proxy; WatchConnector *watch; - DBusConnector *dbus; UploadManager *upload; AppManager *apps; BankManager *bank; @@ -79,7 +74,6 @@ public slots: private slots: void onSettingChanged(const QString &key); void onSettingsChanged(); - void onPebbleChanged(); void onConnectedChanged(); void onActiveVoiceCallChanged(); void onVoiceError(const QString &message); @@ -113,16 +107,15 @@ class PebbledProxy : public QObject, protected QDBusContext Q_PROPERTY(QVariantList AllApps READ AllApps NOTIFY AllAppsChanged) inline Manager* manager() const { return static_cast(parent()); } - inline QVariantMap pebble() const { return manager()->dbus->pebble(); } public: inline explicit PebbledProxy(QObject *parent) : QObject(parent), l(metaObject()->className()) {} - inline QString Name() const { return pebble()["Name"].toString(); } - inline QString Address() const { return pebble()["Address"].toString(); } - inline QVariantMap Info() const { return manager()->watch->versions().toMap(); } - inline bool Connected() const { return manager()->watch->isConnected(); } + inline QString Name() const { qCDebug(l) << manager()->watch->name(); return manager()->watch->name(); } + inline QString Address() const { qCDebug(l) << manager()->watch->address().toString(); return manager()->watch->address().toString(); } + inline QVariantMap Info() const { qCDebug(l) << manager()->watch->versions().toMap(); return manager()->watch->versions().toMap(); } + inline bool Connected() const { qCDebug(l) << manager()->watch->isConnected(); return manager()->watch->isConnected(); } inline QString AppUuid() const { return manager()->currentAppUuid.toString(); } QStringList AppSlots() const; @@ -131,7 +124,7 @@ class PebbledProxy : public QObject, protected QDBusContext public slots: inline void Disconnect() { manager()->watch->disconnect(); } - inline void Reconnect() { manager()->watch->reconnect(); } + inline void Reconnect() { manager()->watch->connect(); } inline void Ping(uint val) { manager()->watch->ping(val); } inline void SyncTime() { manager()->watch->time(); } diff --git a/daemon/watchconnector.cpp b/daemon/watchconnector.cpp index d9cdd67..09006c0 100644 --- a/daemon/watchconnector.cpp +++ b/daemon/watchconnector.cpp @@ -1,6 +1,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "unpacker.h" #include "watchconnector.h" @@ -64,12 +70,13 @@ bool WatchConnector::WatchVersions::isEmpty() const } WatchConnector::WatchConnector(QObject *parent) : - QObject(parent), l(metaObject()->className()), socket(nullptr), is_connected(false) + QObject(parent), l(metaObject()->className()), + socket(nullptr), is_connected(false), currentPebble(0), _last_address(0) { reconnectTimer.setSingleShot(true); - connect(&reconnectTimer, SIGNAL(timeout()), SLOT(reconnect())); + QObject::connect(&reconnectTimer, SIGNAL(timeout()), SLOT(connect())); timeSyncTimer.setSingleShot(true); - connect(&timeSyncTimer, SIGNAL(timeout()), SLOT(time())); + QObject::connect(&timeSyncTimer, SIGNAL(timeout()), SLOT(time())); timeSyncTimer.setInterval(4 * 60 * 60 * 1000); // sync time every 4 hours firmwareMapping.insert(UNKNOWN, "unknown"); @@ -128,28 +135,71 @@ WatchConnector::~WatchConnector() { } -void WatchConnector::deviceDiscovered(const QBluetoothDeviceInfo &device) +//dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.ListAdapters +//dbus-send --system --dest=org.bluez --print-reply $path org.bluez.Adapter.GetProperties +//dbus-send --system --dest=org.bluez --print-reply $devpath org.bluez.Device.GetProperties +//dbus-send --system --dest=org.bluez --print-reply $devpath org.bluez.Input.Connect +bool WatchConnector::findPebbles() { - //FIXME TODO: Configurable - if (device.name().startsWith("Pebble")) { - qCDebug(l) << "Found Pebble:" << device.name() << '(' << device.address().toString() << ')'; - handleWatch(device.name(), device.address().toString()); - } else { - qCDebug(l) << "Found other device:" << device.name() << '(' << device.address().toString() << ')'; + pebbles.clear(); + currentPebble = 0; + + QDBusConnection system = QDBusConnection::systemBus(); + + QDBusReply> ListAdaptersReply = system.call( + QDBusMessage::createMethodCall("org.bluez", "/", "org.bluez.Manager", + "ListAdapters")); + if (not ListAdaptersReply.isValid()) { + qCCritical(l) << ListAdaptersReply.error().message(); + return false; } -} -void WatchConnector::deviceConnect(const QString &name, const QString &address) -{ - if (name.startsWith("Pebble")) handleWatch(name, address); -} + QList adapters = ListAdaptersReply.value(); -void WatchConnector::reconnect() -{ - qCDebug(l) << "reconnect" << _last_name; - if (!_last_name.isEmpty() && !_last_address.isEmpty()) { - deviceConnect(_last_name, _last_address); + if (adapters.isEmpty()) { + qCDebug(l) << "No BT adapters found"; + return false; + } + + QDBusReply AdapterPropertiesReply = system.call( + QDBusMessage::createMethodCall("org.bluez", adapters[0].path(), "org.bluez.Adapter", + "GetProperties")); + if (not AdapterPropertiesReply.isValid()) { + qCCritical(l) << AdapterPropertiesReply.error().message(); + return false; + } + + QList devices; + AdapterPropertiesReply.value()["Devices"].value() >> devices; + + foreach (QDBusObjectPath path, devices) { + QDBusReply DevicePropertiesReply = system.call( + QDBusMessage::createMethodCall("org.bluez", path.path(), "org.bluez.Device", + "GetProperties")); + if (not DevicePropertiesReply.isValid()) { + qCCritical(l) << DevicePropertiesReply.error().message(); + continue; + } + + const QVariantMap &dict = DevicePropertiesReply.value(); + + QString tmp = dict["Name"].toString(); + qCDebug(l) << "Found BT device:" << tmp; + if (tmp.startsWith("Pebble")) { + qCDebug(l) << "Found Pebble:" << tmp; + QBluetoothAddress addr(dict["Address"].toString()); + QBluetoothLocalDevice dev; + if (dev.pairingStatus(addr) == QBluetoothLocalDevice::AuthorizedPaired) { + pebbles.insert(dict["Name"].toString(), addr); + } + } } + + if (pebbles.size()) { + scheduleReconnect(); + } + + return true; } void WatchConnector::disconnect() @@ -162,11 +212,23 @@ void WatchConnector::disconnect() qCDebug(l) << "stopped timers"; } -void WatchConnector::handleWatch(const QString &name, const QString &address) +void WatchConnector::connect() { - qCDebug(l) << "handleWatch" << name << address; + if (currentPebble >= pebbles.count()) { + currentPebble = 0; + } + + QString _name = pebbles.keys().at(currentPebble); + QBluetoothAddress _address = pebbles.value(_name); + + qCDebug(l) << "connect watch" << currentPebble << _name << _address.toString(); reconnectTimer.stop(); + if (_address.isNull()) { + qCWarning(l) << "No known pebble"; + return; + } + // Check if bluetooth is on QBluetoothLocalDevice host; bool btOff = host.hostMode() == QBluetoothLocalDevice::HostPoweredOff; @@ -181,20 +243,18 @@ void WatchConnector::handleWatch(const QString &name, const QString &address) socket->deleteLater(); } - _last_name = name; - _last_address = address; _versions.clear(); qCDebug(l) << "Creating socket"; socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); - connect(socket, SIGNAL(readyRead()), SLOT(onReadSocket())); - connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(onBytesWritten(qint64))); - connect(socket, SIGNAL(connected()), SLOT(onConnected())); - connect(socket, SIGNAL(disconnected()), SLOT(onDisconnected())); - connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(onError(QBluetoothSocket::SocketError))); + QObject::connect(socket, SIGNAL(readyRead()), SLOT(onReadSocket())); + QObject::connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(onBytesWritten(qint64))); + QObject::connect(socket, SIGNAL(connected()), SLOT(onConnected())); + QObject::connect(socket, SIGNAL(disconnected()), SLOT(onDisconnected())); + QObject::connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(onError(QBluetoothSocket::SocketError))); // FIXME: Assuming port 1 (with Pebble) - socket->connectToService(QBluetoothAddress(address), 1); + socket->connectToService(_address, 1); } QString WatchConnector::decodeEndpoint(uint val) @@ -319,7 +379,9 @@ void WatchConnector::onConnected() } sendMessage(watchVERSION, QByteArray(1, 0)); emit connectedChanged(); - if (name() != _last_name) emit nameChanged(); + quint64 new_address = address().toUInt64(); + if (new_address != _last_address) emit pebbleChanged(); + _last_address = new_address; time(); } } @@ -358,7 +420,11 @@ void WatchConnector::scheduleReconnect() void WatchConnector::onError(QBluetoothSocket::SocketError error) { if (error == QBluetoothSocket::UnknownSocketError) { - qCDebug(l) << error << socket->errorString(); + QString errorString = socket->errorString(); + qCDebug(l) << error << errorString; + if (errorString.endsWith(" down")) { + currentPebble++; + } } else { qCCritical(l) << "error connecting Pebble:" << error << socket->errorString(); } @@ -369,7 +435,7 @@ void WatchConnector::sendData(const QByteArray &data) writeData.append(data); if (socket == nullptr) { qCDebug(l) << "no socket - reconnecting"; - reconnect(); + connect(); } else if (is_connected) { qCDebug(l) << "writing" << data.length() << "bytes to socket"; if (PROTOCOL_DEBUG) qCDebug(l) << data.toHex(); diff --git a/daemon/watchconnector.h b/daemon/watchconnector.h index 518493b..fa65f6b 100644 --- a/daemon/watchconnector.h +++ b/daemon/watchconnector.h @@ -8,10 +8,8 @@ #include #include #include -#include -#include #include -#include +#include #include class WatchConnector : public QObject @@ -21,7 +19,7 @@ class WatchConnector : public QObject Q_ENUMS(Endpoint) - Q_PROPERTY(QString name READ name NOTIFY nameChanged) + Q_PROPERTY(QString name READ name NOTIFY pebbleChanged) Q_PROPERTY(QString connected READ isConnected NOTIFY connectedChanged) public: @@ -205,7 +203,8 @@ class WatchConnector : public QObject virtual ~WatchConnector(); inline bool isConnected() const { return is_connected; } - inline QString name() const { return socket != nullptr ? socket->peerName() : ""; } + inline QString name() const { return pebbles.keys(address()).at(0); } + inline QBluetoothAddress address() const { return socket != nullptr ? socket->peerAddress() : QBluetoothAddress(); } inline WatchVersions versions() const { return _versions; } void setEndpointHandler(uint endpoint, const EndpointHandlerFunc &func); @@ -215,15 +214,15 @@ class WatchConnector : public QObject static QString decodeEndpoint(uint val); signals: - void nameChanged(); + void pebbleChanged(); void versionsChanged(); void connectedChanged(); public slots: - void deviceConnect(const QString &name, const QString &address); + bool findPebbles(); void scheduleReconnect(); + void connect(); void disconnect(); - void reconnect(); void sendMessage(uint endpoint, const QByteArray &data, const EndpointHandlerFunc &callback = EndpointHandlerFunc()); void ping(uint cookie); @@ -248,8 +247,6 @@ public slots: void endPhoneCall(uint cookie=0); private slots: - void deviceDiscovered(const QBluetoothDeviceInfo&); - void handleWatch(const QString &name, const QString &address); void onReadSocket(); void onBytesWritten(qint64); void onConnected(); @@ -267,8 +264,9 @@ private slots: QByteArray writeData; QTimer reconnectTimer; QTimer timeSyncTimer; - QString _last_name; - QString _last_address; + QMap pebbles; + int currentPebble; + quint64 _last_address; WatchVersions _versions; };