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.
live-activity-data
Andreas Shimokawa 2015-08-27 15:02:29 +02:00
parent 027e6fe8c3
commit 44c7f99c58
6 changed files with 104 additions and 90 deletions

View File

@ -33,7 +33,7 @@ public class GadgetbridgePblSupport {
mPebbleProtocol = pebbleProtocol;
}
public GBDeviceEvent handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
int timestamp = 0;
for (Pair<Integer, Object> 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};
}
}

View File

@ -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<Pair<Integer, Object>> pairs = new ArrayList<>();
pairs.add(new Pair<Integer, Object>(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<Pair<Integer, Object>> pairs) {
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
int ctrl_message = 0;
GBDeviceEventSleepMonitorResult sleepMonitorResult = null;
for (Pair<Integer, Object> 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};
}
}

View File

@ -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 {

View File

@ -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<Pair<Integer, Object>> dict = decodeDict(buf);
devEvt = mWeatherNeatSupport.handleMessage(dict);
devEvts = mWeatherNeatSupport.handleMessage(dict);
} else if (MorpheuzSupport.uuid.equals(uuid)) {
ArrayList<Pair<Integer, Object>> dict = decodeDict(buf);
devEvt = mMorpheuzSupport.handleMessage(dict);
devEvts = mMorpheuzSupport.handleMessage(dict);
} else if (GadgetbridgePblSupport.uuid.equals(uuid)) {
ArrayList<Pair<Integer, Object>> 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) {

View File

@ -48,9 +48,9 @@ public class WeatherNeatSupport {
return buf.array();
}
public GBDeviceEvent handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes();
sendBytes.encodedBytes = encodeWeatherNeatMessage("Berlin", "22 C", "cloudy", 0);
return sendBytes;
return new GBDeviceEvent[] {sendBytes};
}
}

View File

@ -63,7 +63,7 @@ public abstract class GBDeviceProtocol {
return null;
}
public GBDeviceEvent decodeResponse(byte[] responseData) {
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
return null;
}
}