Change the way how device commands or replys to information requests are passed back to the App

This was necessary to pack more complex and more specific information regarding apps etc.
live-sensor-data
Andreas Shimokawa 2015-03-26 12:06:26 +01:00
parent 0ccb818f58
commit 67a5917597
11 changed files with 143 additions and 69 deletions

View File

@ -29,6 +29,13 @@ import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommand;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandAppInfo;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandCallControl;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandMusicControl;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.protocol.PebbleProtocol;
public class BluetoothCommunicationService extends Service { public class BluetoothCommunicationService extends Service {
public static final String ACTION_START public static final String ACTION_START
= "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.start"; = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.start";
@ -117,18 +124,20 @@ public class BluetoothCommunicationService extends Service {
nm.notify(NOTIFICATION_ID, notification); nm.notify(NOTIFICATION_ID, notification);
} }
private void evaluateGBCommandBundle(GBCommandBundle cmdBundle) { private void evaluateGBCommandBundle(GBDeviceCommand deviceCmd) {
switch (cmdBundle.commandClass) { switch (deviceCmd.commandClass) {
case MUSIC_CONTROL: case MUSIC_CONTROL:
Log.i(TAG, "Got command for MUSIC_CONTROL"); Log.i(TAG, "Got command for MUSIC_CONTROL");
GBDeviceCommandMusicControl musicCmd = (GBDeviceCommandMusicControl)deviceCmd;
Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL); Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL);
musicIntent.putExtra("command", cmdBundle.command.ordinal()); musicIntent.putExtra("command", musicCmd.command.ordinal());
sendBroadcast(musicIntent); sendBroadcast(musicIntent);
break; break;
case CALL_CONTROL: case CALL_CONTROL:
Log.i(TAG, "Got command for CALL_CONTROL"); Log.i(TAG, "Got command for CALL_CONTROL");
GBDeviceCommandCallControl callCmd = (GBDeviceCommandCallControl)deviceCmd;
Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL); Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL);
callIntent.putExtra("command", cmdBundle.command.ordinal()); callIntent.putExtra("command", callCmd.command.ordinal());
sendBroadcast(callIntent); sendBroadcast(callIntent);
break; break;
case VERSION_INFO: case VERSION_INFO:
@ -136,17 +145,19 @@ public class BluetoothCommunicationService extends Service {
if (gbdevice == null) { if (gbdevice == null) {
return; return;
} }
gbdevice.setFirmwareVersion(cmdBundle.info[0]); GBDeviceCommandVersionInfo infoCmd = (GBDeviceCommandVersionInfo)deviceCmd;
gbdevice.setFirmwareVersion(infoCmd.fwVersion);
sendDeviceUpdateIntent(); sendDeviceUpdateIntent();
break; break;
case APP_INFO: case APP_INFO:
Log.i(TAG, "Got command for APP_INFO"); Log.i(TAG, "Got command for APP_INFO");
GBDeviceCommandAppInfo appInfoCmd = (GBDeviceCommandAppInfo)deviceCmd;
Intent appInfoIntent = new Intent(AppManagerActivity.ACTION_REFRESH_APPLIST); Intent appInfoIntent = new Intent(AppManagerActivity.ACTION_REFRESH_APPLIST);
int appCount = cmdBundle.info.length / 2; int appCount = appInfoCmd.apps.length;
appInfoIntent.putExtra("app_count", appCount); appInfoIntent.putExtra("app_count", appCount);
for (Integer i = 0; i < appCount; i++) { for (Integer i = 0; i < appCount; i++) {
appInfoIntent.putExtra("app_name" + i.toString(), cmdBundle.info[i * 2]); appInfoIntent.putExtra("app_name" + i.toString(), appInfoCmd.apps[i].getName());
appInfoIntent.putExtra("app_creator" + i.toString(), cmdBundle.info[i * 2 + 1]); appInfoIntent.putExtra("app_creator" + i.toString(), appInfoCmd.apps[i].getCreator());
} }
sendBroadcast(appInfoIntent); sendBroadcast(appInfoIntent);
break; break;
@ -399,11 +410,11 @@ public class BluetoothCommunicationService extends Service {
write(PebbleProtocol.encodePhoneVersion(PebbleProtocol.PHONEVERSION_REMOTE_OS_ANDROID)); write(PebbleProtocol.encodePhoneVersion(PebbleProtocol.PHONEVERSION_REMOTE_OS_ANDROID));
write(PebbleProtocol.encodeFirmwareVersionReq()); write(PebbleProtocol.encodeFirmwareVersionReq());
} else if (endpoint != PebbleProtocol.ENDPOINT_DATALOG) { } else if (endpoint != PebbleProtocol.ENDPOINT_DATALOG) {
GBCommandBundle cmdBundle = PebbleProtocol.decodeResponse(buffer); GBDeviceCommand deviceCmd = PebbleProtocol.decodeResponse(buffer);
if (cmdBundle == null) { if (deviceCmd == null) {
Log.i(TAG, "unhandled message to endpoint " + endpoint + " (" + bytes + " bytes)"); Log.i(TAG, "unhandled message to endpoint " + endpoint + " (" + bytes + " bytes)");
} else { } else {
evaluateGBCommandBundle(cmdBundle); evaluateGBCommandBundle(deviceCmd);
} }
} }
try { try {

View File

@ -10,25 +10,25 @@ import com.android.internal.telephony.ITelephony;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class GBCallControlReceiver extends BroadcastReceiver { import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandCallControl;
private final String TAG = this.getClass().getSimpleName();
public class GBCallControlReceiver extends BroadcastReceiver {
public static final String ACTION_CALLCONTROL = "nodomain.freeyourgadget.gadgetbridge.callcontrol"; public static final String ACTION_CALLCONTROL = "nodomain.freeyourgadget.gadgetbridge.callcontrol";
private final String TAG = this.getClass().getSimpleName();
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
GBCommand command = GBCommand.values()[intent.getIntExtra("command", 0)]; GBDeviceCommandCallControl.Command callCmd = GBDeviceCommandCallControl.Command.values()[intent.getIntExtra("command", 0)];
int keyCode; switch (callCmd) {
switch (command) { case END:
case CALL_END: case START:
case CALL_START:
try { try {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName()); Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony"); Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true); method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager); ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
if (command == GBCommand.CALL_END) { if (callCmd == GBDeviceCommandCallControl.Command.END) {
telephonyService.endCall(); telephonyService.endCall();
} else { } else {
telephonyService.answerRingingCall(); telephonyService.answerRingingCall();

View File

@ -1,8 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge;
public class GBCommandBundle {
public GBCommandClass commandClass;
public GBCommand command;
public String[] info;
}

View File

@ -1,8 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge;
public enum GBCommandClass {
MUSIC_CONTROL,
CALL_CONTROL,
APP_INFO,
VERSION_INFO
}

View File

@ -6,6 +6,8 @@ import android.content.Intent;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.KeyEvent; import android.view.KeyEvent;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandMusicControl;
public class GBMusicControlReceiver extends BroadcastReceiver { public class GBMusicControlReceiver extends BroadcastReceiver {
private final String TAG = this.getClass().getSimpleName(); private final String TAG = this.getClass().getSimpleName();
@ -13,22 +15,22 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
GBCommand command = GBCommand.values()[intent.getIntExtra("command", 0)]; GBDeviceCommandMusicControl.Command musicCmd = GBDeviceCommandMusicControl.Command.values()[intent.getIntExtra("command", 0)];
int keyCode; int keyCode;
switch (command) { switch (musicCmd) {
case MUSIC_NEXT: case NEXT:
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT; keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
break; break;
case MUSIC_PREVIOUS: case PREVIOUS:
keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
break; break;
case MUSIC_PLAY: case PLAY:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
break; break;
case MUSIC_PAUSE: case PAUSE:
keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE; keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE;
break; break;
case MUSIC_PLAYPAUSE: case PLAYPAUSE:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
break; break;
default: default:

View File

@ -0,0 +1,15 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public abstract class GBDeviceCommand {
public CommandClass commandClass = CommandClass.UNKNOWN;
public enum CommandClass {
UNKNOWN,
MUSIC_CONTROL,
CALL_CONTROL,
APP_INFO,
VERSION_INFO
}
}

View File

@ -0,0 +1,11 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
import nodomain.freeyourgadget.gadgetbridge.GBDeviceApp;
public class GBDeviceCommandAppInfo extends GBDeviceCommand {
public GBDeviceApp apps[];
public GBDeviceCommandAppInfo() {
commandClass = CommandClass.APP_INFO;
}
}

View File

@ -0,0 +1,20 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandCallControl extends GBDeviceCommand {
public Command command = Command.UNKNOWN;
public GBDeviceCommandCallControl() {
commandClass = CommandClass.CALL_CONTROL;
}
public enum Command {
UNKNOWN,
ACCEPT,
END,
INCOMING,
OUTGOING,
REJECT,
START,
}
}

View File

@ -0,0 +1,19 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandMusicControl extends GBDeviceCommand {
public Command command = Command.UNKNOWN;
public GBDeviceCommandMusicControl() {
commandClass = CommandClass.MUSIC_CONTROL;
}
public enum Command {
UNKNOWN,
PLAY,
PAUSE,
PLAYPAUSE,
NEXT,
PREVIOUS,
}
}

View File

@ -0,0 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandVersionInfo extends GBDeviceCommand {
public String fwVersion = "N/A";
public String hwVersion = "N/A";
public GBDeviceCommandVersionInfo() {
commandClass = CommandClass.VERSION_INFO;
}
}

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge; package nodomain.freeyourgadget.gadgetbridge.protocol;
import android.util.Log; import android.util.Log;
@ -6,6 +6,9 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import nodomain.freeyourgadget.gadgetbridge.GBCommand;
import nodomain.freeyourgadget.gadgetbridge.GBDeviceApp;
public class PebbleProtocol { public class PebbleProtocol {
static private String TAG = "PebbleProtocol"; static private String TAG = "PebbleProtocol";
@ -13,7 +16,7 @@ public class PebbleProtocol {
static final short ENDPOINT_FIRMWARE = 1; static final short ENDPOINT_FIRMWARE = 1;
static final short ENDPOINT_TIME = 11; static final short ENDPOINT_TIME = 11;
static final short ENDPOINT_FIRMWAREVERSION = 16; static final short ENDPOINT_FIRMWAREVERSION = 16;
static final short ENDPOINT_PHONEVERSION = 17; public static final short ENDPOINT_PHONEVERSION = 17;
static final short ENDPOINT_SYSTEMMESSAGE = 18; static final short ENDPOINT_SYSTEMMESSAGE = 18;
static final short ENDPOINT_MUSICCONTROL = 32; static final short ENDPOINT_MUSICCONTROL = 32;
static final short ENDPOINT_PHONECONTROL = 33; static final short ENDPOINT_PHONECONTROL = 33;
@ -30,7 +33,7 @@ public class PebbleProtocol {
static final short ENDPOINT_SYSREG = 5000; static final short ENDPOINT_SYSREG = 5000;
static final short ENDPOINT_FCTREG = 5001; static final short ENDPOINT_FCTREG = 5001;
static final short ENDPOINT_APPMANAGER = 6000; static final short ENDPOINT_APPMANAGER = 6000;
static final short ENDPOINT_DATALOG = 6778; public static final short ENDPOINT_DATALOG = 6778;
static final short ENDPOINT_RUNKEEPER = 7000; static final short ENDPOINT_RUNKEEPER = 7000;
static final short ENDPOINT_SCREENSHOT = 8000; static final short ENDPOINT_SCREENSHOT = 8000;
static final short ENDPOINT_PUTBYTES = (short) 48879; static final short ENDPOINT_PUTBYTES = (short) 48879;
@ -91,7 +94,7 @@ public class PebbleProtocol {
static final byte PHONEVERSION_REMOTE_OS_UNKNOWN = 0; static final byte PHONEVERSION_REMOTE_OS_UNKNOWN = 0;
static final byte PHONEVERSION_REMOTE_OS_IOS = 1; static final byte PHONEVERSION_REMOTE_OS_IOS = 1;
static final byte PHONEVERSION_REMOTE_OS_ANDROID = 2; public static final byte PHONEVERSION_REMOTE_OS_ANDROID = 2;
static final byte PHONEVERSION_REMOTE_OS_OSX = 3; static final byte PHONEVERSION_REMOTE_OS_OSX = 3;
static final byte PHONEVERSION_REMOTE_OS_LINUX = 4; static final byte PHONEVERSION_REMOTE_OS_LINUX = 4;
static final byte PHONEVERSION_REMOTE_OS_WINDOWS = 5; static final byte PHONEVERSION_REMOTE_OS_WINDOWS = 5;
@ -242,69 +245,69 @@ public class PebbleProtocol {
return buf.array(); return buf.array();
} }
public static GBCommandBundle decodeResponse(byte[] responseData) { public static GBDeviceCommand decodeResponse(byte[] responseData) {
ByteBuffer buf = ByteBuffer.wrap(responseData); ByteBuffer buf = ByteBuffer.wrap(responseData);
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
short length = buf.getShort(); short length = buf.getShort();
short endpoint = buf.getShort(); short endpoint = buf.getShort();
byte pebbleCmd = buf.get(); byte pebbleCmd = buf.get();
GBCommandBundle cmd = new GBCommandBundle(); GBDeviceCommand cmd = null;
switch (endpoint) { switch (endpoint) {
case ENDPOINT_MUSICCONTROL: case ENDPOINT_MUSICCONTROL:
cmd.commandClass = GBCommandClass.MUSIC_CONTROL; GBDeviceCommandMusicControl musicCmd = new GBDeviceCommandMusicControl();
switch (pebbleCmd) { switch (pebbleCmd) {
case MUSICCONTROL_NEXT: case MUSICCONTROL_NEXT:
cmd.command = GBCommand.MUSIC_NEXT; musicCmd.command = GBDeviceCommandMusicControl.Command.NEXT;
break; break;
case MUSICCONTROL_PREVIOUS: case MUSICCONTROL_PREVIOUS:
cmd.command = GBCommand.MUSIC_PREVIOUS; musicCmd.command = GBDeviceCommandMusicControl.Command.PREVIOUS;
break; break;
case MUSICCONTROL_PLAY: case MUSICCONTROL_PLAY:
cmd.command = GBCommand.MUSIC_PLAY; musicCmd.command = GBDeviceCommandMusicControl.Command.PLAY;
break; break;
case MUSICCONTROL_PAUSE: case MUSICCONTROL_PAUSE:
cmd.command = GBCommand.MUSIC_PAUSE; musicCmd.command = GBDeviceCommandMusicControl.Command.PAUSE;
break; break;
case MUSICCONTROL_PLAYPAUSE: case MUSICCONTROL_PLAYPAUSE:
cmd.command = GBCommand.MUSIC_PLAYPAUSE; musicCmd.command = GBDeviceCommandMusicControl.Command.PLAYPAUSE;
break; break;
default: default:
cmd.command = GBCommand.UNDEFINEND;
break; break;
} }
cmd = musicCmd;
break; break;
case ENDPOINT_PHONECONTROL: case ENDPOINT_PHONECONTROL:
cmd.commandClass = GBCommandClass.CALL_CONTROL; GBDeviceCommandCallControl callCmd = new GBDeviceCommandCallControl();
switch (pebbleCmd) { switch (pebbleCmd) {
case PHONECONTROL_HANGUP: case PHONECONTROL_HANGUP:
cmd.command = GBCommand.CALL_END; callCmd.command = GBDeviceCommandCallControl.Command.END;
break; break;
default: default:
Log.i(TAG, "Unknown PHONECONTROL command" + pebbleCmd); Log.i(TAG, "Unknown PHONECONTROL command" + pebbleCmd);
cmd.command = GBCommand.UNDEFINEND;
break; break;
} }
cmd = callCmd;
break; break;
case ENDPOINT_FIRMWAREVERSION: case ENDPOINT_FIRMWAREVERSION:
GBDeviceCommandVersionInfo versionCmd = new GBDeviceCommandVersionInfo();
int version = buf.getInt(); int version = buf.getInt();
byte[] versionString = new byte[32]; byte[] versionString = new byte[32];
buf.get(versionString, 0, 32); buf.get(versionString, 0, 32);
cmd.commandClass = GBCommandClass.VERSION_INFO; versionCmd.fwVersion = new String(versionString).trim();
cmd.command = GBCommand.VERSION_FIRMWARE; Log.i(TAG, "Got firmware version: " + versionCmd.fwVersion);
cmd.info = new String[]{new String(versionString).trim()}; cmd = versionCmd;
Log.i(TAG, "Got firmware version: " + cmd.info);
break; break;
case ENDPOINT_APPMANAGER: case ENDPOINT_APPMANAGER:
cmd.commandClass = GBCommandClass.APP_INFO;
switch (pebbleCmd) { switch (pebbleCmd) {
case APPMANAGER_GETAPPBANKSTATUS: case APPMANAGER_GETAPPBANKSTATUS:
cmd.command = GBCommand.APP_INFO_NAME; GBDeviceCommandAppInfo appInfoCmd = new GBDeviceCommandAppInfo();
int banks = buf.getInt(); int banks = buf.getInt();
int banksUsed = buf.getInt(); int banksUsed = buf.getInt();
byte[] appName = new byte[32]; byte[] appName = new byte[32];
byte[] creatorName = new byte[32]; byte[] creatorName = new byte[32];
cmd.info = new String[banksUsed * 2]; appInfoCmd.apps = new GBDeviceApp[banksUsed];
for (int i = 0; i < banksUsed; i++) { for (int i = 0; i < banksUsed; i++) {
buf.getInt(); // id buf.getInt(); // id
@ -312,14 +315,13 @@ public class PebbleProtocol {
buf.get(appName, 0, 32); buf.get(appName, 0, 32);
buf.get(creatorName, 0, 32); buf.get(creatorName, 0, 32);
int flags = buf.getInt(); int flags = buf.getInt();
short appVersion = buf.getShort(); Short appVersion = buf.getShort();
cmd.info[i * 2] = new String(appName).trim(); appInfoCmd.apps[i] = new GBDeviceApp(new String(appName).trim(), new String(creatorName).trim(), appVersion.toString());
cmd.info[i * 2 + 1] = new String(creatorName).trim();
} }
cmd = appInfoCmd;
break; break;
default: default:
Log.i(TAG, "Unknown APPMANAGER command" + pebbleCmd); Log.i(TAG, "Unknown APPMANAGER command" + pebbleCmd);
cmd.command = GBCommand.UNDEFINEND;
break; break;
} }
break; break;