diff options
Diffstat (limited to 'daemon')
| -rw-r--r-- | daemon/jskitmanager.cpp | 8 | ||||
| -rw-r--r-- | daemon/jskitobjects.cpp | 64 | ||||
| -rw-r--r-- | daemon/jskitobjects.h | 11 | ||||
| -rw-r--r-- | daemon/watchconnector.cpp | 106 | ||||
| -rw-r--r-- | daemon/watchconnector.h | 10 |
5 files changed, 193 insertions, 6 deletions
diff --git a/daemon/jskitmanager.cpp b/daemon/jskitmanager.cpp index 2da1986..a24ab10 100644 --- a/daemon/jskitmanager.cpp +++ b/daemon/jskitmanager.cpp @@ -155,8 +155,12 @@ void JSKitManager::startJsApp() // Shims for compatibility... QJSValue result = _engine->evaluate( - "function XMLHttpRequest() { return Pebble.createXMLHttpRequest(); }\n" - ); + "function XMLHttpRequest() { return Pebble.createXMLHttpRequest(); }\n\ + function setInterval(func, time) { return Pebble.setInterval(func, time); }\n\ + function clearInterval(id) { Pebble.clearInterval(id); }\n\ + function setTimeout(func, time) { return Pebble.setTimeout(func, time); }\n\ + function clearTimeout(id) { Pebble.clearTimeout(id); }\n\ + "); Q_ASSERT(!result.isError()); // Polyfills... diff --git a/daemon/jskitobjects.cpp b/daemon/jskitobjects.cpp index 01a7e20..d9ef02f 100644 --- a/daemon/jskitobjects.cpp +++ b/daemon/jskitobjects.cpp @@ -4,6 +4,7 @@ #include <QAuthenticator> #include <QBuffer> #include <QDir> +#include <QTimerEvent> #include <QCryptographicHash> #include <limits> #include "jskitobjects.h" @@ -38,6 +39,69 @@ void JSKitPebble::removeEventListener(const QString &type, QJSValue function) } } +int JSKitPebble::setInterval(QJSValue expression, int delay) +{ + qCDebug(l) << "Setting interval for " << delay << "ms: " << expression.toString(); + if (expression.isString() || expression.isCallable()) { + int timerId = startTimer(delay); + _intervals.insert(timerId, expression); + qCDebug(l) << "Timer id: " << timerId; + return timerId; + } + return -1; +} + +void JSKitPebble::clearInterval(int timerId) +{ + qCDebug(l) << "Killing interval " << timerId ; + killTimer(timerId); + _intervals.remove(timerId); +} + +int JSKitPebble::setTimeout(QJSValue expression, int delay) +{ + qCDebug(l) << "Setting timeout for " << delay << "ms: " << expression.toString(); + if (expression.isString() || expression.isCallable()) { + int timerId = startTimer(delay); + _timeouts.insert(timerId, expression); + return timerId; + } + return -1; +} + +void JSKitPebble::clearTimeout(int timerId) +{ + qCDebug(l) << "Killing timeout " << timerId ; + killTimer(timerId); + _timeouts.remove(timerId); +} + +void JSKitPebble::timerEvent(QTimerEvent *event) +{ + int id = event->timerId(); + QJSValue expression; // find in either intervals or timeouts + if (_intervals.contains(id)) + expression = _intervals.value(id); + else if (_timeouts.contains(id)) { + expression = _timeouts.value(id); + killTimer(id); // timeouts don't repeat + } + else { + qCWarning(l) << "Unknown timer event"; + killTimer(id); // interval nor timeout exist. kill the timer + return; + } + + if (expression.isCallable()) { // call it if it's a function + QJSValue result = expression.call().toString(); + qCDebug(l) << "Timer function result: " << result.toString(); + } + else { // otherwise evaluate it + QJSValue result = _mgr->engine()->evaluate(expression.toString()); + qCDebug(l) << "Timer expression result: " << result.toString(); + } +} + uint JSKitPebble::sendAppMessage(QJSValue message, QJSValue callbackForAck, QJSValue callbackForNack) { QVariantMap data = message.toVariant().toMap(); diff --git a/daemon/jskitobjects.h b/daemon/jskitobjects.h index 43e1c30..9f5308f 100644 --- a/daemon/jskitobjects.h +++ b/daemon/jskitobjects.h @@ -19,6 +19,12 @@ public: Q_INVOKABLE void addEventListener(const QString &type, QJSValue function); Q_INVOKABLE void removeEventListener(const QString &type, QJSValue function); + Q_INVOKABLE int setInterval(QJSValue expression, int delay); + Q_INVOKABLE void clearInterval(int timerId); + + Q_INVOKABLE int setTimeout(QJSValue expression, int delay); + Q_INVOKABLE void clearTimeout(int timerId); + Q_INVOKABLE uint sendAppMessage(QJSValue message, QJSValue callbackForAck = QJSValue(), QJSValue callbackForNack = QJSValue()); Q_INVOKABLE void showSimpleNotificationOnPebble(const QString &title, const QString &body); @@ -32,6 +38,9 @@ public: void invokeCallbacks(const QString &type, const QJSValueList &args = QJSValueList()); +protected: + void timerEvent(QTimerEvent *event); + private: QJSValue buildAckEventObject(uint transaction, const QString &message = QString()) const; @@ -39,6 +48,8 @@ private: AppInfo _appInfo; JSKitManager *_mgr; QHash<QString, QList<QJSValue>> _callbacks; + QHash<int, QJSValue> _intervals; + QHash<int, QJSValue> _timeouts; }; class JSKitConsole : public QObject diff --git a/daemon/watchconnector.cpp b/daemon/watchconnector.cpp index 9993a38..1701972 100644 --- a/daemon/watchconnector.cpp +++ b/daemon/watchconnector.cpp @@ -53,6 +53,7 @@ QVariantMap WatchConnector::WatchVersions::toMap() const map.insert("bootloader", this->bootLoaderBuild.toTime_t()); map.insert("serial", this->serialNumber); map.insert("address", this->address.toHex()); + map.insert("platform", this->hardwarePlatform); map.insertMulti("firmware", this->main.toMap()); map.insertMulti("firmware", this->safe.toMap()); } @@ -89,10 +90,14 @@ WatchConnector::WatchConnector(QObject *parent) : hardwareMapping.insert(BIANCA, HWMap(APLITE, "v2_0")); hardwareMapping.insert(SNOWY_EVT2, HWMap(BASALT, "snowy_evt2")); hardwareMapping.insert(SNOWY_DVT, HWMap(BASALT, "snowy_dvt")); + hardwareMapping.insert(BOBBY_SMILES, HWMap(BASALT, "snowy_s3")); + hardwareMapping.insert(SPALDING_EVT, HWMap(CHALK, "spalding_evt")); + hardwareMapping.insert(SPALDING, HWMap(CHALK, "spalding")); hardwareMapping.insert(TINTIN_BB, HWMap(APLITE, "bigboard")); hardwareMapping.insert(TINTIN_BB2, HWMap(APLITE, "bb2")); hardwareMapping.insert(SNOWY_BB, HWMap(BASALT, "snowy_bb")); hardwareMapping.insert(SNOWY_BB2, HWMap(BASALT, "snowy_bb2")); + hardwareMapping.insert(SPALDING_BB2, HWMap(CHALK, "spalding_bb2")); setEndpointHandler(watchVERSION, [this](const QByteArray &data) { Unpacker u(data); @@ -122,6 +127,18 @@ WatchConnector::WatchConnector(QObject *parent) : platform = hardwareMapping.value(_versions.safe.hw_revision).first; + switch (this->platform) { + case APLITE: + _versions.hardwarePlatform = "aplite"; + break; + case BASALT: + _versions.hardwarePlatform = "basalt"; + break; + case CHALK: + _versions.hardwarePlatform = "chalk"; + break; + } + if (u.bad()) { qCWarning(l) << "short read while reading firmware version"; } else { @@ -596,8 +613,93 @@ void WatchConnector::sendNotification(uint lead, QString sender, QString data, Q sendMessage(watchNOTIFICATION, res); } break; - case BASALT: { - qCWarning(l) << "Tried sending notification to unsupported watch platform" << lead << sender << data << subject; + case BASALT: + case CHALK: { + int source; + switch (lead) { + case leadEMAIL: + source = 19; + break; + case leadFACEBOOK: + source = 11; + break; + case leadSMS: + source = 45; + break; + case leadTWITTER: + source = 6; + break; + default: + source = 1; + } + + int attributesCount = 0; + QByteArray attributes; + + attributesCount++; + QByteArray senderBytes = sender.left(64).toUtf8(); + attributes.append(0x01); // id = title + attributes.append(senderBytes.length() & 0xFF); attributes.append(((senderBytes.length() >> 8) & 0xFF)); // length + attributes.append(senderBytes); // content + + attributesCount++; + QByteArray subjectBytes = (subject.isEmpty() ? data : subject).left(64).toUtf8(); + attributes.append(0x02); // id = subtitle + attributes.append(subjectBytes.length() & 0xFF); attributes.append((subjectBytes.length() >> 8) & 0xFF); // length + attributes.append(subjectBytes); //content + + if (!data.isEmpty()) { + attributesCount++; + QByteArray dataBytes = data.left(512).toUtf8(); + attributes.append(0x03); // id = body + attributes.append(dataBytes.length() & 0xFF); attributes.append((dataBytes.length() >> 8) & 0xFF); // length + attributes.append(dataBytes); // content + } + + attributesCount++; + attributes.append(0x04); // id = tinyicon + attributes.append(0x04); attributes.append('\0'); // length + attributes.append(source); attributes.append('\0'); attributes.append('\0'); attributes.append('\0'); // content + + + QByteArray actions; + actions.append('\0'); // action id + actions.append(0x04); // type = dismiss + actions.append(0x01); // attributes length = 1 + actions.append(0x01); // attribute id = title + actions.append(0x07); actions.append('\0'); // attribute length + actions.append("Dismiss"); // attribute content + + + QByteArray itemId = QUuid::createUuid().toRfc4122(); + int time = QDateTime::currentMSecsSinceEpoch() / 1000; + QByteArray item; + item.append(itemId); // item id + item.append(QUuid().toRfc4122()); // parent id + item.append(time & 0xFF); item.append((time >> 8) & 0xFF); item.append((time >> 16) & 0xFF); item.append((time >> 24) & 0xFF); // timestamp + item.append('\0'); item.append('\0'); // duration + item.append(0x01); // type: notification + item.append('\0'); item.append('\0'); // flags + item.append(0x01); // layout + + int length = attributes.length() + actions.length(); + item.append(length & 0xFF); item.append((length >> 8) & 0xFF); // data length + item.append(attributesCount); // attributes count + item.append(0x01); // actions count + item.append(attributes); + item.append(actions); + + int token = (qrand() % ((int)pow(2, 16) - 2)) + 1; + QByteArray blob; + blob.append(0x01); // command = insert + blob.append(token & 0xFF); blob.append((token >> 8) & 0xFF); // token + blob.append(0x04); //database id = notification + blob.append(itemId.length() & 0xFF); // key length + blob.append(itemId); // key + blob.append(item.length() & 0xFF); blob.append((item.length() >> 8) & 0xFF); // value length + blob.append(item); + + sendMessage(watchBLOB_DB, blob); } break; default: diff --git a/daemon/watchconnector.h b/daemon/watchconnector.h index 4369d87..83e065c 100644 --- a/daemon/watchconnector.h +++ b/daemon/watchconnector.h @@ -161,16 +161,21 @@ public: BIANCA = 6, SNOWY_EVT2 = 7, SNOWY_DVT = 8, + SPALDING_EVT = 9, + BOBBY_SMILES = 10, + SPALDING = 11, TINTIN_BB = 0xFF, TINTIN_BB2 = 0xFE, SNOWY_BB = 0xFD, - SNOWY_BB2 = 0xFC + SNOWY_BB2 = 0xFC, + SPALDING_BB2 = 0xFB }; enum HardwarePlatform { HP_UNKNOWN = 0, APLITE, - BASALT + BASALT, + CHALK }; typedef QPair<HardwarePlatform,QString> HWMap; QMap<HardwareRevision, HWMap> hardwareMapping; @@ -192,6 +197,7 @@ public: SoftwareVersion safe; QDateTime bootLoaderBuild; QString hardwareRevision; + QString hardwarePlatform; QString serialNumber; QByteArray address; |
