summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <maemo@javispedro.com>2013-05-08 18:04:31 +0200
committerJavier S. Pedro <maemo@javispedro.com>2013-05-08 18:04:31 +0200
commitccd19d2b7ee4184503ea46b98333b27a5613190e (patch)
treef78cc3f3c946d7a4f8167f72fb20703c65494d84
parent6003bf81107dd9be51589c074b74c5af82bfc8ab (diff)
downloadsowatch-ccd19d2b7ee4184503ea46b98333b27a5613190e.tar.gz
sowatch-ccd19d2b7ee4184503ea46b98333b27a5613190e.zip
big change: a new abstract BluetoothWatch class
-rw-r--r--libsowatchbt/bluetoothwatch.cpp176
-rw-r--r--libsowatchbt/bluetoothwatch.h74
-rw-r--r--libsowatchbt/bluetoothwatchscanner.cpp31
-rw-r--r--libsowatchbt/bluetoothwatchscanner.h37
-rw-r--r--libsowatchbt/libsowatchbt.pro38
-rw-r--r--libsowatchbt/sowatchbt.h9
-rw-r--r--libsowatchbt/sowatchbt_global.h12
-rw-r--r--liveview/liveview.cpp93
-rw-r--r--liveview/liveview.h52
-rw-r--r--liveview/liveview.pro39
-rw-r--r--liveview/liveviewplugin.cpp45
-rw-r--r--liveview/liveviewplugin.h25
-rw-r--r--liveview/liveviewscanner.cpp26
-rw-r--r--liveview/liveviewscanner.h21
-rw-r--r--metawatch/metawatch.cpp199
-rw-r--r--metawatch/metawatch.h47
-rw-r--r--metawatch/metawatch.pro5
-rw-r--r--metawatch/metawatchdigital.cpp4
-rw-r--r--metawatch/metawatchdigital.h2
-rw-r--r--metawatch/metawatchdigitalsimulator.cpp4
-rw-r--r--metawatch/metawatchscanner.cpp18
-rw-r--r--metawatch/metawatchscanner.h12
-rw-r--r--metawatchwatchlets/bubble.pngbin0 -> 263 bytes
-rw-r--r--metawatchwatchlets/bubble_tip.pngbin0 -> 187 bytes
-rw-r--r--metawatchwatchlets/idle_border.pngbin0 -> 198 bytes
-rw-r--r--metawatchwatchlets/idle_call.pngbin0 -> 197 bytes
-rw-r--r--metawatchwatchlets/idle_mail.pngbin0 -> 196 bytes
-rw-r--r--metawatchwatchlets/idle_msg.pngbin0 -> 191 bytes
-rw-r--r--sowatch.pro16
-rw-r--r--sowatchd/sowatchd.pro3
-rw-r--r--sowatchd/watchhandler.cpp4
31 files changed, 742 insertions, 250 deletions
diff --git a/libsowatchbt/bluetoothwatch.cpp b/libsowatchbt/bluetoothwatch.cpp
new file mode 100644
index 0000000..d977b67
--- /dev/null
+++ b/libsowatchbt/bluetoothwatch.cpp
@@ -0,0 +1,176 @@
+#include "bluetoothwatch.h"
+
+using namespace sowatch;
+QTM_USE_NAMESPACE
+
+const int BluetoothWatch::connectRetryTimes[] = {
+ 5, 10, 30, 60, 120, 300
+};
+
+BluetoothWatch::BluetoothWatch(const QBluetoothAddress& address, QObject *parent)
+ : Watch(parent),
+ _localDev(new QBluetoothLocalDevice(this)),
+ _address(address),
+ _socket(0),
+ _connected(false),
+ _connectRetries(0),
+ _connectTimer(new QTimer(this)),
+ _connectAlignedTimer(new QSystemAlignedTimer(this))
+{
+ _connectTimer->setSingleShot(true);
+ _connectAlignedTimer->setSingleShot(true);
+
+ connect(_connectTimer, SIGNAL(timeout()), SLOT(handleConnectTimer()));
+ connect(_connectAlignedTimer, SIGNAL(timeout()), SLOT(handleConnectTimer()));
+ connect(_localDev, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
+ SLOT(handleLocalDevModeChanged(QBluetoothLocalDevice::HostMode)));
+
+ // Check to see if we can connect right away
+ if (_localDev->isValid() &&
+ _localDev->hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
+ // Do an initial connection attempt after a short delay
+ // (To give time for other plugins to initialize, etc.)
+ scheduleConnect();
+ } else {
+ qDebug() << "Not starting MetaWatch connection because BT is off";
+ }
+}
+
+BluetoothWatch::~BluetoothWatch()
+{
+ if (_socket) {
+ _socket->close();
+ delete _socket;
+ }
+}
+
+bool BluetoothWatch::isConnected() const
+{
+ return _connected;
+}
+
+void BluetoothWatch::scheduleConnect()
+{
+ if (_connected ||
+ _connectAlignedTimer->isActive() || _connectTimer->isActive()) {
+ // Already connected or already scheduled to connect.
+ return;
+ }
+
+ _connectRetries = 0;
+ _connectTimer->start(100);
+}
+
+void BluetoothWatch::scheduleRetryConnect()
+{
+ if (_connected ||
+ _connectAlignedTimer->isActive() || _connectTimer->isActive()) {
+ // Already connected or already scheduled to connect.
+ return;
+ }
+
+ int timeToNextRetry;
+ if (_connectRetries >= connectRetryTimesSize) {
+ timeToNextRetry = connectRetryTimes[connectRetryTimesSize - 1];
+ } else {
+ timeToNextRetry = connectRetryTimes[_connectRetries];
+ _connectRetries++; // Increase the number of connection attemps
+ }
+
+ qDebug() << "Backing off for" << timeToNextRetry << "seconds for next retry";
+ _connectAlignedTimer->start(timeToNextRetry / 2, timeToNextRetry * 2);
+ if (_connectAlignedTimer->lastError() != QSystemAlignedTimer::NoError) {
+ // Hopefully a future version of QSystemAlignedTimer implements this fallback
+ // For now, we have to do it ourselves.
+ qDebug() << "Note: using plain QTimer for retry";
+ _connectTimer->start(timeToNextRetry * 1000);
+ }
+}
+
+void BluetoothWatch::unscheduleConnect()
+{
+ _connectAlignedTimer->stop();
+ _connectTimer->stop();
+}
+
+void BluetoothWatch::connectToWatch()
+{
+ delete _socket; //Delete socket from previous connect if any.
+ _socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket);
+
+ connect(_socket, SIGNAL(connected()), SLOT(handleSocketConnected()));
+ connect(_socket, SIGNAL(disconnected()), SLOT(handleSocketDisconnected()));
+ connect(_socket, SIGNAL(readyRead()), SLOT(handleSocketData()));
+ connect(_socket, SIGNAL(error(QBluetoothSocket::SocketError)),
+ SLOT(handleSocketError(QBluetoothSocket::SocketError)));
+ connect(_socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)),
+ SLOT(handleSocketState(QBluetoothSocket::SocketState)));
+
+ _socket->connectToService(_address, 1, QIODevice::ReadWrite | QIODevice::Unbuffered);
+}
+
+void BluetoothWatch::handleConnectTimer()
+{
+ connectToWatch();
+}
+
+void BluetoothWatch::handleLocalDevModeChanged(QBluetoothLocalDevice::HostMode state)
+{
+ qDebug() << "Local bluetooth device mode changed to" << state;
+ if (state == QBluetoothLocalDevice::HostPoweredOff) {
+ // Host bluetooth was powered down
+ // Assume the socket has been disconnected
+ handleSocketDisconnected();
+ // Cancel any pending connection attempts
+ unscheduleConnect();
+ } else {
+ // Host bluetooth might have been powered up
+ if (!_connected) {
+ scheduleConnect();
+ }
+ }
+}
+
+void BluetoothWatch::handleSocketConnected()
+{
+ if (!_connected) {
+ qDebug() << "connected";
+
+ _connected = true;
+ _connectRetries = 0;
+
+ setupBluetoothWatch();
+
+ emit connected();
+ }
+}
+
+void BluetoothWatch::handleSocketDisconnected()
+{
+ // Signal disconnection if necessary
+ if (_connected) {
+ qDebug() << "disconnected";
+
+ _connected = false;
+ desetupBluetoothWatch();
+
+ emit disconnected();
+ }
+
+ // Setup reconnection attempt if necessary
+ if (_localDev->hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
+ scheduleRetryConnect();
+ }
+}
+
+void BluetoothWatch::handleSocketError(QBluetoothSocket::SocketError error)
+{
+ qWarning() << "Socket error:" << error;
+ // Seems that sometimes a disconnection event may not be generated.
+ handleSocketDisconnected();
+}
+
+void BluetoothWatch::handleSocketState(QBluetoothSocket::SocketState state)
+{
+ qDebug() << "socket is in" << state;
+}
diff --git a/libsowatchbt/bluetoothwatch.h b/libsowatchbt/bluetoothwatch.h
new file mode 100644
index 0000000..882e7c0
--- /dev/null
+++ b/libsowatchbt/bluetoothwatch.h
@@ -0,0 +1,74 @@
+#ifndef SOWATCHBT_BLUETOOTHWATCH_H
+#define SOWATCHBT_BLUETOOTHWATCH_H
+
+#include <QtConnectivity/QBluetoothAddress>
+#include <QtConnectivity/QBluetoothSocket>
+#include <QtConnectivity/QBluetoothLocalDevice>
+#include <QtSystemInfo/QSystemAlignedTimer>
+#include <sowatch.h>
+#include "sowatchbt_global.h"
+
+namespace sowatch
+{
+
+using QTM_PREPEND_NAMESPACE(QBluetoothSocket);
+using QTM_PREPEND_NAMESPACE(QBluetoothAddress);
+using QTM_PREPEND_NAMESPACE(QSystemAlignedTimer);
+using QTM_PREPEND_NAMESPACE(QBluetoothLocalDevice);
+
+class SOWATCHBT_EXPORT BluetoothWatch : public Watch
+{
+ Q_OBJECT
+
+public:
+ BluetoothWatch(const QBluetoothAddress& address, QObject *parent = 0);
+ ~BluetoothWatch();
+
+ bool isConnected() const;
+
+protected:
+ /** Start the initial connection attempt, reset failed connection timers. */
+ void scheduleConnect();
+ /** Schedule an new connection attempt, consider the current one failed. */
+ void scheduleRetryConnect();
+ /** Cancel any pending connection attempts. */
+ void unscheduleConnect();
+
+ /** Attempt a connection to the watch right now. */
+ virtual void connectToWatch();
+
+ /** To be overriden; should configure a newly connected watch. */
+ virtual void setupBluetoothWatch() = 0;
+ /** To be overriden; handle a sudden watch disconnection. */
+ virtual void desetupBluetoothWatch() = 0;
+
+private slots:
+ void handleConnectTimer();
+ void handleLocalDevModeChanged(QBluetoothLocalDevice::HostMode state);
+ void handleSocketConnected();
+ void handleSocketDisconnected();
+ void handleSocketError(QBluetoothSocket::SocketError error);
+ void handleSocketState(QBluetoothSocket::SocketState error);
+
+protected:
+ /** Local BT device used. */
+ QBluetoothLocalDevice *_localDev;
+ /** BT address of the watch we are trying to connect to. */
+ QBluetoothAddress _address;
+ /** Socket to the watch. */
+ QBluetoothSocket *_socket;
+ /** Whether we have succesfully connected to the watch or not. */
+ bool _connected;
+
+private:
+ // Timers to retry the connection when the watch is not found.
+ static const int connectRetryTimesSize = 6;
+ static const int connectRetryTimes[connectRetryTimesSize];
+ short _connectRetries;
+ QTimer *_connectTimer;
+ QSystemAlignedTimer *_connectAlignedTimer;
+};
+
+}
+
+#endif // SOWATCHBT_BLUETOOTHWATCH_H
diff --git a/libsowatchbt/bluetoothwatchscanner.cpp b/libsowatchbt/bluetoothwatchscanner.cpp
new file mode 100644
index 0000000..eeae5f7
--- /dev/null
+++ b/libsowatchbt/bluetoothwatchscanner.cpp
@@ -0,0 +1,31 @@
+#include <QtConnectivity/QBluetoothDeviceInfo>
+#include <QtConnectivity/QBluetoothAddress>
+
+#include "bluetoothwatchscanner.h"
+
+QTM_USE_NAMESPACE
+using namespace sowatch;
+
+BluetoothWatchScanner::BluetoothWatchScanner(QObject *parent) :
+ WatchScanner(parent),
+ _agent(new QBluetoothServiceDiscoveryAgent(this))
+{
+ connect(_agent, SIGNAL(finished()), this, SIGNAL(finished()));
+ connect(_agent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
+ this, SLOT(handleDiscoveredService(QBluetoothServiceInfo)));
+}
+
+void BluetoothWatchScanner::start()
+{
+ if (_agent->isActive()) {
+ _agent->stop();
+ }
+ _agent->start();
+ qDebug() << "started bluetooth scan";
+ emit started();
+}
+
+void BluetoothWatchScanner::setUuidFilter(const QBluetoothUuid & uuid)
+{
+ _agent->setUuidFilter(uuid);
+}
diff --git a/libsowatchbt/bluetoothwatchscanner.h b/libsowatchbt/bluetoothwatchscanner.h
new file mode 100644
index 0000000..1ab974a
--- /dev/null
+++ b/libsowatchbt/bluetoothwatchscanner.h
@@ -0,0 +1,37 @@
+#ifndef BLUETOOTHWATCHSCANNER_H
+#define BLUETOOTHWATCHSCANNER_H
+
+#include <sowatch.h>
+#include <QtConnectivity/QBluetoothServiceDiscoveryAgent>
+
+#include "sowatchbt_global.h"
+
+namespace sowatch
+{
+
+using QTM_PREPEND_NAMESPACE(QBluetoothServiceDiscoveryAgent);
+using QTM_PREPEND_NAMESPACE(QBluetoothServiceInfo);
+using QTM_PREPEND_NAMESPACE(QBluetoothUuid);
+
+class SOWATCHBT_EXPORT BluetoothWatchScanner : public WatchScanner
+{
+ Q_OBJECT
+
+public:
+ BluetoothWatchScanner(QObject *parent);
+
+ void start();
+
+protected:
+ void setUuidFilter(const QBluetoothUuid & uuid);
+
+protected slots:
+ virtual void handleDiscoveredService(const QBluetoothServiceInfo& info) = 0;
+
+private:
+ QBluetoothServiceDiscoveryAgent *_agent;
+};
+
+}
+
+#endif // BLUETOOTHWATCHSCANNER_H
diff --git a/libsowatchbt/libsowatchbt.pro b/libsowatchbt/libsowatchbt.pro
new file mode 100644
index 0000000..a707778
--- /dev/null
+++ b/libsowatchbt/libsowatchbt.pro
@@ -0,0 +1,38 @@
+TARGET = sowatchbt
+TEMPLATE = lib
+VERSION = 1.0.0
+
+# Qt Mobility 1.2
+maemo5 {
+ CONFIG += mobility12
+} else {
+ CONFIG += mobility
+}
+MOBILITY += connectivity systeminfo
+
+DEFINES += SOWATCHBT_LIBRARY
+
+SOURCES += \
+ bluetoothwatch.cpp \
+ bluetoothwatchscanner.cpp
+
+HEADERS += sowatchbt.h sowatchbt_global.h \
+ bluetoothwatch.h \
+ bluetoothwatchscanner.h
+
+LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
+INCLUDEPATH += $$PWD/../libsowatch
+DEPENDPATH += $$PWD/../libsowatch
+
+install_headers.files = $$HEADERS
+
+install_headers.path = /usr/include/sowatch
+!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
+ target.path = /opt/sowatch/lib
+ install_translations.path = /opt/sowatch/i18n
+} else {
+ target.path = /usr/lib
+ install_translations.path = /usr/share/sowatch/i18n
+}
+
+INSTALLS += install_headers target
diff --git a/libsowatchbt/sowatchbt.h b/libsowatchbt/sowatchbt.h
new file mode 100644
index 0000000..a60f835
--- /dev/null
+++ b/libsowatchbt/sowatchbt.h
@@ -0,0 +1,9 @@
+#ifndef SOWATCHBT_H
+#define SOWATCHBT_H
+
+#include "sowatchbt_global.h"
+
+#include "bluetoothwatch.h"
+#include "bluetoothwatchscanner.h"
+
+#endif // SOWATCHBT_H
diff --git a/libsowatchbt/sowatchbt_global.h b/libsowatchbt/sowatchbt_global.h
new file mode 100644
index 0000000..72c724e
--- /dev/null
+++ b/libsowatchbt/sowatchbt_global.h
@@ -0,0 +1,12 @@
+#ifndef SOWATCHBT_GLOBAL_H
+#define SOWATCHBT_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(SOWATCHBT_LIBRARY)
+# define SOWATCHBT_EXPORT Q_DECL_EXPORT
+#else
+# define SOWATCHBT_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // SOWATCHBT_GLOBAL_H
diff --git a/liveview/liveview.cpp b/liveview/liveview.cpp
new file mode 100644
index 0000000..b6644d8
--- /dev/null
+++ b/liveview/liveview.cpp
@@ -0,0 +1,93 @@
+#include "liveview.h"
+
+using namespace sowatch;
+QTM_USE_NAMESPACE
+
+LiveView::LiveView(ConfigKey* settings, QObject* parent) :
+ BluetoothWatch(QBluetoothAddress(settings->value("address").toString()), parent),
+ _settings(settings->getSubkey(QString(), this))
+{
+
+}
+
+QPaintEngine* LiveView::paintEngine() const
+{
+ return 0; // TODO
+}
+
+int LiveView::metric(PaintDeviceMetric metric) const
+{
+ return 0; // TODO
+}
+
+QString LiveView::model() const
+{
+ return "liveview";
+}
+
+QStringList LiveView::buttons() const
+{
+ return QStringList();
+}
+
+bool LiveView::isConnected() const
+{
+ return false;
+}
+
+bool LiveView::busy() const
+{
+ return false; // TODO
+}
+
+void LiveView::setDateTime(const QDateTime& dateTime)
+{
+
+}
+void LiveView::queryDateTime()
+{
+
+}
+QDateTime LiveView::dateTime() const
+{
+ return QDateTime::currentDateTime(); // TODO
+}
+
+void LiveView::queryBatteryLevel()
+{
+
+}
+int LiveView::batteryLevel() const
+{
+ return 0; // TODO
+}
+
+void LiveView::queryCharging()
+{
+
+}
+
+bool LiveView::charging() const
+{
+ return false; // TODO
+}
+
+void LiveView::displayIdleScreen()
+{
+
+}
+
+void LiveView::displayNotification(Notification *notification)
+{
+
+}
+
+void LiveView::displayApplication()
+{
+
+}
+
+void LiveView::vibrate(int msecs)
+{
+
+}
diff --git a/liveview/liveview.h b/liveview/liveview.h
new file mode 100644
index 0000000..39b1b92
--- /dev/null
+++ b/liveview/liveview.h
@@ -0,0 +1,52 @@
+#ifndef LIVEVIEW_H
+#define LIVEVIEW_H
+
+#include <sowatch.h>
+#include <sowatchbt.h>
+
+namespace sowatch
+{
+
+class LiveView : public BluetoothWatch
+{
+ Q_OBJECT
+
+public:
+ explicit LiveView(ConfigKey *settings, QObject *parent = 0);
+ ~LiveView();
+
+ QPaintEngine* paintEngine() const;
+ int metric(PaintDeviceMetric metric) const;
+
+ QString model() const;
+ QStringList buttons() const;
+ bool isConnected() const;
+ bool busy() const;
+
+ void setDateTime(const QDateTime& dateTime);
+ void queryDateTime();
+ QDateTime dateTime() const;
+
+ void queryBatteryLevel();
+ int batteryLevel() const;
+
+ void queryCharging();
+ bool charging() const;
+
+ void displayIdleScreen();
+ void displayNotification(Notification *notification);
+ void displayApplication();
+
+ void vibrate(int msecs);
+
+protected:
+ void setupBluetoothWatch();
+ void desetupBluetoothWatch();
+
+private:
+ ConfigKey *_settings;
+};
+
+}
+
+#endif // LIVEVIEW_H
diff --git a/liveview/liveview.pro b/liveview/liveview.pro
new file mode 100644
index 0000000..9b949d7
--- /dev/null
+++ b/liveview/liveview.pro
@@ -0,0 +1,39 @@
+TARGET = liveviewdriver
+TEMPLATE = lib
+CONFIG += plugin
+QT += gui
+
+# Qt Mobility 1.2
+maemo5 {
+ CONFIG += mobility12
+} else {
+ CONFIG += mobility
+}
+MOBILITY += connectivity systeminfo
+
+SOURCES += liveviewplugin.cpp \
+ liveviewscanner.cpp \
+ liveview.cpp
+HEADERS += liveviewplugin.h \
+ liveviewscanner.h \
+ liveview.h
+
+LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
+INCLUDEPATH += $$PWD/../libsowatch
+DEPENDPATH += $$PWD/../libsowatch
+
+LIBS += -L$$OUT_PWD/../libsowatchbt/ -lsowatchbt
+INCLUDEPATH += $$PWD/../libsowatchbt
+DEPENDPATH += $$PWD/../libsowatchbt
+
+!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
+ QMAKE_RPATHDIR += /opt/sowatch/lib
+ target.path = /opt/sowatch/lib/drivers
+ res_files.path = /opt/sowatch/share/metawatch
+ qml_files.path = /opt/sowatch/qml
+} else {
+ target.path = /usr/lib/sowatch/drivers
+ res_files.path = /usr/share/sowatch/metawatch
+ qml_files.path = /usr/share/sowatch/qml
+}
+INSTALLS += target
diff --git a/liveview/liveviewplugin.cpp b/liveview/liveviewplugin.cpp
new file mode 100644
index 0000000..6ad6f7f
--- /dev/null
+++ b/liveview/liveviewplugin.cpp
@@ -0,0 +1,45 @@
+#include <QtConnectivity/QBluetoothAddress>
+
+#include "liveview.h"
+#include "liveviewscanner.h"
+#include "liveviewplugin.h"
+
+using namespace sowatch;
+QTM_USE_NAMESPACE
+
+LiveViewPlugin::LiveViewPlugin()
+{
+}
+
+LiveViewPlugin::~LiveViewPlugin()
+{
+
+}
+
+QStringList LiveViewPlugin::drivers()
+{
+ QStringList d;
+ d << "livewview";
+ return d;
+}
+
+WatchScanner* LiveViewPlugin::getScanner(QObject *parent)
+{
+ return new LiveViewScanner(parent);
+}
+
+QUrl LiveViewPlugin::getConfigQmlUrl(const QString &driver)
+{
+ return QUrl();
+}
+
+Watch* LiveViewPlugin::getWatch(const QString& driver, ConfigKey* settings, QObject *parent)
+{
+ if (driver == "liveview") {
+ return new LiveView(settings, parent);
+ } else {
+ return 0;
+ }
+}
+
+Q_EXPORT_PLUGIN2(liveview, LiveViewPlugin)
diff --git a/liveview/liveviewplugin.h b/liveview/liveviewplugin.h
new file mode 100644
index 0000000..eb55249
--- /dev/null
+++ b/liveview/liveviewplugin.h
@@ -0,0 +1,25 @@
+#ifndef LIVEVIEWPLUGIN_H
+#define LIVEVIEWPLUGIN_H
+
+#include <sowatch.h>
+
+namespace sowatch
+{
+
+class LiveViewPlugin : public QObject, public WatchPluginInterface {
+ Q_OBJECT
+ Q_INTERFACES(sowatch::WatchPluginInterface)
+
+public:
+ LiveViewPlugin();
+ ~LiveViewPlugin();
+
+ QStringList drivers();
+ WatchScanner* getScanner(QObject *parent);
+ QUrl getConfigQmlUrl(const QString &driver);
+ Watch* getWatch(const QString& driver, ConfigKey *settings, QObject *parent);
+};
+
+}
+
+#endif // LIVEVIEWPLUGIN_H
diff --git a/liveview/liveviewscanner.cpp b/liveview/liveviewscanner.cpp
new file mode 100644
index 0000000..3aee19d
--- /dev/null
+++ b/liveview/liveviewscanner.cpp
@@ -0,0 +1,26 @@
+#include <QtConnectivity/QBluetoothDeviceInfo>
+#include <QtConnectivity/QBluetoothAddress>
+
+#include "liveviewscanner.h"
+
+QTM_USE_NAMESPACE
+using namespace sowatch;
+
+LiveViewScanner::LiveViewScanner(QObject *parent) :
+ BluetoothWatchScanner(parent)
+{
+ setUuidFilter(QBluetoothUuid::SerialPort);
+}
+
+void LiveViewScanner::handleDiscoveredService(const QBluetoothServiceInfo &info)
+{
+ const QBluetoothDeviceInfo dev = info.device();
+ QString deviceName = dev.name();
+ if (deviceName == "LiveView") {
+ QVariantMap foundInfo;
+ foundInfo["driver"] = QString("liveview");
+ foundInfo["address"] = dev.address().toString();
+ foundInfo["name"] = deviceName;
+ emit watchFound(foundInfo);
+ }
+}
diff --git a/liveview/liveviewscanner.h b/liveview/liveviewscanner.h
new file mode 100644
index 0000000..ecd182c
--- /dev/null
+++ b/liveview/liveviewscanner.h
@@ -0,0 +1,21 @@
+#ifndef LIVEVIEWSCANNER_H
+#define LIVEVIEWSCANNER_H
+
+#include <sowatch.h>
+#include <sowatchbt.h>
+
+namespace sowatch
+{
+
+class LiveViewScanner : public BluetoothWatchScanner
+{
+ Q_OBJECT
+public:
+ explicit LiveViewScanner(QObject *parent = 0);
+
+ void handleDiscoveredService(const QBluetoothServiceInfo &info);
+};
+
+}
+
+#endif // LIVEVIEWSCANNER_H
diff --git a/metawatch/metawatch.cpp b/metawatch/metawatch.cpp
index 782e47f..7487c13 100644
--- a/metawatch/metawatch.cpp
+++ b/metawatch/metawatch.cpp
@@ -13,10 +13,6 @@ const char MetaWatch::btnToWatch[8] = {
0, 1, 2, 3, 5, 6, -1, -1
};
-const int MetaWatch::connectRetryTimes[] = {
- 5, 10, 30, 60, 120, 300
-};
-
const quint8 MetaWatch::bitRevTable[16] = {
0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
};
@@ -79,23 +75,17 @@ const quint16 MetaWatch::crcTable[256] = {
#endif
MetaWatch::MetaWatch(ConfigKey* settings, QObject* parent) :
- Watch(parent),
+ BluetoothWatch(QBluetoothAddress(settings->value("address").toString()), parent),
_settings(settings->getSubkey(QString(), this)),
_idleTimer(new QTimer(this)), _ringTimer(new QTimer(this)),
_watchTime(), _watchBattery(0), _watchCharging(false),
_currentMode(IdleMode), _paintMode(IdleMode),
_paintEngine(0),
- _connectRetries(0), _connected(false),
- _connectTimer(new QTimer(this)),
- _connectAlignedTimer(new QSystemAlignedTimer(this)),
- _localDev(new QBluetoothLocalDevice(this)),
- _socket(0),
_sendTimer(new QTimer(this))
{
// Read current device settings
connect(_settings, SIGNAL(subkeyChanged(QString)), SLOT(settingChanged(QString)));
- _address = QBluetoothAddress(settings->value("address").toString());
_notificationTimeout = settings->value("notification-timeout", 15).toInt();
_24hMode = settings->value("24h-mode", false).toBool();
_dayMonthOrder = settings->value("day-month-order", false).toBool();
@@ -113,34 +103,12 @@ MetaWatch::MetaWatch(ConfigKey* settings, QObject* parent) :
_ringTimer->setInterval(DelayBetweenRings);
connect(_ringTimer, SIGNAL(timeout()), SLOT(timedRing()));
- _connectTimer->setSingleShot(true);
- _connectAlignedTimer->setSingleShot(true);
- connect(_connectTimer, SIGNAL(timeout()), SLOT(timedReconnect()));
- connect(_connectAlignedTimer, SIGNAL(timeout()), SLOT(timedReconnect()));
-
_sendTimer->setInterval(DelayBetweenMessages);
connect(_sendTimer, SIGNAL(timeout()), SLOT(timedSend()));
-
- // Connect other signals
- connect(_localDev, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), SLOT(localDevModeChanged(QBluetoothLocalDevice::HostMode)));
-
- // Check to see if we can connect right away
- if (_localDev->isValid() &&
- _localDev->hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
- // Do an initial connection attempt after a short delay
- // (To give time for other plugins to initialize, etc.)
- scheduleConnect();
- } else {
- qDebug() << "Not starting MetaWatch connection because BT is off";
- }
}
MetaWatch::~MetaWatch()
{
- if (_socket) {
- _socket->close();
- delete _socket;
- }
if (_paintEngine) {
delete _paintEngine;
}
@@ -165,11 +133,6 @@ QStringList MetaWatch::buttons() const
return _buttonNames;
}
-bool MetaWatch::isConnected() const
-{
- return _connected;
-}
-
bool MetaWatch::busy() const
{
return !_connected ||
@@ -299,6 +262,26 @@ void MetaWatch::ungrabButton(Mode mode, Button button)
disableButton(mode, button, PressAndRelease);
}
+void MetaWatch::setupBluetoothWatch()
+{
+ _partialReceived.type = NoMessage;
+ _partialReceived.data.clear();
+ _currentMode = IdleMode;
+ _paintMode = IdleMode;
+
+ // Configure the watch according to user preferences
+ updateWatchProperties();
+
+ // Sync watch date & time
+ setDateTime(QDateTime::currentDateTime());
+}
+
+void MetaWatch::desetupBluetoothWatch()
+{
+ _toSend.clear();
+ _sendTimer->stop();
+}
+
quint16 MetaWatch::calcCrc(const QByteArray &data, int size)
{
quint16 remainder = 0xFFFF;
@@ -327,66 +310,6 @@ quint16 MetaWatch::calcCrc(const Message& msg)
return calcCrc(data, msgSize + 4);
}
-void MetaWatch::scheduleConnect()
-{
- if (_connected ||
- _connectAlignedTimer->isActive() || _connectTimer->isActive()) {
- // Already connected or already scheduled to connect.
- return;
- }
-
- _connectRetries = 0;
- _connectTimer->start(100);
-}
-
-void MetaWatch::scheduleRetryConnect()
-{
- if (_connected ||
- _connectAlignedTimer->isActive() || _connectTimer->isActive()) {
- // Already connected or already scheduled to connect.
- return;
- }
-
- int timeToNextRetry;
- if (_connectRetries >= connectRetryTimesSize) {
- timeToNextRetry = connectRetryTimes[connectRetryTimesSize - 1];
- } else {
- timeToNextRetry = connectRetryTimes[_connectRetries];
- _connectRetries++; // Increase the number of connection attemps
- }
-
- qDebug() << "Backing off for" << timeToNextRetry << "seconds for next retry";
- _connectAlignedTimer->start(timeToNextRetry / 2, timeToNextRetry * 2);
- if (_connectAlignedTimer->lastError() != QSystemAlignedTimer::NoError) {
- // Hopefully a future version of QSystemAlignedTimer implements this fallback
- // For now, we have to do it ourselves.
- qDebug() << "Note: using plain QTimer for retry";
- _connectTimer->start(timeToNextRetry * 1000);
- }
-}
-
-void MetaWatch::unscheduleConnect()
-{
- _connectAlignedTimer->stop();
- _connectTimer->stop();
-}
-
-void MetaWatch::connectToWatch()
-{
- delete _socket; //Delete socket from previous connect if any.
- _socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket);
-
- connect(_socket, SIGNAL(connected()), SLOT(socketConnected()));
- connect(_socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
- connect(_socket, SIGNAL(readyRead()), SLOT(socketData()));
- connect(_socket, SIGNAL(error(QBluetoothSocket::SocketError)),
- SLOT(socketError(QBluetoothSocket::SocketError)));
- connect(_socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)),
- SLOT(socketState(QBluetoothSocket::SocketState)));
-
- _socket->connectToService(_address, 1, QIODevice::ReadWrite | QIODevice::Unbuffered);
-}
-
void MetaWatch::send(const Message &msg)
{
_toSend.enqueue(msg);
@@ -706,89 +629,11 @@ void MetaWatch::settingChanged(const QString &key)
}
}
-void MetaWatch::localDevModeChanged(QBluetoothLocalDevice::HostMode state)
-{
- qDebug() << "Local bluetooth device mode changed to" << state;
- if (state == QBluetoothLocalDevice::HostPoweredOff) {
- // Host bluetooth was powered down
- // Assume the socket has been disconnected
- socketDisconnected();
- // Cancel any pending connection attempts
- unscheduleConnect();
- } else {
- // Host bluetooth might have been powered up
- if (!_connected) {
- scheduleConnect();
- }
- }
-}
-
-void MetaWatch::socketConnected()
-{
- if (!_connected) {
- qDebug() << "connected";
-
- _connected = true;
- _connectRetries = 0;
- _partialReceived.type = NoMessage;
- _partialReceived.data.clear();
- _currentMode = IdleMode;
- _paintMode = IdleMode;
-
- // Configure the watch according to user preferences
- updateWatchProperties();
-
- // Sync watch date & time
- setDateTime(QDateTime::currentDateTime());
-
- // Call the MetaWatch Model-specific setup routines
- handleWatchConnected();
-
- emit connected();
- }
-}
-
-void MetaWatch::socketDisconnected()
-{
- // Signal disconnection if necessary
- if (_connected) {
- qDebug() << "disconnected";
-
- _connected = false;
- _toSend.clear();
- _sendTimer->stop();
-
- emit disconnected();
- }
-
- // Setup reconnection attempt if necessary
- if (_localDev->hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
- scheduleRetryConnect();
- }
-}
-
-void MetaWatch::socketData()
+void MetaWatch::dataReceived()
{
realReceive(false);
}
-void MetaWatch::socketError(QBluetoothSocket::SocketError error)
-{
- qWarning() << "Socket error:" << error;
- // Seems that sometimes a disconnection event may not be generated.
- socketDisconnected();
-}
-
-void MetaWatch::socketState(QBluetoothSocket::SocketState state)
-{
- qDebug() << "socket is in" << state;
-}
-
-void MetaWatch::timedReconnect()
-{
- connectToWatch();
-}
-
void MetaWatch::timedSend()
{
// If there are packets to be sent...
diff --git a/metawatch/metawatch.h b/metawatch/metawatch.h
index a9cf58b..d671635 100644
--- a/metawatch/metawatch.h
+++ b/metawatch/metawatch.h
@@ -3,12 +3,12 @@
#include <QtCore/QQueue>
#include <QtCore/QTimer>
-#include <QtCore/QSettings>
#include <QtConnectivity/QBluetoothAddress>
#include <QtConnectivity/QBluetoothSocket>
#include <QtConnectivity/QBluetoothLocalDevice>
#include <QtSystemInfo/QSystemAlignedTimer>
#include <sowatch.h>
+#include <sowatchbt.h>
namespace sowatch
{
@@ -20,7 +20,7 @@ using QTM_PREPEND_NAMESPACE(QBluetoothLocalDevice);
class MetaWatchPaintEngine;
-class MetaWatch : public Watch
+class MetaWatch : public BluetoothWatch
{
Q_OBJECT
@@ -99,7 +99,7 @@ public:
QString model() const;
QStringList buttons() const;
- bool isConnected() const;
+
bool busy() const;
void setDateTime(const QDateTime& dateTime);
@@ -177,40 +177,22 @@ protected:
/** The framebuffers for each of the watch modes */
QImage _image[3];
- // Timers to retry the connection when the watch is not found.
- static const int connectRetryTimesSize = 6;
- static const int connectRetryTimes[connectRetryTimesSize];
- short _connectRetries;
- bool _connected;
- QTimer* _connectTimer;
- QSystemAlignedTimer* _connectAlignedTimer;
-
- // Connection stuff
- QBluetoothLocalDevice* _localDev;
- QBluetoothAddress _address;
- QBluetoothSocket* _socket;
-
/** The "packets to be sent" asynchronous queue **/
QQueue<Message> _toSend;
QTimer* _sendTimer;
Message _partialReceived;
- /** Used to calculate CRC */
+ // Watch connect/disconnect handling
+ void setupBluetoothWatch();
+ void desetupBluetoothWatch();
+
+ // Message passing
+ /** Used to calculate CRC fields in message header */
static const quint8 bitRevTable[16];
static const quint16 crcTable[256];
static quint16 calcCrc(const QByteArray& data, int size);
static quint16 calcCrc(const Message& msg);
- /** Start the initial connection attempt, reset failed connection timers. */
- void scheduleConnect();
- /** Schedule an new connection attempt, consider the current one failed. */
- void scheduleRetryConnect();
- /** Cancel any pending connection attempts. */
- void unscheduleConnect();
-
- /** Attempt a connection to the watch right now. */
- virtual void connectToWatch();
-
/** Sends a message to the watch. Does not block. */
virtual void send(const Message& msg);
/** Sends a message to the watch if a message of the same type is not
@@ -239,18 +221,9 @@ protected:
void handleButtonEventMessage(const Message& msg);
void handleBatteryVoltageMessage(const Message& msg);
- /** To be overriden; should configure a newly connected watch. */
- virtual void handleWatchConnected() = 0;
-
private slots:
void settingChanged(const QString& key);
- void localDevModeChanged(QBluetoothLocalDevice::HostMode state);
- void socketConnected();
- void socketDisconnected();
- void socketData();
- void socketError(QBluetoothSocket::SocketError error);
- void socketState(QBluetoothSocket::SocketState error);
- void timedReconnect();
+ void dataReceived();
void timedSend();
void timedRing();
diff --git a/metawatch/metawatch.pro b/metawatch/metawatch.pro
index 536ccee..2c7af94 100644
--- a/metawatch/metawatch.pro
+++ b/metawatch/metawatch.pro
@@ -36,10 +36,13 @@ res_files.files += res/graphics res/fonts
qml_files.files += qml/com qml/metawatch-digital-config.qml
LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
-
INCLUDEPATH += $$PWD/../libsowatch
DEPENDPATH += $$PWD/../libsowatch
+LIBS += -L$$OUT_PWD/../libsowatchbt/ -lsowatchbt
+INCLUDEPATH += $$PWD/../libsowatchbt
+DEPENDPATH += $$PWD/../libsowatchbt
+
!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
QMAKE_RPATHDIR += /opt/sowatch/lib
target.path = /opt/sowatch/lib/drivers
diff --git a/metawatch/metawatchdigital.cpp b/metawatch/metawatchdigital.cpp
index e099f76..e3f8431 100644
--- a/metawatch/metawatchdigital.cpp
+++ b/metawatch/metawatchdigital.cpp
@@ -235,8 +235,10 @@ QImage MetaWatchDigital::iconForNotification(const Notification *n)
}
}
-void MetaWatchDigital::handleWatchConnected()
+void MetaWatchDigital::setupBluetoothWatch()
{
+ MetaWatch::setupBluetoothWatch(); // Call generic setup
+
// Grab all of the buttons that are of interest to us
// We do not grab the F button, as it triggers the LED.
grabButton(IdleMode, BtnA); // Required for app-switch
diff --git a/metawatch/metawatchdigital.h b/metawatch/metawatchdigital.h
index dde017a..1e1a62b 100644
--- a/metawatch/metawatchdigital.h
+++ b/metawatch/metawatchdigital.h
@@ -28,7 +28,7 @@ public:
void update(Mode mode, const QList<QRect>& rects = QList<QRect>());
protected:
- void handleWatchConnected();
+ void setupBluetoothWatch();
private:
// Idle screen: notifications unread count
diff --git a/metawatch/metawatchdigitalsimulator.cpp b/metawatch/metawatchdigitalsimulator.cpp
index c20e8c5..f808515 100644
--- a/metawatch/metawatchdigitalsimulator.cpp
+++ b/metawatch/metawatchdigitalsimulator.cpp
@@ -116,6 +116,8 @@ void MetaWatchDigitalSimulator::vibrate(bool on)
void MetaWatchDigitalSimulator::connectToWatch()
{
+ // Skip BluetoothWatch connection stuff
+
if (!_connected && _form) {
qDebug() << "simulator connected";
@@ -123,7 +125,7 @@ void MetaWatchDigitalSimulator::connectToWatch()
_currentMode = IdleMode;
_paintMode = IdleMode;
- handleWatchConnected();
+ MetaWatchDigital::setupBluetoothWatch();
emit connected();
}
diff --git a/metawatch/metawatchscanner.cpp b/metawatch/metawatchscanner.cpp
index e560195..3742092 100644
--- a/metawatch/metawatchscanner.cpp
+++ b/metawatch/metawatchscanner.cpp
@@ -7,23 +7,9 @@ QTM_USE_NAMESPACE
using namespace sowatch;
MetaWatchScanner::MetaWatchScanner(QObject *parent) :
- WatchScanner(parent),
- _agent(new QBluetoothServiceDiscoveryAgent(this))
+ BluetoothWatchScanner(parent)
{
- _agent->setUuidFilter(QBluetoothUuid::SerialPort);
- connect(_agent, SIGNAL(finished()), this, SIGNAL(finished()));
- connect(_agent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
- this, SLOT(handleDiscoveredService(QBluetoothServiceInfo)));
-}
-
-void MetaWatchScanner::start()
-{
- if (_agent->isActive()) {
- _agent->stop();
- }
- _agent->start();
- qDebug() << "started metawatch bluetooth scan";
- emit started();
+ setUuidFilter(QBluetoothUuid::SerialPort);
}
void MetaWatchScanner::handleDiscoveredService(const QBluetoothServiceInfo &info)
diff --git a/metawatch/metawatchscanner.h b/metawatch/metawatchscanner.h
index a41633a..6cafe3e 100644
--- a/metawatch/metawatchscanner.h
+++ b/metawatch/metawatchscanner.h
@@ -2,25 +2,17 @@
#define METAWATCHSCANNER_H
#include <sowatch.h>
-#include <QtConnectivity/QBluetoothServiceDiscoveryAgent>
+#include <sowatchbt.h>
namespace sowatch
{
-using QTM_PREPEND_NAMESPACE(QBluetoothServiceDiscoveryAgent);
-using QTM_PREPEND_NAMESPACE(QBluetoothServiceInfo);
-
-class MetaWatchScanner : public WatchScanner
+class MetaWatchScanner : public BluetoothWatchScanner
{
Q_OBJECT
public:
explicit MetaWatchScanner(QObject *parent = 0);
- void start();
-
-private:
- QBluetoothServiceDiscoveryAgent *_agent;
-
private slots:
void handleDiscoveredService(const QBluetoothServiceInfo& info);
};
diff --git a/metawatchwatchlets/bubble.png b/metawatchwatchlets/bubble.png
new file mode 100644
index 0000000..59718f8
--- /dev/null
+++ b/metawatchwatchlets/bubble.png
Binary files differ
diff --git a/metawatchwatchlets/bubble_tip.png b/metawatchwatchlets/bubble_tip.png
new file mode 100644
index 0000000..947f018
--- /dev/null
+++ b/metawatchwatchlets/bubble_tip.png
Binary files differ
diff --git a/metawatchwatchlets/idle_border.png b/metawatchwatchlets/idle_border.png
new file mode 100644
index 0000000..7879647
--- /dev/null
+++ b/metawatchwatchlets/idle_border.png
Binary files differ
diff --git a/metawatchwatchlets/idle_call.png b/metawatchwatchlets/idle_call.png
new file mode 100644
index 0000000..872f681
--- /dev/null
+++ b/metawatchwatchlets/idle_call.png
Binary files differ
diff --git a/metawatchwatchlets/idle_mail.png b/metawatchwatchlets/idle_mail.png
new file mode 100644
index 0000000..6afaaaa
--- /dev/null
+++ b/metawatchwatchlets/idle_mail.png
Binary files differ
diff --git a/metawatchwatchlets/idle_msg.png b/metawatchwatchlets/idle_msg.png
new file mode 100644
index 0000000..b3bbd6b
--- /dev/null
+++ b/metawatchwatchlets/idle_msg.png
Binary files differ
diff --git a/sowatch.pro b/sowatch.pro
index 1233f46..47f39ad 100644
--- a/sowatch.pro
+++ b/sowatch.pro
@@ -4,14 +4,20 @@ TEMPLATE = subdirs
# Core library
# This is mandatory. Depends on Qt and GConf.
-SUBDIRS = libsowatch \
- metawatchwatchlets
+SUBDIRS = libsowatch
+
+SUBDIRS += libsowatchbt
+libsowatchbt.depends = libsowatch
# The MetaWatch driver plugin
-# Since this is the only watch plugin, it is mandatory.
# Depends on Qt Mobility SystemInfo and Bluetooth.
-SUBDIRS += metawatch
-metawatch.depends = libsowatch
+SUBDIRS += metawatch metawatchwatchlets
+metawatch.depends = libsowatch libsowatchbt
+metawatchwatchlets.depends = metawatch
+
+# LiveView driver plugin
+SUBDIRS += liveview
+liveview.depends = libsowatch libsowatchbt
# Some watchlets
# This just shows a list of pending notifications and has no dependencies.
diff --git a/sowatchd/sowatchd.pro b/sowatchd/sowatchd.pro
index 17176fb..3ffa490 100644
--- a/sowatchd/sowatchd.pro
+++ b/sowatchd/sowatchd.pro
@@ -11,6 +11,9 @@ HEADERS += daemon.h daemonadaptor.h watchhandler.h
LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
INCLUDEPATH += $$PWD/../libsowatch
DEPENDPATH += $$PWD/../libsowatch
+LIBS += -L$$OUT_PWD/../libsowatchbt/ -lsowatchbt
+INCLUDEPATH += $$PWD/../libsowatchbt
+DEPENDPATH += $$PWD/../libsowatchbt
# Library & target paths
!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
diff --git a/sowatchd/watchhandler.cpp b/sowatchd/watchhandler.cpp
index a2ea76a..cdd520d 100644
--- a/sowatchd/watchhandler.cpp
+++ b/sowatchd/watchhandler.cpp
@@ -4,7 +4,9 @@ using namespace sowatch;
WatchHandler::WatchHandler(ConfigKey *config, QObject *parent)
: QObject(parent),
- _config(config->getSubkey("", this))
+ _config(config->getSubkey("", this)),
+ _watch(0),
+ _server(0)
{
Registry *registry = Registry::registry();