From ccd19d2b7ee4184503ea46b98333b27a5613190e Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Wed, 8 May 2013 18:04:31 +0200 Subject: big change: a new abstract BluetoothWatch class --- libsowatchbt/bluetoothwatch.cpp | 176 ++++++++++++++++++++++++++++ libsowatchbt/bluetoothwatch.h | 74 ++++++++++++ libsowatchbt/bluetoothwatchscanner.cpp | 31 +++++ libsowatchbt/bluetoothwatchscanner.h | 37 ++++++ libsowatchbt/libsowatchbt.pro | 38 ++++++ libsowatchbt/sowatchbt.h | 9 ++ libsowatchbt/sowatchbt_global.h | 12 ++ liveview/liveview.cpp | 93 +++++++++++++++ liveview/liveview.h | 52 +++++++++ liveview/liveview.pro | 39 +++++++ liveview/liveviewplugin.cpp | 45 ++++++++ liveview/liveviewplugin.h | 25 ++++ liveview/liveviewscanner.cpp | 26 +++++ liveview/liveviewscanner.h | 21 ++++ metawatch/metawatch.cpp | 199 ++++---------------------------- metawatch/metawatch.h | 47 ++------ metawatch/metawatch.pro | 5 +- metawatch/metawatchdigital.cpp | 4 +- metawatch/metawatchdigital.h | 2 +- metawatch/metawatchdigitalsimulator.cpp | 4 +- metawatch/metawatchscanner.cpp | 18 +-- metawatch/metawatchscanner.h | 12 +- metawatchwatchlets/bubble.png | Bin 0 -> 263 bytes metawatchwatchlets/bubble_tip.png | Bin 0 -> 187 bytes metawatchwatchlets/idle_border.png | Bin 0 -> 198 bytes metawatchwatchlets/idle_call.png | Bin 0 -> 197 bytes metawatchwatchlets/idle_mail.png | Bin 0 -> 196 bytes metawatchwatchlets/idle_msg.png | Bin 0 -> 191 bytes sowatch.pro | 16 ++- sowatchd/sowatchd.pro | 3 + sowatchd/watchhandler.cpp | 4 +- 31 files changed, 742 insertions(+), 250 deletions(-) create mode 100644 libsowatchbt/bluetoothwatch.cpp create mode 100644 libsowatchbt/bluetoothwatch.h create mode 100644 libsowatchbt/bluetoothwatchscanner.cpp create mode 100644 libsowatchbt/bluetoothwatchscanner.h create mode 100644 libsowatchbt/libsowatchbt.pro create mode 100644 libsowatchbt/sowatchbt.h create mode 100644 libsowatchbt/sowatchbt_global.h create mode 100644 liveview/liveview.cpp create mode 100644 liveview/liveview.h create mode 100644 liveview/liveview.pro create mode 100644 liveview/liveviewplugin.cpp create mode 100644 liveview/liveviewplugin.h create mode 100644 liveview/liveviewscanner.cpp create mode 100644 liveview/liveviewscanner.h create mode 100644 metawatchwatchlets/bubble.png create mode 100644 metawatchwatchlets/bubble_tip.png create mode 100644 metawatchwatchlets/idle_border.png create mode 100644 metawatchwatchlets/idle_call.png create mode 100644 metawatchwatchlets/idle_mail.png create mode 100644 metawatchwatchlets/idle_msg.png 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 +#include +#include +#include +#include +#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 +#include + +#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 +#include + +#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 + +#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 +#include + +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 + +#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 + +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 +#include + +#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 +#include + +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 #include -#include #include #include #include #include #include +#include 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 _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& rects = QList()); 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 -#include +#include 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 Binary files /dev/null and b/metawatchwatchlets/bubble.png differ diff --git a/metawatchwatchlets/bubble_tip.png b/metawatchwatchlets/bubble_tip.png new file mode 100644 index 0000000..947f018 Binary files /dev/null and b/metawatchwatchlets/bubble_tip.png differ diff --git a/metawatchwatchlets/idle_border.png b/metawatchwatchlets/idle_border.png new file mode 100644 index 0000000..7879647 Binary files /dev/null and b/metawatchwatchlets/idle_border.png differ diff --git a/metawatchwatchlets/idle_call.png b/metawatchwatchlets/idle_call.png new file mode 100644 index 0000000..872f681 Binary files /dev/null and b/metawatchwatchlets/idle_call.png differ diff --git a/metawatchwatchlets/idle_mail.png b/metawatchwatchlets/idle_mail.png new file mode 100644 index 0000000..6afaaaa Binary files /dev/null and b/metawatchwatchlets/idle_mail.png differ diff --git a/metawatchwatchlets/idle_msg.png b/metawatchwatchlets/idle_msg.png new file mode 100644 index 0000000..b3bbd6b Binary files /dev/null and b/metawatchwatchlets/idle_msg.png 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(); -- cgit v1.2.3