summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsowatch/watch.h27
-rw-r--r--metawatch/metawatch.cpp130
-rw-r--r--metawatch/metawatch.h27
3 files changed, 163 insertions, 21 deletions
diff --git a/libsowatch/watch.h b/libsowatch/watch.h
index f18ed9a..9147f9a 100644
--- a/libsowatch/watch.h
+++ b/libsowatch/watch.h
@@ -17,7 +17,9 @@ class SOWATCH_EXPORT Watch : public QObject, public QPaintDevice
Q_OBJECT
Q_PROPERTY(QString model READ model CONSTANT)
Q_PROPERTY(bool connected READ isConnected)
- Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime)
+ Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
+ Q_PROPERTY(int batteryLevel READ batteryLevel NOTIFY batteryLevelChanged)
+ Q_PROPERTY(bool charging READ charging NOTIFY chargingChanged)
public:
explicit Watch(QObject* parent = 0);
@@ -34,10 +36,23 @@ public:
/** Indicates if watch is too busy atm and we should limit frame rate. */
virtual bool busy() const = 0;
- /** Gets the current date/time on the watch. */
- virtual QDateTime dateTime() = 0;
/** Sets the current date/time on the watch. */
virtual void setDateTime(const QDateTime& dateTime) = 0;
+ /** Asynchronously queries battery date/time from the watch; once the
+ * query is finished, dateTimeChanged() will be signaled and dateTime()
+ * will return the updated value. */
+ virtual void queryDateTime() = 0;
+ /** Gets the current date/time as last fetched from the watch. */
+ virtual QDateTime dateTime() const = 0;
+
+ /** Asynchronously queries battery level from the watch. */
+ virtual void queryBatteryLevel() = 0;
+ /** Gets the battery level (range [0-100]) as last read from the watch. */
+ virtual int batteryLevel() const = 0;
+
+ /** Asynchronously queries whether the watch is connected to a charger. */
+ virtual void queryCharging() = 0;
+ virtual bool charging() const = 0;
/** Grabs a button from whatever is default function is for the current mode. */
virtual void grabButton(int button) = 0;
@@ -65,6 +80,12 @@ signals:
void disconnected();
/** The watch has returned to the idle screen by either inactivity or notification cleared/timeout. */
void idling();
+ /** Emitted once the queryDateTime() operation is completed. */
+ void dateTimeChanged();
+ /** Emitted once the queryBatteryLevel() operation is completed. */
+ void batteryLevelChanged();
+ /** Emitted once the queryCharging() operation is completed. */
+ void chargingChanged();
/** A button has been pressed. */
void buttonPressed(int button);
/** A button has been pressed and then released. */
diff --git a/metawatch/metawatch.cpp b/metawatch/metawatch.cpp
index 8c246aa..9ca4b2d 100644
--- a/metawatch/metawatch.cpp
+++ b/metawatch/metawatch.cpp
@@ -81,6 +81,7 @@ const quint16 MetaWatch::crcTable[256] = {
MetaWatch::MetaWatch(const QBluetoothAddress& address, QSettings* settings, QObject* parent) :
Watch(parent),
_idleTimer(new QTimer(this)), _ringTimer(new QTimer(this)),
+ _watchTime(), _watchBattery(0), _watchBatteryAverage(0), _watchCharging(false),
_currentMode(IdleMode), _paintMode(IdleMode),
_paintEngine(0),
_connectRetries(0), _connected(false),
@@ -151,11 +152,6 @@ bool MetaWatch::busy() const
_toSend.size() > 20;
}
-QDateTime MetaWatch::dateTime()
-{
- return QDateTime::currentDateTime(); // TODO
-}
-
void MetaWatch::setDateTime(const QDateTime &dateTime)
{
Message msg(SetRealTimeClock, QByteArray(8, 0));
@@ -175,6 +171,44 @@ void MetaWatch::setDateTime(const QDateTime &dateTime)
send(msg);
}
+void MetaWatch::queryDateTime()
+{
+ Message msg(GetRealTimeClock);
+ sendIfNotQueued(msg);
+}
+
+QDateTime MetaWatch::dateTime() const
+{
+ return _watchTime;
+}
+
+void MetaWatch::queryBatteryLevel()
+{
+ Message msg(ReadBatteryVoltage);
+ sendIfNotQueued(msg);
+}
+
+int MetaWatch::batteryLevel() const
+{
+ // TODO This "estimation" is quite awful, could be way more accurate.
+ int level = (_watchBatteryAverage - 3500) / (4100-3500);
+ if (level < 0) level = 0;
+ if (level > 100) level = 100;
+
+ return level;
+}
+
+void MetaWatch::queryCharging()
+{
+ Message msg(ReadBatteryVoltage);
+ sendIfNotQueued(msg);
+}
+
+bool MetaWatch::charging() const
+{
+ return _watchCharging;
+}
+
void MetaWatch::grabButton(int button)
{
grabButton(_currentMode, (Button) button);
@@ -292,19 +326,16 @@ void MetaWatch::send(const Message &msg)
}
}
-void MetaWatch::handleMessage(const Message &msg)
+void MetaWatch::sendIfNotQueued(const Message& msg)
{
- switch (msg.type) {
- case StatusChangeEvent:
- handleStatusChangeMessage(msg);
- break;
- case ButtonEvent:
- handleButtonEventMessage(msg);
- break;
- default:
- qWarning() << "Unknown message of type" << msg.type << "received";
- break;
+ foreach (const Message& m, _toSend) {
+ if (m.type == msg.type) {
+ return; // Already on the queue, discard message.
+ }
}
+
+ // Otherwise, send it as requested
+ send(msg);
}
void MetaWatch::setVibrateMode(bool enable, uint on, uint off, uint cycles)
@@ -428,6 +459,54 @@ void MetaWatch::disableButton(Mode mode, Button button, ButtonPress press)
send(msg);
}
+void MetaWatch::handleMessage(const Message &msg)
+{
+ switch (msg.type) {
+ case GetDeviceTypeResponse:
+ handleDeviceTypeMessage(msg);
+ break;
+ case GetRealTimeClockResponse:
+ handleRealTimeClockMessage(msg);
+ break;
+ case StatusChangeEvent:
+ handleStatusChangeMessage(msg);
+ break;
+ case ButtonEvent:
+ handleButtonEventMessage(msg);
+ break;
+ case ReadBatteryVoltageResponse:
+ handleBatteryVoltageMessage(msg);
+ break;
+ default:
+ qWarning() << "Unknown message of type" << msg.type << "received";
+ break;
+ }
+}
+
+void MetaWatch::handleDeviceTypeMessage(const Message &msg)
+{
+ Q_ASSERT(msg.type == GetDeviceTypeResponse);
+ if (msg.data.size() < 1) {
+ qWarning() << "Short device type response";
+ }
+ qDebug() << "got device type" << msg.data[0];
+}
+
+void MetaWatch::handleRealTimeClockMessage(const Message &msg)
+{
+ int year = ((msg.data[1] & 0xFF) << 8) | (msg.data[0] & 0xFF);
+ int month = msg.data[2] & 0xFF;
+ int day = msg.data[3] & 0xFF;
+ QDate d(year, month, day);
+ int hour = msg.data[5] & 0xFF;
+ int minute = msg.data[6] & 0xFF;
+ int second = msg.data[7] & 0xFF;
+ QTime t(hour, minute, second);
+ _watchTime = QDateTime(d, t);
+
+ emit dateTimeChanged();
+}
+
void MetaWatch::handleStatusChangeMessage(const Message &msg)
{
Q_UNUSED(msg);
@@ -458,6 +537,25 @@ void MetaWatch::handleButtonEventMessage(const Message &msg)
}
}
+void MetaWatch::handleBatteryVoltageMessage(const Message &msg)
+{
+ Q_ASSERT(msg.type == ReadBatteryVoltageResponse);
+ if (msg.data.size() < 6) {
+ qWarning() << "Short battery voltage response:" << msg.data.size();
+ return;
+ }
+ _watchCharging = msg.data[1];
+ _watchBattery = ((msg.data[3] & 0xFF) << 8) | (msg.data[2] & 0xFF);
+ _watchBatteryAverage = ((msg.data[5] & 0xFF) << 8) | (msg.data[4] & 0xFF);
+
+ qDebug() << "got battery voltage" << _watchBattery << "mV "
+ << "average" << _watchBatteryAverage << "mV "
+ << (_watchCharging ? "charging" : "discharging");
+
+ emit chargingChanged();
+ emit batteryLevelChanged();
+}
+
void MetaWatch::socketConnected()
{
if (!_connected) {
diff --git a/metawatch/metawatch.h b/metawatch/metawatch.h
index badfa83..8f0d52e 100644
--- a/metawatch/metawatch.h
+++ b/metawatch/metawatch.h
@@ -91,8 +91,15 @@ public:
bool isConnected() const;
bool busy() const;
- QDateTime dateTime();
void setDateTime(const QDateTime& dateTime);
+ void queryDateTime();
+ QDateTime dateTime() const;
+
+ void queryBatteryLevel();
+ int batteryLevel() const;
+
+ void queryCharging();
+ bool charging() const;
void grabButton(int button);
void ungrabButton(int button);
@@ -131,11 +138,17 @@ protected:
QStringList _buttonNames;
// Current watch state
+ QDateTime _watchTime;
+ short _watchBattery;
+ short _watchBatteryAverage;
+ bool _watchCharging;
Mode _currentMode;
Mode _paintMode;
- // For QPaintDevice
+ // Required by QPaintDevice
mutable MetaWatchPaintEngine* _paintEngine;
+
+ /** The shadow framebuffers for each of the watch modes */
QImage _image[3];
// Timers to retry the connection when the watch is not found.
@@ -169,8 +182,14 @@ protected:
static quint16 calcCrc(const QByteArray& data, int size);
static quint16 calcCrc(const Message& msg);
+ /** Sends a message to the watch. Does not block. */
void send(const Message& msg);
+ /** Sends a message to the watch if a message of the same type is not
+ * already queued. Does not block.
+ */
+ void sendIfNotQueued(const Message& msg);
+ /* Some functions that wrap sending some watch messages. */
void setVibrateMode(bool enable, uint on, uint off, uint cycles);
void updateLcdLine(Mode mode, const QImage& image, int line);
void updateLcdLines(Mode mode, const QImage& image, int lineA, int lineB);
@@ -182,9 +201,13 @@ protected:
void disableButton(Mode mode, Button button, ButtonPress press);
void handleMessage(const Message& msg);
+ void handleDeviceTypeMessage(const Message& msg);
+ void handleRealTimeClockMessage(const Message& msg);
void handleStatusChangeMessage(const Message& msg);
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: