summaryrefslogtreecommitdiff
path: root/src/metawatch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/metawatch.cpp')
-rw-r--r--src/metawatch.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/metawatch.cpp b/src/metawatch.cpp
new file mode 100644
index 0000000..a27d0ec
--- /dev/null
+++ b/src/metawatch.cpp
@@ -0,0 +1,183 @@
+#include <QtCore/QDataStream>
+#include <QtCore/QDateTime>
+#include <QtCore/QDebug>
+
+#include "metawatch.h"
+#include "metawatchbletransport.h"
+
+MetaWatch::MetaWatch(const QString &btAddr, QObject *parent) :
+ QObject(parent)
+{
+ GatoPeripheral *peripheral = new GatoPeripheral(GatoAddress(btAddr), this);
+ _transport = new MetaWatchBLETransport(peripheral, this);
+
+ connect(_transport, &MetaWatchTransport::connected, this, &MetaWatch::connected);
+ connect(_transport, &MetaWatchTransport::disconnected, this, &MetaWatch::disconnected);
+ connect(_transport, &MetaWatchTransport::messageReceived, this, &MetaWatch::handleTransportMessage);
+}
+
+QList<QUrl> MetaWatch::availableClocks()
+{
+ QList<QUrl> clocks;
+
+ for (int i = 0; i < 6; i++) {
+ clocks << QUrl("clock://" + QString::number(i));
+ }
+
+ return clocks;
+}
+
+void MetaWatch::setDateTime(const QDateTime &dt)
+{
+ const QDate &date = dt.date();
+ const QTime &time = dt.time();
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s.setByteOrder(QDataStream::BigEndian);
+ s << quint16(date.year()) << quint8(date.month()) << quint8(date.day());
+ s << quint8(date.dayOfWeek() % 7);
+ s << quint8(time.hour()) << quint8(time.minute()) << quint8(time.second());
+
+ _transport->sendMessage(MessageSetRealTimeClock, 0, data);
+}
+
+void MetaWatch::configure(WatchProperties props)
+{
+ _transport->sendMessage(MessageWatchPropertyOperation, props | WatchPropertyOperationWrite, QByteArray());
+}
+
+void MetaWatch::updateDeviceType()
+{
+ // Also disables HFP/MAP connection.
+ _transport->sendMessage(MessageGetDeviceType, 0xC0, QByteArray());
+}
+
+void MetaWatch::updateBatteryStatus()
+{
+ _transport->sendMessage(MessageGetBatteryStatus, 0, QByteArray());
+}
+
+void MetaWatch::updateLcdDisplay()
+{
+ // Switches to UiGen2 mode and to page 0.
+ _transport->sendMessage(MessageUpdateLcdDisplay, 0x80, QByteArray());
+}
+
+void MetaWatch::updateWidgetList(const QList<WidgetInfo*> &widgets)
+{
+ int num_widgets = 0;
+
+ // Count valid widgets
+ for (int w = 0; w < widgets.size(); w++) {
+ const WidgetInfo *info = widgets[w];
+ if (info->valid()) num_widgets++;
+ }
+
+ const int max_widgets_in_one_msg = 7;
+ const int num_messages = (num_widgets + (max_widgets_in_one_msg - 1)) / max_widgets_in_one_msg;
+ int num_message = 0;
+ QByteArray msg;
+
+ Q_ASSERT(num_messages < 4);
+
+ msg.reserve(max_widgets_in_one_msg * 2);
+
+ if (num_widgets == 0) {
+ msg.append(static_cast<char>(0xFF));
+ msg.append(static_cast<char>(0x00));
+
+ // Clear all widgets
+ _transport->sendMessage(MessageSetWidgetList, 0x4, msg);
+
+ return;
+ }
+
+ qDebug() << "Msgs" << num_messages << num_message;
+
+ for (int w = 0; w < num_widgets; w++) {
+ WidgetInfo *info = widgets[w];
+ if (!info->valid()) continue; // Skip disabled/empty widget
+
+ quint8 id = w;
+ quint8 options = ((info->page() << 4) & 0x30)
+ | ((info->size() << 2) & 0xC) | ((info->position() << 2) & 0x3);
+
+ if (info->url().scheme() == "clock") {
+ id |= (clockUrlToClockId(info->url()) << 4) & 0xF0;
+ options |= 0x80;
+ }
+
+ if (info->invert()) {
+ options |= 0x40;
+ }
+
+ qDebug() << QString::number(id, 16) << QString::number(options, 16);
+
+ msg.append(id);
+ msg.append(options);
+
+ if (msg.size() >= max_widgets_in_one_msg * 2) {
+ Q_ASSERT(num_message < num_messages);
+ _transport->sendMessage(MessageSetWidgetList,
+ ((num_messages << 2) & 0xC) | (num_message & 0x3),
+ msg);
+
+ msg.clear();
+ msg.reserve(max_widgets_in_one_msg * 2);
+ num_message++;
+ }
+ }
+
+ if (msg.size() > 0) {
+ Q_ASSERT(num_message < num_messages);
+ _transport->sendMessage(MessageSetWidgetList,
+ ((num_messages << 2) & 0xC) | (num_message & 0x3),
+ msg);
+ }
+}
+
+void MetaWatch::connectDevice()
+{
+ _transport->connectDevice();
+}
+
+void MetaWatch::disconnectDevice()
+{
+ _transport->disconnectDevice();
+}
+
+int MetaWatch::clockUrlToClockId(const QUrl &url)
+{
+ if (url.scheme() != "clock")
+ return -1;
+
+ QString host = url.host();
+ if (!host.startsWith("clock"))
+ return -1;
+
+ return host.mid(5).toInt();
+}
+
+void MetaWatch::handleTransportMessage(quint8 type, quint8 options, const QByteArray &payload)
+{
+ switch (type) {
+ case MessageGetDeviceTypeResponse:
+ emit deviceType(static_cast<DeviceType>(options & 0xF));
+ break;
+ case MessageModeChangeIndication:
+ qDebug() << "Got mode change indication";
+ break;
+ case MessageReadBatteryStatusResponse:
+ if (payload.size() < 6) {
+ qWarning() << "Invalid battery status response size";
+ }
+ emit batteryStatus(payload[1], payload[2]);
+ break;
+ case MessageConnectionChange:
+ case MessageIntervalChanged:
+ // No idea what to do with these.
+ break;
+ default:
+ qWarning() << "Unknown message type received:" << QString::number(type, 16);
+ }
+}