From 44c7f99c581a1e89601cee2bd807d4abedefcaa9 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 27 Aug 2015 15:02:29 +0200 Subject: [PATCH 1/3] GBDeviceProtocol::decodeResponse() now returns an array GBDeviceEvents This allowed to remove some ugly hacks from pebble code, when encoding a response in a GBDeviceEventSendBytes and at the same time trying to notify generic code via another GBDeviceEnvent. --- .../pebble/GadgetbridgePblSupport.java | 4 +- .../devices/pebble/MorpheuzSupport.java | 62 ++++------ .../devices/pebble/PebbleIoThread.java | 13 ++- .../devices/pebble/PebbleProtocol.java | 109 +++++++++++------- .../devices/pebble/WeatherNeatSupport.java | 4 +- .../service/serial/GBDeviceProtocol.java | 2 +- 6 files changed, 104 insertions(+), 90 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/GadgetbridgePblSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/GadgetbridgePblSupport.java index 0c709d9e8..f12bba391 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/GadgetbridgePblSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/GadgetbridgePblSupport.java @@ -33,7 +33,7 @@ public class GadgetbridgePblSupport { mPebbleProtocol = pebbleProtocol; } - public GBDeviceEvent handleMessage(ArrayList> pairs) { + public GBDeviceEvent[] handleMessage(ArrayList> pairs) { int timestamp = 0; for (Pair pair : pairs) { switch (pair.first) { @@ -75,6 +75,6 @@ public class GadgetbridgePblSupport { } GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); sendBytes.encodedBytes = mPebbleProtocol.encodeApplicationMessageAck(uuid, mPebbleProtocol.last_id); - return sendBytes; + return new GBDeviceEvent[]{sendBytes}; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/MorpheuzSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/MorpheuzSupport.java index a557ed80d..af368adc3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/MorpheuzSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/MorpheuzSupport.java @@ -5,7 +5,6 @@ import android.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.SimpleTimeZone; import java.util.TimeZone; @@ -41,7 +40,6 @@ public class MorpheuzSupport { public static final UUID uuid = UUID.fromString("5be44f1d-d262-4ea6-aa30-ddbec1e3cab2"); private final PebbleProtocol mPebbleProtocol; - private boolean sent_to_gadgetbridge = false; // data received from Morpheuz in native format private int smartalarm_from = -1; // time in minutes relative from 0:00 for smart alarm (earliest) private int smartalarm_to = -1;// time in minutes relative from 0:00 for smart alarm (latest) @@ -57,21 +55,15 @@ public class MorpheuzSupport { private byte[] encodeMorpheuzMessage(int key, int value) { ArrayList> pairs = new ArrayList<>(); pairs.add(new Pair(key, value)); - byte[] ackMessage = mPebbleProtocol.encodeApplicationMessageAck(uuid, mPebbleProtocol.last_id); - byte[] testMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, uuid, pairs); - ByteBuffer buf = ByteBuffer.allocate(ackMessage.length + testMessage.length); - - // encode ack and put in front of push message (hack for acknowledging the last message) - buf.put(ackMessage); - buf.put(testMessage); - - return buf.array(); + return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, uuid, pairs); } - public GBDeviceEvent handleMessage(ArrayList> pairs) { + public GBDeviceEvent[] handleMessage(ArrayList> pairs) { + int ctrl_message = 0; + GBDeviceEventSleepMonitorResult sleepMonitorResult = null; + for (Pair pair : pairs) { - int ctrl_message = 0; switch (pair.first) { case KEY_TRANSMIT: case KEY_GONEOFF: @@ -79,22 +71,11 @@ public class MorpheuzSupport { alarm_gone_off = (int) pair.second; LOG.info("got gone off: " + alarm_gone_off / 60 + ":" + alarm_gone_off % 60); } - /* super-ugly hack: if if did not notice GadgetBridge yet, do so and delay confirmation so Morpheuz - * will resend gone off data. The second time, we acknowledge it. - * - * this can be fixed by allowing to return multiple GBDeviceCommands - */ - if (sent_to_gadgetbridge) { - ctrl_message = MorpheuzSupport.CTRL_VERSION_DONE | MorpheuzSupport.CTRL_GONEOFF_DONE | MorpheuzSupport.CTRL_TRANSMIT_DONE | MorpheuzSupport.CTRL_SET_LAST_SENT; - } else { - GBDeviceEventSleepMonitorResult sleepMonitorResult = new GBDeviceEventSleepMonitorResult(); - sleepMonitorResult.smartalarm_from = smartalarm_from; - sleepMonitorResult.smartalarm_to = smartalarm_to; - sleepMonitorResult.alarm_gone_off = alarm_gone_off; - sleepMonitorResult.recording_base_timestamp = recording_base_timestamp; - sent_to_gadgetbridge = true; - return sleepMonitorResult; - } + sleepMonitorResult = new GBDeviceEventSleepMonitorResult(); + sleepMonitorResult.smartalarm_from = smartalarm_from; + sleepMonitorResult.smartalarm_to = smartalarm_to; + sleepMonitorResult.alarm_gone_off = alarm_gone_off; + sleepMonitorResult.recording_base_timestamp = recording_base_timestamp; break; case KEY_POINT: if (recording_base_timestamp == -1) { @@ -140,7 +121,6 @@ public class MorpheuzSupport { case KEY_VERSION: LOG.info("got version: " + ((float) ((int) pair.second) / 10.0f)); ctrl_message = MorpheuzSupport.CTRL_VERSION_DONE | MorpheuzSupport.CTRL_SET_LAST_SENT; - sent_to_gadgetbridge = false; break; case KEY_BASE: // fix timestamp @@ -156,14 +136,20 @@ public class MorpheuzSupport { LOG.info("unhandled key: " + pair.first); break; } - if (ctrl_message > 0) { - GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); - sendBytes.encodedBytes = encodeMorpheuzMessage(MorpheuzSupport.KEY_CTRL, ctrl_message); - return sendBytes; - } } - GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); - sendBytes.encodedBytes = mPebbleProtocol.encodeApplicationMessageAck(uuid, mPebbleProtocol.last_id); - return sendBytes; + + // always ack + GBDeviceEventSendBytes sendBytesAck = new GBDeviceEventSendBytes(); + sendBytesAck.encodedBytes = mPebbleProtocol.encodeApplicationMessageAck(uuid, mPebbleProtocol.last_id); + + // sometimes send control message + GBDeviceEventSendBytes sendBytesCtrl = null; + if (ctrl_message > 0) { + sendBytesCtrl = new GBDeviceEventSendBytes(); + sendBytesCtrl.encodedBytes = encodeMorpheuzMessage(MorpheuzSupport.KEY_CTRL, ctrl_message); + } + + // ctrl and sleep monitor might be null, thats okay + return new GBDeviceEvent[]{sendBytesAck, sendBytesCtrl, sleepMonitorResult}; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java index 281995296..17958601c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java @@ -237,12 +237,17 @@ public class PebbleIoThread extends GBDeviceIoThread { mInStream.skip(2); } - GBDeviceEvent deviceEvent = mPebbleProtocol.decodeResponse(buffer); - if (deviceEvent == null) { + GBDeviceEvent deviceEvents[] = mPebbleProtocol.decodeResponse(buffer); + if (deviceEvents == null) { LOG.info("unhandled message to endpoint " + endpoint + " (" + length + " bytes)"); } else { - if (!evaluateGBDeviceEventPebble(deviceEvent)) { - mPebbleSupport.evaluateGBDeviceEvent(deviceEvent); + for (GBDeviceEvent deviceEvent : deviceEvents) { + if (deviceEvent == null) { + continue; + } + if (!evaluateGBDeviceEventPebble(deviceEvent)) { + mPebbleSupport.evaluateGBDeviceEvent(deviceEvent); + } } } try { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index f8e390331..8c72ff4b1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -1059,15 +1059,31 @@ public class PebbleProtocol extends GBDeviceProtocol { return null; } - private GBDeviceEventDismissNotification decodeNotificationAction(ByteBuffer buf) { + private GBDeviceEventDismissNotification decodeNotificationAction2x(ByteBuffer buf) { buf.order(ByteOrder.LITTLE_ENDIAN); byte command = buf.get(); if (command == 0x02) { // dismiss notification ? - if (isFw3x) { - buf.getLong(); // skip 8 bytes of UUID - buf.getInt(); // skip 4 bytes of UUID + int id = buf.getInt(); + short action = buf.getShort(); // at least the low byte should be the action - or not? + if (action == 0x0001) { + GBDeviceEventDismissNotification devEvtDismissNotification = new GBDeviceEventDismissNotification(); + devEvtDismissNotification.notificationID = id; + return devEvtDismissNotification; } + LOG.info("unexpected paramerter in dismiss action: " + action); + } + + return null; + } + + private GBDeviceEventDismissNotification decodeNotificationAction3x(ByteBuffer buf) { + buf.order(ByteOrder.LITTLE_ENDIAN); + + byte command = buf.get(); + if (command == 0x02) { // dismiss notification ? + buf.getLong(); // skip 8 bytes of UUID + buf.getInt(); // skip 4 bytes of UUID int id = buf.getInt(); short action = buf.getShort(); // at least the low byte should be the action - or not? if (action == 0x0001) { @@ -1114,26 +1130,31 @@ public class PebbleProtocol extends GBDeviceProtocol { private GBDeviceEventSendBytes decodeDatalog(ByteBuffer buf, short length) { byte command = buf.get(); byte id = buf.get(); - if (command == DATALOG_TIMEOUT) { - LOG.info("DATALOG TIMEOUT. id=" + (id & 0xff) + " - ignoring"); - return null; - } - if (command == DATALOG_SENDDATA) { - buf.order(ByteOrder.LITTLE_ENDIAN); - int items_left = buf.getInt(); - int crc = buf.getInt(); - LOG.info("DATALOG SENDDATA. id=" + (id & 0xff) + ", items_left=" + items_left + ", total length=" + (length - 9)); - } else if (command == DATALOG_OPENSESSION) { - buf.order(ByteOrder.BIG_ENDIAN); - long uuid_high = buf.getLong(); - long uuid_low = buf.getLong(); - UUID uuid = new UUID(uuid_high, uuid_low); - buf.order(ByteOrder.LITTLE_ENDIAN); - int timestamp = buf.getInt(); - int log_tag = buf.getInt(); - byte item_type = buf.get(); - short item_size = buf.get(); - LOG.info("DATALOG OPENSESSION. id=" + (id & 0xff) + ", App UUID=" + uuid.toString() + ", item_type=" + item_type + ", item_size=" + item_size); + switch (command) { + case DATALOG_TIMEOUT: + LOG.info("DATALOG TIMEOUT. id=" + (id & 0xff) + " - ignoring"); + return null; + case DATALOG_SENDDATA: + buf.order(ByteOrder.LITTLE_ENDIAN); + int items_left = buf.getInt(); + int crc = buf.getInt(); + LOG.info("DATALOG SENDDATA. id=" + (id & 0xff) + ", items_left=" + items_left + ", total length=" + (length - 9)); + break; + case DATALOG_OPENSESSION: + buf.order(ByteOrder.BIG_ENDIAN); + long uuid_high = buf.getLong(); + long uuid_low = buf.getLong(); + UUID uuid = new UUID(uuid_high, uuid_low); + buf.order(ByteOrder.LITTLE_ENDIAN); + int timestamp = buf.getInt(); + int log_tag = buf.getInt(); + byte item_type = buf.get(); + short item_size = buf.get(); + LOG.info("DATALOG OPENSESSION. id=" + (id & 0xff) + ", App UUID=" + uuid.toString() + ", item_type=" + item_type + ", item_size=" + item_size); + break; + default: + LOG.info("unknown DATALOG command: " + (command & 0xff)); + break; } LOG.info("sending ACK (0x85)"); GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); @@ -1142,12 +1163,12 @@ public class PebbleProtocol extends GBDeviceProtocol { } @Override - public GBDeviceEvent decodeResponse(byte[] responseData) { + public GBDeviceEvent[] decodeResponse(byte[] responseData) { ByteBuffer buf = ByteBuffer.wrap(responseData); buf.order(ByteOrder.BIG_ENDIAN); short length = buf.getShort(); short endpoint = buf.getShort(); - GBDeviceEvent devEvt = null; + GBDeviceEvent devEvts[] = null; byte pebbleCmd = -1; switch (endpoint) { case ENDPOINT_MUSICCONTROL: @@ -1178,7 +1199,7 @@ public class PebbleProtocol extends GBDeviceProtocol { default: break; } - devEvt = musicCmd; + devEvts = new GBDeviceEvent[]{musicCmd}; break; case ENDPOINT_PHONECONTROL: pebbleCmd = buf.get(); @@ -1191,7 +1212,7 @@ public class PebbleProtocol extends GBDeviceProtocol { LOG.info("Unknown PHONECONTROL event" + pebbleCmd); break; } - devEvt = callCmd; + devEvts = new GBDeviceEvent[]{callCmd}; break; case ENDPOINT_FIRMWAREVERSION: pebbleCmd = buf.get(); @@ -1213,7 +1234,7 @@ public class PebbleProtocol extends GBDeviceProtocol { } else if (hwRev == -3) { // basalt emulator versionCmd.hwVersion = "dvt"; } - devEvt = versionCmd; + devEvts = new GBDeviceEvent[]{versionCmd}; break; case ENDPOINT_APPMANAGER: pebbleCmd = buf.get(); @@ -1253,12 +1274,12 @@ public class PebbleProtocol extends GBDeviceProtocol { break; } } - devEvt = appInfoCmd; + devEvts = new GBDeviceEvent[]{appInfoCmd}; break; case APPMANAGER_GETUUIDS: GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); sendBytes.encodedBytes = encodeSimpleMessage(ENDPOINT_APPMANAGER, APPMANAGER_GETAPPBANKSTATUS); - devEvt = sendBytes; + devEvts = new GBDeviceEvent[]{sendBytes}; tmpUUIDS.clear(); slotsUsed = buf.getInt(); for (int i = 0; i < slotsUsed; i++) { @@ -1282,7 +1303,7 @@ public class PebbleProtocol extends GBDeviceProtocol { deleteRes.event = GBDeviceEventAppManagement.Event.FAILURE; break; } - devEvt = deleteRes; + devEvts = new GBDeviceEvent[]{deleteRes}; break; default: LOG.info("Unknown APPMANAGER event" + pebbleCmd); @@ -1303,7 +1324,7 @@ public class PebbleProtocol extends GBDeviceProtocol { installRes.event = GBDeviceEventAppManagement.Event.FAILURE; break; } - devEvt = installRes; + devEvts = new GBDeviceEvent[]{installRes}; break; case ENDPOINT_APPLICATIONMESSAGE: pebbleCmd = buf.get(); @@ -1317,13 +1338,13 @@ public class PebbleProtocol extends GBDeviceProtocol { LOG.info("got APPLICATIONMESSAGE PUSH from UUID " + uuid); if (WeatherNeatSupport.uuid.equals(uuid)) { ArrayList> dict = decodeDict(buf); - devEvt = mWeatherNeatSupport.handleMessage(dict); + devEvts = mWeatherNeatSupport.handleMessage(dict); } else if (MorpheuzSupport.uuid.equals(uuid)) { ArrayList> dict = decodeDict(buf); - devEvt = mMorpheuzSupport.handleMessage(dict); + devEvts = mMorpheuzSupport.handleMessage(dict); } else if (GadgetbridgePblSupport.uuid.equals(uuid)) { ArrayList> dict = decodeDict(buf); - devEvt = mGadgetbridgePblSupport.handleMessage(dict); + devEvts = mGadgetbridgePblSupport.handleMessage(dict); } break; case APPLICATIONMESSAGE_ACK: @@ -1346,33 +1367,35 @@ public class PebbleProtocol extends GBDeviceProtocol { LOG.info("Pebble asked for Phone/App Version - repLYING!"); GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); sendBytes.encodedBytes = encodePhoneVersion(PHONEVERSION_REMOTE_OS_ANDROID); - devEvt = sendBytes; + devEvts = new GBDeviceEvent[]{sendBytes}; break; default: break; } break; case ENDPOINT_DATALOG: - devEvt = decodeDatalog(buf, length); + devEvts = new GBDeviceEvent[]{decodeDatalog(buf, length)}; break; case ENDPOINT_SCREENSHOT: - devEvt = decodeScreenshot(buf, length); + devEvts = new GBDeviceEvent[]{decodeScreenshot(buf, length)}; break; case ENDPOINT_EXTENSIBLENOTIFS: + devEvts = new GBDeviceEvent[]{decodeNotificationAction2x(buf)}; + break; case ENDPOINT_NOTIFICATIONACTION: - devEvt = decodeNotificationAction(buf); + devEvts = new GBDeviceEvent[]{decodeNotificationAction3x(buf)}; break; case ENDPOINT_PING: - devEvt = decodePing(buf); + devEvts = new GBDeviceEvent[]{decodePing(buf)}; break; case ENDPOINT_APPFETCH: - devEvt = decodeAppFetch(buf); + devEvts = new GBDeviceEvent[]{decodeAppFetch(buf)}; break; default: break; } - return devEvt; + return devEvts; } public void setForceProtocol(boolean force) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/WeatherNeatSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/WeatherNeatSupport.java index 0ddc190d6..cd6c5bb9a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/WeatherNeatSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/WeatherNeatSupport.java @@ -48,9 +48,9 @@ public class WeatherNeatSupport { return buf.array(); } - public GBDeviceEvent handleMessage(ArrayList> pairs) { + public GBDeviceEvent[] handleMessage(ArrayList> pairs) { GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); sendBytes.encodedBytes = encodeWeatherNeatMessage("Berlin", "22 C", "cloudy", 0); - return sendBytes; + return new GBDeviceEvent[] {sendBytes}; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/serial/GBDeviceProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/serial/GBDeviceProtocol.java index 20133c3b9..e99e0c250 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/serial/GBDeviceProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/serial/GBDeviceProtocol.java @@ -63,7 +63,7 @@ public abstract class GBDeviceProtocol { return null; } - public GBDeviceEvent decodeResponse(byte[] responseData) { + public GBDeviceEvent[] decodeResponse(byte[] responseData) { return null; } } \ No newline at end of file From 2ca8e149ee56d8871929ce3cfffd3cd67847a222 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 27 Aug 2015 18:01:19 +0200 Subject: [PATCH 2/3] 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 --- CHANGELOG.md | 3 + .../devices/pebble/PebbleProtocol.java | 87 ++++++++++++------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc66f9c5c..5974a62d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ###Changelog +####next version +* Pebble: support "dismiss all" action also on Pebble Time/FW 3.x notifications + ####Version 0.5.1 * Pebble: support taking screenshot from Pebble Time * Fix broken "find lost device" which was broken in 0.5.0 diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index 8c72ff4b1..111a79e66 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -95,6 +95,11 @@ public class PebbleProtocol extends GBDeviceProtocol { static final byte MUSICCONTROL_VOLUMEDOWN = 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_SETTIME = 2; 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) { String[] parts = {title, subtitle, body}; - int icon_id = 1; + int icon_id = 0x80000000 | 1; switch (type) { case NOTIFICATION_EMAIL: - icon_id = 19; + icon_id = 0x80000000 | 19; break; case NOTIFICATION_SMS: - icon_id = 45; + icon_id = 0x80000000 | 45; } // Calculate length first final short NOTIFICATION_PIN_LENGTH = 46; final short ACTIONS_LENGTH = 17; 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) { for (String s : parts) { 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(); 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.putInt(icon_id); - if (mForceProtocol) { - // ACTION - buf.put((byte) 0x01); // id - buf.put((byte) 0x04); // dismiss action - buf.put((byte) 0x01); // number attributes - buf.put((byte) 0x01); // attribute id (title) - String actionstring = "dismiss all"; - buf.putShort((short) actionstring.length()); - buf.put(actionstring.getBytes()); - } + // ACTION + buf.put((byte) 0x01); // id + buf.put((byte) 0x02); // generic action, dismiss did not do anything + buf.put((byte) 0x01); // number attributes + buf.put((byte) 0x01); // attribute id (title) + String actionstring = "dismiss all"; + buf.putShort((short) actionstring.length()); + buf.put(actionstring.getBytes()); 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) { final short METADATA_LENGTH = 126; @@ -1077,21 +1095,24 @@ public class PebbleProtocol extends GBDeviceProtocol { return null; } - private GBDeviceEventDismissNotification decodeNotificationAction3x(ByteBuffer buf) { + private GBDeviceEvent[] decodeNotificationAction3x(ByteBuffer buf) { buf.order(ByteOrder.LITTLE_ENDIAN); byte command = buf.get(); - if (command == 0x02) { // dismiss notification ? - buf.getLong(); // skip 8 bytes of UUID - buf.getInt(); // skip 4 bytes of UUID - int id = buf.getInt(); - short action = buf.getShort(); // at least the low byte should be the action - or not? - if (action == 0x0001) { - GBDeviceEventDismissNotification devEvtDismissNotification = new GBDeviceEventDismissNotification(); - devEvtDismissNotification.notificationID = id; - return devEvtDismissNotification; + if (command == NOTIFICATIONACTION_INVOKE) { + buf.order(ByteOrder.BIG_ENDIAN); + long uuid_high = buf.getLong(); + long uuid_low = buf.getLong(); + int id = (int) (uuid_low & 0xffff); + byte action = buf.get(); + if (action == 0x01) { + GBDeviceEventDismissNotification dismissNotification = new GBDeviceEventDismissNotification(); + 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; @@ -1383,7 +1404,7 @@ public class PebbleProtocol extends GBDeviceProtocol { devEvts = new GBDeviceEvent[]{decodeNotificationAction2x(buf)}; break; case ENDPOINT_NOTIFICATIONACTION: - devEvts = new GBDeviceEvent[]{decodeNotificationAction3x(buf)}; + devEvts = decodeNotificationAction3x(buf); break; case ENDPOINT_PING: devEvts = new GBDeviceEvent[]{decodePing(buf)}; From 75a1068a6907f963996cb3c816df7eb23eb7382f Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Thu, 27 Aug 2015 23:08:17 +0200 Subject: [PATCH 3/3] Added new french translation, thanks a lot, gnupyx! --- app/src/main/res/values-fr/strings.xml | 146 +++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 app/src/main/res/values-fr/strings.xml diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..9737eab95 --- /dev/null +++ b/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,146 @@ + + + Gadgetbridge + Gadgetbridge + Paramètre + Débugger + Quitter + Synchroniser + Moniteur de sommeil (ALPHA) + Trouver l\'appareil + Prendre une capture d\'écran + Déconnexion + Débugger + + Supprimer + + Vous êtes sur le point d\'installer le firmware %s à la place de celui qui est actuellement sur votre MiBand. + Ce firmware a été testé et est compatible with GadgetBridge + Ce firmware n\'est pas testé and peut ne pas être compatible avec GadgetBridge. Il ne vous est pas conseillé de flasher votre MiBand + + Paramètre + Paramètres généraux + Connecter votre appareil quand le Bluetooth est mise en marche + Date et heure + Synchroniser l\'horloge + Synchroniser l\'horloge lors de la connexion et quand l\'heure ou lorsque le fuseau horaire change sur Android + Notifications + Répétitions + SMS + Appel entrant + K9-Email + Message Pebble + Support des notififactions génériques + même lorsque l\'écran est allumé + toujours + quand l\'écran est éteint + jamais + Options développeur + Adresse Mi Band + Paramètres Pebble + Protocole des notifications en vigueur + Cette option force l\'utilisant du dernier protocole de notification qui dépend de la verrsion du firmware. ACTIVER LA UNIQUEMENT SI VOUS SAVEZ CE QUE VOUS FAITES! + Activités les fonctionnalités non testé + Activer les fonctionnalités non testés + non connecté + en train de se connecter + connecté + état inconnu + HW: %1$s FW: %2$s + FW: %1$s + (inconnu) + Test + Notification de test + Ceci est un test de notification venant de Gadgetbridge + Le bluetooth n\'est pas supporté + Le bluetooth est désactivé + Tapper sur l\'appareil pour le connecter + Ne peut être connecter. L’adresse bluetooth est invalide? + Gadgetbridge est en fonctionnement + faible + moyen + plein + Ne charge pas + Installation du binaire %1$d/%2$d + installation en échec + installation réalisé + VOUS ÊTES EN TRAIN D\'INSTALLER UN FIRMWARE, PROCEDEZ À VOS PROPRES RISQUES. CE FIRMWARE EST POUR LA VERSION HW: %s + N/A + initialisé + %1$s par %2$s + Décourir les appareils + Arreter de scanner + Démarrer le scan + Découvrir l\'appareil + %1$s (%2$s) + Coupler l\'appareil + Utiliser l\'appareillage bluetouth d\'android pour coupler l\'appareil + Coupler votre Mi Band + Coupler avec %s... + Aucune adresse mac fournis, ne peut être couplé + Paramètres spécifique à l\'appareil + Paramètres Mi Band + homme + femme + autre + gauche + droite + Aucune donnée utilisateur valide fournis, utilisation des données fictives pour le moment + Quand votre Mi Band vibre et clignote, appuyez dessus plusieurs fois d\'affilée. + Installer + Rendre votre appareil découvrable. Actuellement les appareils connectés ne seront pas découvert. + Note: + A propos de vous + Nom/Pseudo + Année de naissance + Genre + Taille en cm + Poids en kg + Nombre de vibration + Moniteur de sommeil + Ecrire le fichier de logs (besoin de redemarrer) + iniitialisation + De %1$s à %2$s + Port main gauche ou droite? + Profil de vibration + Saccadé + Court + Moyen + Long + Goute d\'eau + Cycle + Réveil + Vibration + Notification SMS + Paramètres des vibrations + Notification génériques + Notification Pebble + Notification des emails K9 + Notification des appels entrant + Trouver l\'appareil perdu + Annuler pour arreter les vibrations + Votre activité + Configurer les réveils + Configurer les réveils + Détails des alarmes + Dim + Lun + Mar + Mer + Jeu + Ven + Sam + réveil intelligent + Il y avais une erreur lors du paramétrage des alarmes, s\'il vous plaît essayer à nouveau! + Alarmes envoyer à l\'appareil + Aucune donnée. Synchroniser l\'appareil? + A propos du transférer %1$s de données à partir de %2$s + Objectif de pas par jour + Erreur d’exécution %1$s\' + Votre activité (ALPHA) + Impossible de se connecter: %1$s + Impossible de trouver un gestionnaire pour installer ce fichier. + Impossible d\'installer le fichier donné: $1%s + Impossible d\'installer le firmware donnée: il ne correspond pas à la version du matériel de votre Pebble. + S\'il vous plaît patienter pendant la détermination de l\'état de l\'installation ... +