summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorTomasz Sterna <tomek@xiaoka.com>2014-07-06 17:22:25 +0200
committerTomasz Sterna <tomek@xiaoka.com>2014-07-09 01:57:32 +0200
commit7283842cbed6a378d430552d327eab4a27775538 (patch)
tree708f4a2b4e702ddcc07bef8e6fdcd8f8a32a23ef /daemon
parentd3d54722d8532bd649db6792126c0a990712e26c (diff)
Moved watchConnector to daemon and implemented daemon interface for QML
Diffstat (limited to 'daemon')
-rw-r--r--daemon/daemon.pro9
-rw-r--r--daemon/dbusadaptor.cpp16
-rw-r--r--daemon/dbusadaptor.h12
-rw-r--r--daemon/manager.cpp4
-rw-r--r--daemon/manager.h6
-rw-r--r--daemon/watchconnector.cpp300
-rw-r--r--daemon/watchconnector.h132
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