diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-06 17:22:25 +0200 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-09 01:57:32 +0200 |
| commit | 7283842cbed6a378d430552d327eab4a27775538 (patch) | |
| tree | 708f4a2b4e702ddcc07bef8e6fdcd8f8a32a23ef /daemon | |
| parent | d3d54722d8532bd649db6792126c0a990712e26c (diff) | |
Moved watchConnector to daemon and implemented daemon interface for QML
Diffstat (limited to 'daemon')
| -rw-r--r-- | daemon/daemon.pro | 9 | ||||
| -rw-r--r-- | daemon/dbusadaptor.cpp | 16 | ||||
| -rw-r--r-- | daemon/dbusadaptor.h | 12 | ||||
| -rw-r--r-- | daemon/manager.cpp | 4 | ||||
| -rw-r--r-- | daemon/manager.h | 6 | ||||
| -rw-r--r-- | daemon/watchconnector.cpp | 300 | ||||
| -rw-r--r-- | daemon/watchconnector.h | 132 |
7 files changed, 455 insertions, 24 deletions
diff --git a/daemon/daemon.pro b/daemon/daemon.pro index c4b6a76..deadea0 100644 --- a/daemon/daemon.pro +++ b/daemon/daemon.pro @@ -5,25 +5,24 @@ CONFIG -= app_bundle CONFIG += link_pkgconfig QT -= gui -INCLUDEPATH += ../lib -LIBS += -L$$OUT_PWD/../lib -lpebble - QT += bluetooth dbus contacts PKGCONFIG += commhistory-qt5 mlite5 QMAKE_CXXFLAGS += -std=c++0x SOURCES += \ daemon.cpp \ + manager.cpp \ voicecallmanager.cpp \ voicecallhandler.cpp \ - manager.cpp \ + watchconnector.cpp \ dbusconnector.cpp \ dbusadaptor.cpp HEADERS += \ + manager.h \ voicecallmanager.h \ voicecallhandler.h \ - manager.h \ + watchconnector.h \ dbusconnector.h \ dbusadaptor.h diff --git a/daemon/dbusadaptor.cpp b/daemon/dbusadaptor.cpp index 914f9f2..6460dca 100644 --- a/daemon/dbusadaptor.cpp +++ b/daemon/dbusadaptor.cpp @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusAdaptor -a dbusadaptor org.pebbled.xml + * Command line was: qdbusxml2cpp -a daemon/dbusadaptor -p app/daemonproxy daemon/org.pebbled.xml * * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). * @@ -18,40 +18,40 @@ #include <QtCore/QVariant> /* - * Implementation of adaptor class DBusAdaptor + * Implementation of adaptor class PebbledAdaptor */ -DBusAdaptor::DBusAdaptor(QObject *parent) +PebbledAdaptor::PebbledAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } -DBusAdaptor::~DBusAdaptor() +PebbledAdaptor::~PebbledAdaptor() { // destructor } -QString DBusAdaptor::address() const +QString PebbledAdaptor::address() const { // get the value of property address return qvariant_cast< QString >(parent()->property("address")); } -bool DBusAdaptor::connected() const +bool PebbledAdaptor::connected() const { // get the value of property connected return qvariant_cast< bool >(parent()->property("connected")); } -QString DBusAdaptor::name() const +QString PebbledAdaptor::name() const { // get the value of property name return qvariant_cast< QString >(parent()->property("name")); } -QVariantMap DBusAdaptor::pebble() const +QVariantMap PebbledAdaptor::pebble() const { // get the value of property pebble return qvariant_cast< QVariantMap >(parent()->property("pebble")); diff --git a/daemon/dbusadaptor.h b/daemon/dbusadaptor.h index 9d8759a..d1662c6 100644 --- a/daemon/dbusadaptor.h +++ b/daemon/dbusadaptor.h @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusAdaptor -a dbusadaptor org.pebbled.xml + * Command line was: qdbusxml2cpp -a daemon/dbusadaptor -p app/daemonproxy daemon/org.pebbled.xml * * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). * @@ -9,8 +9,8 @@ * before re-generating it. */ -#ifndef DBUSADAPTOR_H_1404605591 -#define DBUSADAPTOR_H_1404605591 +#ifndef DBUSADAPTOR_H_1404660047 +#define DBUSADAPTOR_H_1404660047 #include <QtCore/QObject> #include <QtDBus/QtDBus> @@ -26,7 +26,7 @@ QT_END_NAMESPACE /* * Adaptor class for interface org.pebbled */ -class DBusAdaptor: public QDBusAbstractAdaptor +class PebbledAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.pebbled") @@ -43,8 +43,8 @@ class DBusAdaptor: public QDBusAbstractAdaptor " </interface>\n" "") public: - DBusAdaptor(QObject *parent); - virtual ~DBusAdaptor(); + PebbledAdaptor(QObject *parent); + virtual ~PebbledAdaptor(); public: // PROPERTIES Q_PROPERTY(QString address READ address) diff --git a/daemon/manager.cpp b/daemon/manager.cpp index 4ba2a8b..f25e724 100644 --- a/daemon/manager.cpp +++ b/daemon/manager.cpp @@ -37,8 +37,8 @@ Manager::Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallMan dbus->findPebble(); } - DBusProxy *proxy = new DBusProxy(this); - DBusAdaptor *adaptor = new DBusAdaptor(proxy); + PebbledProxy *proxy = new PebbledProxy(this); + PebbledAdaptor *adaptor = new PebbledAdaptor(proxy); QDBusConnection connection = QDBusConnection::sessionBus(); connection.registerObject("/", proxy); connection.registerService("org.pebbled"); diff --git a/daemon/manager.h b/daemon/manager.h index b052355..b9aa01b 100644 --- a/daemon/manager.h +++ b/daemon/manager.h @@ -19,7 +19,7 @@ class Manager : public QObject { Q_OBJECT - friend class DBusProxy; + friend class PebbledProxy; QBluetoothLocalDevice btDevice; @@ -55,7 +55,7 @@ protected slots: }; -class DBusProxy : public QObject +class PebbledProxy : public QObject { Q_OBJECT Q_PROPERTY(QVariantMap pebble READ pebble) @@ -69,7 +69,7 @@ class DBusProxy : public QObject bool pebbleConnected() { return static_cast<Manager*>(parent())->watch->isConnected(); } public: - explicit DBusProxy(QObject *parent) : QObject(parent) {} + explicit PebbledProxy(QObject *parent) : QObject(parent) {} }; diff --git a/daemon/watchconnector.cpp b/daemon/watchconnector.cpp new file mode 100644 index 0000000..18d287e --- /dev/null +++ b/daemon/watchconnector.cpp @@ -0,0 +1,300 @@ +#include "watchconnector.h" +#include <QTimer> +#include <QDateTime> + +using namespace watch; + +static int __reconnect_timeout = 5000; //ms + +WatchConnector::WatchConnector(QObject *parent) : + QObject(parent), socket(nullptr), is_connected(false) +{} + +WatchConnector::~WatchConnector() +{ +} + +void WatchConnector::deviceDiscovered(const QBluetoothDeviceInfo &device) +{ + //FIXME TODO: Configurable + if (device.name().startsWith("Pebble")) { + qDebug() << "Found Pebble:" << device.name() << '(' << device.address().toString() << ')'; + handleWatch(device.name(), device.address().toString()); + } else { + qDebug() << "Found other device:" << device.name() << '(' << device.address().toString() << ')'; + } +} + +void WatchConnector::deviceConnect(const QString &name, const QString &address) +{ + if (name.startsWith("Pebble")) handleWatch(name, address); +} + +void WatchConnector::reconnect() +{ + qDebug() << "reconnect" << _last_name; + if (!_last_name.isEmpty() && !_last_address.isEmpty()) { + deviceConnect(_last_name, _last_address); + } +} + +void WatchConnector::handleWatch(const QString &name, const QString &address) +{ + qDebug() << "handleWatch" << name << address; + if (socket != nullptr && socket->isOpen()) { + socket->close(); + socket->deleteLater(); + } + + bool emit_name = (_last_name != name); + _last_name = name; + _last_address = address; + if (emit_name) emit nameChanged(); + + qDebug() << "Creating socket"; + socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket); + + connect(socket, SIGNAL(readyRead()), SLOT(onReadSocket())); + connect(socket, SIGNAL(connected()), SLOT(onConnected())); + connect(socket, SIGNAL(disconnected()), SLOT(onDisconnected())); + connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(onError(QBluetoothSocket::SocketError))); + + // FIXME: Assuming port 1 (with Pebble) + socket->connectToService(QBluetoothAddress(address), QBluetoothUuid(QBluetoothUuid::SerialPort)); +} + +QString WatchConnector::decodeEndpoint(unsigned int val) +{ + //FIXME: Create a map of these values + switch(val) { + case watchTIME: + return "TIME"; + case watchVERSION: + return "VERSION"; + case watchPHONE_VERSION: + return "PHONE_VERSION"; + case watchSYSTEM_MESSAGE: + return "SYSTEM_MESSAGE"; + case watchMUSIC_CONTROL: + return "MUSIC_CONTROL"; + case watchPHONE_CONTROL: + return "PHONE_CONTROL"; + case watchAPPLICATION_MESSAGE: + return "APP_MSG"; + case watchLAUNCHER: + return "LAUNCHER"; + case watchLOGS: + return "LOGS"; + case watchPING: + return "PING"; + case watchLOG_DUMP: + return "DUMP"; + case watchRESET: + return "RESET"; + case watchAPP: + return "APP"; + case watchAPP_LOGS: + return "APP_LOGS"; + case watchNOTIFICATION: + return "NOTIFICATION"; + case watchRESOURCE: + return "RESOURCE"; + case watchAPP_MANAGER: + return "APP_MANAG"; + case watchSCREENSHOT: + return "SCREENSHOT"; + case watchPUTBYTES: + return "PUTBYTES"; + default: + return "Unknown: "+ QString::number(val); + } +} + +void WatchConnector::decodeMsg(QByteArray data) +{ + unsigned int datalen = 0; + int index = 0; + datalen = (data.at(index) << 8) + data.at(index+1); + index += 2; + + unsigned int endpoint = 0; + endpoint = (data.at(index) << 8) + data.at(index+1); + index += 2; + + qDebug() << "Length:" << datalen << " Endpoint:" << decodeEndpoint(endpoint); + qDebug() << "Data:" << data.mid(index).toHex(); + if (endpoint == watchPHONE_CONTROL) { + if (data.length() >= 5) { + if (data.at(4) == callHANGUP) { + emit hangup(); + } + } + } +} + +void WatchConnector::onReadSocket() +{ + qDebug() << "read"; + + QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender()); + if (!socket) return; + + while (socket->bytesAvailable()) { + QByteArray line = socket->readAll(); + emit messageReceived(socket->peerName(), QString::fromUtf8(line.constData(), line.length())); + decodeMsg(line); + } +} + +void WatchConnector::onConnected() +{ + qDebug() << "Connected!"; + bool was_connected = is_connected; + is_connected = true; + if (not was_connected) emit connectedChanged(); +} + +void WatchConnector::onDisconnected() +{ + qDebug() << "Disconnected!"; + + bool was_connected = is_connected; + is_connected = false; + + QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender()); + if (!socket) return; + + if (was_connected) emit connectedChanged(); + + socket->deleteLater(); + + // Try to connect again after a timeout + QTimer::singleShot(__reconnect_timeout, this, SLOT(reconnect())); +} + +void WatchConnector::onError(QBluetoothSocket::SocketError error) { + qWarning() << "Error connecting Pebble" << error << socket->errorString(); +} + +void WatchConnector::sendData(const QByteArray &data) +{ + if (socket == nullptr) return; + + socket->write(data); +} + +void WatchConnector::sendMessage(unsigned int endpoint, QByteArray data) +{ + qDebug() << "Sending message"; + QByteArray msg; + + // First send the length + msg.append((data.length() & 0xFF00) >> 8); + msg.append(data.length() & 0xFF); + + // Then the endpoint + msg.append((endpoint & 0xFF00) >> 8); + msg.append(endpoint & 0xFF); + + // Finally the data + msg.append(data); + + sendData(msg); +} + +void WatchConnector::buildData(QByteArray &res, QStringList data) +{ + for (QString d : data) + { + QByteArray tmp = d.left(0xF0).toUtf8(); + res.append(tmp.length() & 0xFF); + res.append(tmp); + } +} + +QByteArray WatchConnector::buildMessageData(unsigned int lead, QStringList data) +{ + QByteArray res; + res.append(lead & 0xFF); + buildData(res, data); + + return res; +} + +void WatchConnector::ping(unsigned int val) +{ + QByteArray res; + res.append((char)0); + + res.append((char)((val >> 24) & 0xff)); + res.append((char)((val >> 16) & 0xff)); + res.append((char)((val >> 8) & 0xff)); + res.append((char)(val & 0xff)); + + sendMessage(watchPING, res); +} + +QString WatchConnector::timeStamp() +{ + return QString::number(QDateTime::currentMSecsSinceEpoch()); +} + +void WatchConnector::sendNotification(unsigned int lead, QString sender, QString data, QString subject) +{ + QStringList tmp; + tmp.append(sender); + tmp.append(data); + tmp.append(timeStamp()); + if (lead == 0) tmp.append(subject); + + QByteArray res = buildMessageData(lead, tmp); + + sendMessage(watchNOTIFICATION, res); +} + +void WatchConnector::sendSMSNotification(QString sender, QString data) +{ + sendNotification(1, sender, data, ""); +} + +void WatchConnector::sendEmailNotification(QString sender, QString data, QString subject) +{ + sendNotification(0, sender, data, subject); +} + +void WatchConnector::phoneControl(char act, unsigned int cookie, QStringList datas) +{ + QByteArray head; + head.append((char)act); + head.append((cookie >> 24)& 0xFF); + head.append((cookie >> 16)& 0xFF); + head.append((cookie >> 8)& 0xFF); + head.append(cookie & 0xFF); + if (datas.length()>0) buildData(head, datas); + + sendMessage(watchPHONE_CONTROL, head); +} + +void WatchConnector::ring(QString number, QString name, bool incoming, unsigned int cookie) +{ + QStringList tmp; + tmp.append(number); + tmp.append(name); + + char act = callINCOMING; + if (!incoming) { + act = callOUTGOING; + } + + phoneControl(act, cookie, tmp); +} + +void WatchConnector::startPhoneCall(unsigned int cookie) +{ + phoneControl(callSTART, cookie, QStringList()); +} + +void WatchConnector::endPhoneCall(unsigned int cookie) +{ + phoneControl(callEND, cookie, QStringList()); +} diff --git a/daemon/watchconnector.h b/daemon/watchconnector.h new file mode 100644 index 0000000..493856b --- /dev/null +++ b/daemon/watchconnector.h @@ -0,0 +1,132 @@ +/* + Copyright (C) 2014 Jouni Roivas + All rights reserved. + + You may use this file under the terms of BSD license as follows: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the authors nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef WATCHCONNECTOR_H +#define WATCHCONNECTOR_H + +#include <QObject> +#include <QPointer> +#include <QStringList> +#include <QBluetoothDeviceInfo> +#include <QBluetoothSocket> +#include <QBluetoothServiceInfo> + +using namespace QtBluetooth; + +namespace watch +{ + +class WatchConnector : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name NOTIFY nameChanged) + Q_PROPERTY(QString connected READ isConnected NOTIFY connectedChanged) +public: + enum { + watchTIME = 11, + watchVERSION = 16, + watchPHONE_VERSION = 17, + watchSYSTEM_MESSAGE = 18, + watchMUSIC_CONTROL = 32, + watchPHONE_CONTROL = 33, + watchAPPLICATION_MESSAGE = 48, + watchLAUNCHER = 49, + watchLOGS = 2000, + watchPING = 2001, + watchLOG_DUMP = 2002, + watchRESET = 2003, + watchAPP = 2004, + watchAPP_LOGS = 2006, + watchNOTIFICATION = 3000, + watchRESOURCE = 4000, + watchAPP_MANAGER = 6000, + watchSCREENSHOT = 8000, + watchPUTBYTES = 48879 + }; + enum { + callANSWER = 1, + callHANGUP = 2, + callGET_STATE = 3, + callINCOMING = 4, + callOUTGOING = 5, + callMISSED = 6, + callRING = 7, + callSTART = 8, + callEND = 9 + }; + explicit WatchConnector(QObject *parent = 0); + virtual ~WatchConnector(); + bool isConnected() const { return is_connected; } + QString name() const { if (socket != nullptr) return socket->peerName(); return ""; } + + QString timeStamp(); + QString decodeEndpoint(unsigned int val); + +signals: + void messageReceived(QString peer, QString msg); + void nameChanged(); + void connectedChanged(); + void hangup(); + +public slots: + void sendData(const QByteArray &data); + void sendMessage(unsigned int endpoint, QByteArray data); + void ping(unsigned int val); + void sendNotification(unsigned int lead, QString sender, QString data, QString subject); + void sendSMSNotification(QString sender, QString data); + void sendEmailNotification(QString sender, QString data, QString subject); + + void buildData(QByteArray &res, QStringList data); + QByteArray buildMessageData(unsigned int lead, QStringList data); + + void phoneControl(char act, unsigned int cookie, QStringList datas); + void ring(QString number, QString name, bool incoming=true, unsigned int cookie=0); + void startPhoneCall(unsigned int cookie=0); + void endPhoneCall(unsigned int cookie=0); + + void deviceConnect(const QString &name, const QString &address); + void deviceDiscovered(const QBluetoothDeviceInfo&); + void handleWatch(const QString &name, const QString &address); + void onReadSocket(); + void onConnected(); + void onDisconnected(); + void onError(QBluetoothSocket::SocketError error); + void reconnect(); + +private: + void decodeMsg(QByteArray data); + + QPointer<QBluetoothSocket> socket; + bool is_connected; + QString _last_name; + QString _last_address; +}; +} + +#endif // WATCHCONNECTOR_H |
