Pebble: First shot at implementing dataloggin for PebbleKit apps
Closes #497 Could help #316
This commit is contained in:
parent
e5d09b9fa2
commit
946ed5f000
|
@ -0,0 +1,16 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
|
||||
public class GBDeviceEventDataLogging extends GBDeviceEvent {
|
||||
public static final int COMMAND_RECEIVE_DATA = 1;
|
||||
public static final int COMMAND_FINISH_SESSION = 2;
|
||||
|
||||
public int command;
|
||||
public UUID appUUID;
|
||||
public long tag;
|
||||
public byte pebbleDataType;
|
||||
public Object data;
|
||||
}
|
|
@ -1,9 +1,17 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble.GBDeviceEventDataLogging;
|
||||
|
||||
class DatalogSession {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DatalogSession.class);
|
||||
|
||||
final byte id;
|
||||
final int tag;
|
||||
final UUID uuid;
|
||||
|
@ -26,4 +34,38 @@ class DatalogSession {
|
|||
String getTaginfo() {
|
||||
return taginfo;
|
||||
}
|
||||
|
||||
GBDeviceEvent[] handleMessageForPebbleKit(ByteBuffer buf, int length) {
|
||||
if (0 != (length % itemSize)) {
|
||||
LOG.warn("invalid length");
|
||||
return null;
|
||||
}
|
||||
int packetCount = length / itemSize;
|
||||
GBDeviceEvent[] gbDeviceEvents = new GBDeviceEvent[packetCount + 1]; // pad for ack
|
||||
for (int i = 0; i < packetCount; i++) {
|
||||
GBDeviceEventDataLogging dataLogging = new GBDeviceEventDataLogging();
|
||||
switch (itemType) {
|
||||
case PebbleProtocol.TYPE_BYTEARRAY:
|
||||
byte[] itemData = new byte[itemSize];
|
||||
buf.get(itemData);
|
||||
dataLogging.data = itemData;
|
||||
break;
|
||||
|
||||
case PebbleProtocol.TYPE_UINT:
|
||||
dataLogging.data = buf.getInt() & 0xffffffffL;
|
||||
break;
|
||||
|
||||
case PebbleProtocol.TYPE_INT:
|
||||
dataLogging.data = buf.getInt();
|
||||
break;
|
||||
}
|
||||
|
||||
dataLogging.command = GBDeviceEventDataLogging.COMMAND_RECEIVE_DATA;
|
||||
dataLogging.appUUID = uuid;
|
||||
dataLogging.tag = tag;
|
||||
dataLogging.pebbleDataType = itemType;
|
||||
gbDeviceEvents[i] = dataLogging;
|
||||
}
|
||||
return gbDeviceEvents;
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
|||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble.GBDeviceEventDataLogging;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PBWReader;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleInstallable;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
@ -86,6 +87,7 @@ class PebbleIoThread extends GBDeviceIoThread {
|
|||
mPebbleSupport = pebbleSupport;
|
||||
mEnablePebblekit = prefs.getBoolean("pebble_enable_pebblekit", false);
|
||||
mPebbleProtocol.setAlwaysACKPebbleKit(prefs.getBoolean("pebble_always_ack_pebblekit", false));
|
||||
mPebbleProtocol.setEnablePebbleKit(mEnablePebblekit);
|
||||
}
|
||||
|
||||
private int readWithException(InputStream inputStream, byte[] buffer, int byteOffset, int byteCount) throws IOException {
|
||||
|
@ -493,6 +495,13 @@ class PebbleIoThread extends GBDeviceIoThread {
|
|||
mPebbleKitSupport.sendAppMessageIntent((GBDeviceEventAppMessage) deviceEvent);
|
||||
}
|
||||
}
|
||||
} else if (deviceEvent instanceof GBDeviceEventDataLogging) {
|
||||
if (mEnablePebblekit) {
|
||||
LOG.info("Got Datalogging event");
|
||||
if (mPebbleKitSupport != null) {
|
||||
mPebbleKitSupport.sendDataLoggingIntent((GBDeviceEventDataLogging) deviceEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Base64;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -13,6 +14,7 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble.GBDeviceEventDataLogging;
|
||||
|
||||
class PebbleKitSupport {
|
||||
//private static final String PEBBLEKIT_ACTION_PEBBLE_CONNECTED = "com.getpebble.action.PEBBLE_CONNECTED";
|
||||
|
@ -26,12 +28,20 @@ class PebbleKitSupport {
|
|||
private static final String PEBBLEKIT_ACTION_APP_START = "com.getpebble.action.app.START";
|
||||
private static final String PEBBLEKIT_ACTION_APP_STOP = "com.getpebble.action.app.STOP";
|
||||
|
||||
private static final String PEBBLEKIT_ACTION_DL_RECEIVE_DATA_NEW = "com.getpebble.action.dl.RECEIVE_DATA_NEW";
|
||||
private static final String PEBBLEKIT_ACTION_DL_RECEIVE_DATA = "com.getpebble.action.dl.RECEIVE_DATA";
|
||||
private static final String PEBBLEKIT_ACTION_DL_ACK_DATA = "com.getpebble.action.dl.ACK_DATA";
|
||||
private static final String PEBBLEKIT_ACTION_DL_REQUEST_DATA = "com.getpebble.action.dl.REQUEST_DATA";
|
||||
private static final String PEBBLEKIT_ACTION_DL_FINISH_SESSION = "com.getpebble.action.dl.FINISH_SESSION_NEW";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PebbleKitSupport.class);
|
||||
|
||||
private final PebbleProtocol mPebbleProtocol;
|
||||
private final Context mContext;
|
||||
private final PebbleIoThread mPebbleIoThread;
|
||||
|
||||
private int dataLogTransactionId = 1;
|
||||
|
||||
private final BroadcastReceiver mPebbleKitReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -72,6 +82,9 @@ class PebbleKitSupport {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case PEBBLEKIT_ACTION_DL_ACK_DATA:
|
||||
LOG.info("GOT DL DATA ACK");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +101,7 @@ class PebbleKitSupport {
|
|||
intentFilter.addAction(PEBBLEKIT_ACTION_APP_SEND);
|
||||
intentFilter.addAction(PEBBLEKIT_ACTION_APP_START);
|
||||
intentFilter.addAction(PEBBLEKIT_ACTION_APP_STOP);
|
||||
intentFilter.addAction(PEBBLEKIT_ACTION_DL_ACK_DATA);
|
||||
mContext.registerReceiver(mPebbleKitReceiver, intentFilter);
|
||||
}
|
||||
|
||||
|
@ -116,4 +130,40 @@ class PebbleKitSupport {
|
|||
}
|
||||
}
|
||||
|
||||
void sendDataLoggingIntent(GBDeviceEventDataLogging dataLogging) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("data_log_timestamp", System.currentTimeMillis() / 1000); // is this data really not present in data from watch?!
|
||||
intent.putExtra("uuid", dataLogging.appUUID);
|
||||
intent.putExtra("data_log_uuid", dataLogging.appUUID); // Is that really the same?
|
||||
intent.putExtra("data_log_tag", dataLogging.tag);
|
||||
|
||||
switch (dataLogging.command) {
|
||||
case GBDeviceEventDataLogging.COMMAND_RECEIVE_DATA:
|
||||
intent.setAction(PEBBLEKIT_ACTION_DL_RECEIVE_DATA_NEW);
|
||||
intent.putExtra("pbl_data_id", dataLogTransactionId++);
|
||||
intent.putExtra("pbl_data_type", dataLogging.pebbleDataType);
|
||||
switch (dataLogging.pebbleDataType) {
|
||||
case PebbleProtocol.TYPE_BYTEARRAY:
|
||||
intent.putExtra("pbl_data_object", Base64.encodeToString((byte[]) dataLogging.data, Base64.NO_WRAP));
|
||||
break;
|
||||
case PebbleProtocol.TYPE_UINT:
|
||||
intent.putExtra("pbl_data_object", (Long) dataLogging.data);
|
||||
break;
|
||||
case PebbleProtocol.TYPE_INT:
|
||||
intent.putExtra("pbl_data_object", (Integer) dataLogging.data);
|
||||
break;
|
||||
}
|
||||
LOG.info("broadcasting datalogging to uuid " + dataLogging.appUUID + " tag: " + dataLogging.tag + "transaction id: " + dataLogTransactionId + " type: " + dataLogging.pebbleDataType);
|
||||
break;
|
||||
case GBDeviceEventDataLogging.COMMAND_FINISH_SESSION:
|
||||
intent.setAction(PEBBLEKIT_ACTION_DL_FINISH_SESSION);
|
||||
LOG.info("broadcasting datalogging finish session to uuid " + dataLogging.appUUID + " tag: " + dataLogging.tag);
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG.warn("invalid datalog command");
|
||||
return;
|
||||
}
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificati
|
|||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble.GBDeviceEventDataLogging;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
|
@ -224,10 +225,10 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
private static final byte PHONEVERSION_REMOTE_OS_LINUX = 4;
|
||||
private static final byte PHONEVERSION_REMOTE_OS_WINDOWS = 5;
|
||||
|
||||
private static final byte TYPE_BYTEARRAY = 0;
|
||||
static final byte TYPE_BYTEARRAY = 0;
|
||||
private static final byte TYPE_CSTRING = 1;
|
||||
private static final byte TYPE_UINT = 2;
|
||||
private static final byte TYPE_INT = 3;
|
||||
static final byte TYPE_UINT = 2;
|
||||
static final byte TYPE_INT = 3;
|
||||
|
||||
private final short LENGTH_PREFIX = 4;
|
||||
|
||||
|
@ -253,6 +254,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
private static final Random mRandom = new Random();
|
||||
|
||||
int mFwMajor = 3;
|
||||
boolean mEnablePebbleKit = false;
|
||||
boolean mAlwaysACKPebbleKit = false;
|
||||
private boolean mForceProtocol = false;
|
||||
private GBDeviceEventScreenshot mDevEventScreenshot = null;
|
||||
|
@ -2212,10 +2214,11 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
return null;
|
||||
}
|
||||
|
||||
private GBDeviceEventSendBytes decodeDatalog(ByteBuffer buf, short length) {
|
||||
private GBDeviceEvent[] decodeDatalog(ByteBuffer buf, short length) {
|
||||
boolean ack = true;
|
||||
byte command = buf.get();
|
||||
byte id = buf.get();
|
||||
GBDeviceEvent[] devEvts = new GBDeviceEvent[1];
|
||||
switch (command) {
|
||||
case DATALOG_TIMEOUT:
|
||||
LOG.info("DATALOG TIMEOUT. id=" + (id & 0xff) + " - ignoring");
|
||||
|
@ -2228,7 +2231,11 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
LOG.info("DATALOG SENDDATA. id=" + (id & 0xff) + ", items_left=" + items_left + ", total length=" + (length - 10));
|
||||
if (datalogSession != null) {
|
||||
LOG.info("DATALOG UUID=" + datalogSession.uuid + ", tag=" + datalogSession.tag + datalogSession.getTaginfo() + ", itemSize=" + datalogSession.itemSize + ", itemType=" + datalogSession.itemType);
|
||||
ack = datalogSession.handleMessage(buf, length - 10);
|
||||
if (!datalogSession.uuid.equals(UUID_ZERO) && datalogSession.getClass().equals(DatalogSession.class) && mEnablePebbleKit) {
|
||||
devEvts = datalogSession.handleMessageForPebbleKit(buf, length - 10);
|
||||
} else {
|
||||
ack = datalogSession.handleMessage(buf, length - 10);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATALOG_OPENSESSION:
|
||||
|
@ -2255,7 +2262,15 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
break;
|
||||
case DATALOG_CLOSE:
|
||||
LOG.info("DATALOG_CLOSE. id=" + (id & 0xff));
|
||||
if (mDatalogSessions.containsKey(id)) {
|
||||
datalogSession = mDatalogSessions.get(id);
|
||||
if (datalogSession != null) {
|
||||
if (!datalogSession.uuid.equals(UUID_ZERO) && datalogSession.getClass().equals(DatalogSession.class) && mEnablePebbleKit) {
|
||||
GBDeviceEventDataLogging dataLogging = new GBDeviceEventDataLogging();
|
||||
dataLogging.command = GBDeviceEventDataLogging.COMMAND_FINISH_SESSION;
|
||||
dataLogging.appUUID = datalogSession.uuid;
|
||||
dataLogging.tag = datalogSession.tag;
|
||||
devEvts = new GBDeviceEvent[]{dataLogging, null};
|
||||
}
|
||||
mDatalogSessions.remove(id);
|
||||
}
|
||||
break;
|
||||
|
@ -2271,7 +2286,9 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
LOG.info("sending NACK (0x86)");
|
||||
sendBytes.encodedBytes = encodeDatalog(id, DATALOG_NACK);
|
||||
}
|
||||
return sendBytes;
|
||||
// append ack/nack
|
||||
devEvts[devEvts.length - 1] = sendBytes;
|
||||
return devEvts;
|
||||
}
|
||||
|
||||
private GBDeviceEvent decodeAppReorder(ByteBuffer buf) {
|
||||
|
@ -2539,7 +2556,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
break;
|
||||
case ENDPOINT_DATALOG:
|
||||
devEvts = new GBDeviceEvent[]{decodeDatalog(buf, length)};
|
||||
devEvts = decodeDatalog(buf, length);
|
||||
break;
|
||||
case ENDPOINT_SCREENSHOT:
|
||||
devEvts = new GBDeviceEvent[]{decodeScreenshot(buf, length)};
|
||||
|
@ -2587,10 +2604,15 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
|
||||
void setAlwaysACKPebbleKit(boolean alwaysACKPebbleKit) {
|
||||
LOG.info("setting always ACK Pebbleit to " + alwaysACKPebbleKit);
|
||||
LOG.info("setting always ACK PebbleKit to " + alwaysACKPebbleKit);
|
||||
mAlwaysACKPebbleKit = alwaysACKPebbleKit;
|
||||
}
|
||||
|
||||
void setEnablePebbleKit(boolean enablePebbleKit) {
|
||||
LOG.info("setting enable PebbleKit support to " + enablePebbleKit);
|
||||
mEnablePebbleKit = enablePebbleKit;
|
||||
}
|
||||
|
||||
private String getFixedString(ByteBuffer buf, int length) {
|
||||
byte[] tmp = new byte[length];
|
||||
buf.get(tmp, 0, length);
|
||||
|
|
Loading…
Reference in New Issue