Pebble: support "dismiss all" action also on Pebble Time/FW 3.x notifications

This is done through a workaround, now we just label it as a generic action and reply properly to the invocation from the Pebble.
Fixes #86
This commit is contained in:
Andreas Shimokawa 2015-08-27 18:01:19 +02:00
parent 44c7f99c58
commit 2ca8e149ee
2 changed files with 57 additions and 33 deletions

View File

@ -1,5 +1,8 @@
###Changelog ###Changelog
####next version
* Pebble: support "dismiss all" action also on Pebble Time/FW 3.x notifications
####Version 0.5.1 ####Version 0.5.1
* Pebble: support taking screenshot from Pebble Time * Pebble: support taking screenshot from Pebble Time
* Fix broken "find lost device" which was broken in 0.5.0 * Fix broken "find lost device" which was broken in 0.5.0

View File

@ -95,6 +95,11 @@ public class PebbleProtocol extends GBDeviceProtocol {
static final byte MUSICCONTROL_VOLUMEDOWN = 7; static final byte MUSICCONTROL_VOLUMEDOWN = 7;
static final byte MUSICCONTROL_GETNOWPLAYING = 7; static final byte MUSICCONTROL_GETNOWPLAYING = 7;
static final byte NOTIFICATIONACTION_ACK = 0;
static final byte NOTIFICATIONACTION_NACK = 1;
static final byte NOTIFICATIONACTION_INVOKE = 0x02;
static final byte NOTIFICATIONACTION_RESPONSE = 0x11;
static final byte TIME_GETTIME = 0; static final byte TIME_GETTIME = 0;
static final byte TIME_SETTIME = 2; static final byte TIME_SETTIME = 2;
static final byte TIME_SETTIME_UTC = 3; static final byte TIME_SETTIME_UTC = 3;
@ -524,21 +529,22 @@ public class PebbleProtocol extends GBDeviceProtocol {
private byte[] encodeBlobdbNotification(int timestamp, String title, String subtitle, String body, byte type) { private byte[] encodeBlobdbNotification(int timestamp, String title, String subtitle, String body, byte type) {
String[] parts = {title, subtitle, body}; String[] parts = {title, subtitle, body};
int icon_id = 1; int icon_id = 0x80000000 | 1;
switch (type) { switch (type) {
case NOTIFICATION_EMAIL: case NOTIFICATION_EMAIL:
icon_id = 19; icon_id = 0x80000000 | 19;
break; break;
case NOTIFICATION_SMS: case NOTIFICATION_SMS:
icon_id = 45; icon_id = 0x80000000 | 45;
} }
// Calculate length first // Calculate length first
final short NOTIFICATION_PIN_LENGTH = 46; final short NOTIFICATION_PIN_LENGTH = 46;
final short ACTIONS_LENGTH = 17; final short ACTIONS_LENGTH = 17;
byte attributes_count = 1; // icon byte attributes_count = 1; // icon
byte actions_count = 1; // dismiss
short attributes_length = 7; // icon short attributes_length = 7 + ACTIONS_LENGTH; // icon
if (parts != null) { if (parts != null) {
for (String s : parts) { for (String s : parts) {
if (s == null || s.equals("")) { if (s == null || s.equals("")) {
@ -549,13 +555,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
} }
} }
byte actions_count = 0;
if (mForceProtocol) {
actions_count = 1;
attributes_length += ACTIONS_LENGTH;
}
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
short pin_length = (short) (NOTIFICATION_PIN_LENGTH + attributes_length); short pin_length = (short) (NOTIFICATION_PIN_LENGTH + attributes_length);
@ -598,20 +597,39 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.putShort((short) 4); // length of int buf.putShort((short) 4); // length of int
buf.putInt(icon_id); buf.putInt(icon_id);
if (mForceProtocol) { // ACTION
// ACTION buf.put((byte) 0x01); // id
buf.put((byte) 0x01); // id buf.put((byte) 0x02); // generic action, dismiss did not do anything
buf.put((byte) 0x04); // dismiss action buf.put((byte) 0x01); // number attributes
buf.put((byte) 0x01); // number attributes buf.put((byte) 0x01); // attribute id (title)
buf.put((byte) 0x01); // attribute id (title) String actionstring = "dismiss all";
String actionstring = "dismiss all"; buf.putShort((short) actionstring.length());
buf.putShort((short) actionstring.length()); buf.put(actionstring.getBytes());
buf.put(actionstring.getBytes());
}
return encodeBlobdb(UUID.randomUUID(), BLOBDB_INSERT, BLOBDB_NOTIFICATION, buf.array()); return encodeBlobdb(UUID.randomUUID(), BLOBDB_INSERT, BLOBDB_NOTIFICATION, buf.array());
} }
public byte[] encodeActionResponse(UUID uuid) {
short length = 38;
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + length);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(length);
buf.putShort(ENDPOINT_NOTIFICATIONACTION);
buf.put(NOTIFICATIONACTION_RESPONSE);
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(NOTIFICATIONACTION_ACK);
buf.put((byte) 2); //nr of attributes
buf.put((byte) 6); // icon
buf.putShort((short) 4); // length
buf.putInt(0x80000033); // icon id
buf.put((byte) 2); // title
buf.putShort((short) 9); // length
buf.put("Dismissed".getBytes());
return buf.array();
}
public byte[] encodeInstallMetadata(UUID uuid, String appName, short appVersion, short sdkVersion, int flags, int iconId) { public byte[] encodeInstallMetadata(UUID uuid, String appName, short appVersion, short sdkVersion, int flags, int iconId) {
final short METADATA_LENGTH = 126; final short METADATA_LENGTH = 126;
@ -1077,21 +1095,24 @@ public class PebbleProtocol extends GBDeviceProtocol {
return null; return null;
} }
private GBDeviceEventDismissNotification decodeNotificationAction3x(ByteBuffer buf) { private GBDeviceEvent[] decodeNotificationAction3x(ByteBuffer buf) {
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
byte command = buf.get(); byte command = buf.get();
if (command == 0x02) { // dismiss notification ? if (command == NOTIFICATIONACTION_INVOKE) {
buf.getLong(); // skip 8 bytes of UUID buf.order(ByteOrder.BIG_ENDIAN);
buf.getInt(); // skip 4 bytes of UUID long uuid_high = buf.getLong();
int id = buf.getInt(); long uuid_low = buf.getLong();
short action = buf.getShort(); // at least the low byte should be the action - or not? int id = (int) (uuid_low & 0xffff);
if (action == 0x0001) { byte action = buf.get();
GBDeviceEventDismissNotification devEvtDismissNotification = new GBDeviceEventDismissNotification(); if (action == 0x01) {
devEvtDismissNotification.notificationID = id; GBDeviceEventDismissNotification dismissNotification = new GBDeviceEventDismissNotification();
return devEvtDismissNotification; dismissNotification.notificationID = id;
GBDeviceEventSendBytes sendBytesAck = new GBDeviceEventSendBytes();
sendBytesAck.encodedBytes = encodeActionResponse(new UUID(uuid_high, uuid_low));
return new GBDeviceEvent[]{sendBytesAck, dismissNotification};
} }
LOG.info("unexpected paramerter in dismiss action: " + action); LOG.info("unexpected action: " + action);
} }
return null; return null;
@ -1383,7 +1404,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
devEvts = new GBDeviceEvent[]{decodeNotificationAction2x(buf)}; devEvts = new GBDeviceEvent[]{decodeNotificationAction2x(buf)};
break; break;
case ENDPOINT_NOTIFICATIONACTION: case ENDPOINT_NOTIFICATIONACTION:
devEvts = new GBDeviceEvent[]{decodeNotificationAction3x(buf)}; devEvts = decodeNotificationAction3x(buf);
break; break;
case ENDPOINT_PING: case ENDPOINT_PING:
devEvts = new GBDeviceEvent[]{decodePing(buf)}; devEvts = new GBDeviceEvent[]{decodePing(buf)};