From 1adf7f1bcde493ccaacedb0d9778911ad69ff335 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 4 Sep 2014 01:55:14 +0200 Subject: Initial import --- src/metawatch.cpp | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 src/metawatch.cpp (limited to 'src/metawatch.cpp') 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 +#include +#include + +#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 MetaWatch::availableClocks() +{ + QList 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 &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(0xFF)); + msg.append(static_cast(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(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); + } +} -- cgit v1.2.3