summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/jskitmanager.cpp8
-rw-r--r--daemon/jskitobjects.cpp64
-rw-r--r--daemon/jskitobjects.h11
-rw-r--r--daemon/watchconnector.cpp106
-rw-r--r--daemon/watchconnector.h10
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;