mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-01 14:32:54 +01:00
Pebble: work towards PebbleKit support #106
- Untested features have to be turned on. - We will accept data from any source. - One way, we do not send out replies. This already works with the minimalistic sports demo from the sdk
This commit is contained in:
parent
d3dbde6917
commit
9a32be97cb
@ -3,12 +3,17 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
|||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothSocket;
|
import android.bluetooth.BluetoothSocket;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -20,6 +25,7 @@ import java.net.InetAddress;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
@ -38,6 +44,18 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
|||||||
|
|
||||||
public class PebbleIoThread extends GBDeviceIoThread {
|
public class PebbleIoThread extends GBDeviceIoThread {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
|
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
|
||||||
|
|
||||||
|
public static final String PEBBLEKIT_ACTION_PEBBLE_CONNECTED = "com.getpebble.action.PEBBLE_CONNECTED";
|
||||||
|
public static final String PEBBLEKIT_ACTION_PEBBLE_DISCONNECTED = "com.getpebble.action.PEBBLE_DISCONNECTED";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_ACK = "com.getpebble.action.app.ACK";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_NACK = "com.getpebble.action.app.NACK";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_RECEIVE = "com.getpebble.action.app.RECEIVE";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_RECEIVE_ACK = "com.getpebble.action.app.RECEIVE_ACK";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_RECEIVE_NACK = "com.getpebble.action.app.RECEIVE_NACK";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_SEND = "com.getpebble.action.app.SEND";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_START = "com.getpebble.action.app.START";
|
||||||
|
public static final String PEBBLEKIT_ACTION_APP_STOP = "com.getpebble.action.app.STOP";
|
||||||
|
|
||||||
private final PebbleProtocol mPebbleProtocol;
|
private final PebbleProtocol mPebbleProtocol;
|
||||||
private final PebbleSupport mPebbleSupport;
|
private final PebbleSupport mPebbleSupport;
|
||||||
private boolean mIsTCP = false;
|
private boolean mIsTCP = false;
|
||||||
@ -62,6 +80,35 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
private int mBinarySize = -1;
|
private int mBinarySize = -1;
|
||||||
private int mBytesWritten = -1;
|
private int mBytesWritten = -1;
|
||||||
|
|
||||||
|
private final BroadcastReceiver mPebbleKitReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
LOG.info("Got action: " + action);
|
||||||
|
UUID uuid;
|
||||||
|
switch (action) {
|
||||||
|
case PEBBLEKIT_ACTION_APP_START:
|
||||||
|
uuid = (UUID) intent.getSerializableExtra("uuid");
|
||||||
|
if (uuid != null) {
|
||||||
|
write(mPebbleProtocol.encodeAppStart(uuid));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PEBBLEKIT_ACTION_APP_SEND:
|
||||||
|
uuid = (UUID) intent.getSerializableExtra("uuid");
|
||||||
|
String jsonString = intent.getStringExtra("msg_data");
|
||||||
|
LOG.info("json string: " + jsonString);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONArray jsonArray = new JSONArray(jsonString);
|
||||||
|
write(mPebbleProtocol.encodeApplicationMessageFromJSON(uuid, jsonArray));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public PebbleIoThread(PebbleSupport pebbleSupport, GBDevice gbDevice, GBDeviceProtocol gbDeviceProtocol, BluetoothAdapter btAdapter, Context context) {
|
public PebbleIoThread(PebbleSupport pebbleSupport, GBDevice gbDevice, GBDeviceProtocol gbDeviceProtocol, BluetoothAdapter btAdapter, Context context) {
|
||||||
super(gbDevice, context);
|
super(gbDevice, context);
|
||||||
mPebbleProtocol = (PebbleProtocol) gbDeviceProtocol;
|
mPebbleProtocol = (PebbleProtocol) gbDeviceProtocol;
|
||||||
@ -116,6 +163,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||||
|
|
||||||
mIsConnected = connect(gbDevice.getAddress());
|
mIsConnected = connect(gbDevice.getAddress());
|
||||||
|
enablePebbleKitReceiver(mIsConnected);
|
||||||
mQuit = !mIsConnected; // quit if not connected
|
mQuit = !mIsConnected; // quit if not connected
|
||||||
|
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
@ -285,11 +333,43 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enablePebbleKitReceiver(false);
|
||||||
mBtSocket = null;
|
mBtSocket = null;
|
||||||
gbDevice.setState(GBDevice.State.NOT_CONNECTED);
|
gbDevice.setState(GBDevice.State.NOT_CONNECTED);
|
||||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enablePebbleKitReceiver(boolean enable) {
|
||||||
|
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean force_untested = sharedPrefs.getBoolean("pebble_force_untested", false);
|
||||||
|
|
||||||
|
if (enable && force_untested) {
|
||||||
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_ACK);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_NACK);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_RECEIVE);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_RECEIVE_ACK);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_RECEIVE_NACK);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_SEND);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_START);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_APP_STOP);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_PEBBLE_CONNECTED);
|
||||||
|
intentFilter.addAction(PEBBLEKIT_ACTION_PEBBLE_DISCONNECTED);
|
||||||
|
try {
|
||||||
|
getContext().registerReceiver(mPebbleKitReceiver, intentFilter);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
getContext().unregisterReceiver(mPebbleKitReceiver);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void write_real(byte[] bytes) {
|
private void write_real(byte[] bytes) {
|
||||||
try {
|
try {
|
||||||
if (mIsTCP) {
|
if (mIsTCP) {
|
||||||
|
@ -2,6 +2,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
|||||||
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -13,8 +16,6 @@ import java.util.Random;
|
|||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement;
|
||||||
@ -24,9 +25,11 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificati
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||||
|
|
||||||
public class PebbleProtocol extends GBDeviceProtocol {
|
public class PebbleProtocol extends GBDeviceProtocol {
|
||||||
@ -1173,6 +1176,26 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
return buf.array();
|
return buf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] encodeApplicationMessageFromJSON(UUID uuid, JSONArray jsonArray) {
|
||||||
|
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>();
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
|
||||||
|
String type = (String) jsonObject.get("type");
|
||||||
|
int key = (int) jsonObject.get("key");
|
||||||
|
if (type.equals("uint") || type.equals("int")) {
|
||||||
|
pairs.add(new Pair<>(key, (Object) jsonObject.getInt("value")));
|
||||||
|
} else if (type.equals("string")) {
|
||||||
|
pairs.add(new Pair<>(key, (Object) jsonObject.getString("value")));
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeApplicationMessagePush(ENDPOINT_APPLICATIONMESSAGE, uuid, pairs);
|
||||||
|
}
|
||||||
|
|
||||||
private static byte reverseBits(byte in) {
|
private static byte reverseBits(byte in) {
|
||||||
byte out = 0;
|
byte out = 0;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user