mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-29 05:16:51 +01:00
Pebble: Emulator support
NOTE: - supports aplite and basalt emulator - needs recompilation of Gadgetbridge with INTERNET permission TODO: - fix disconnect issues - emulator special packet support - string localization - ...
This commit is contained in:
parent
121baa19ec
commit
a7796ecbc6
@ -5,7 +5,9 @@
|
|||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="19"
|
android:minSdkVersion="19"
|
||||||
android:targetSdkVersion="21" />
|
android:targetSdkVersion="21" />
|
||||||
|
<!--
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
-->
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
@ -340,13 +340,23 @@ public class ControlCenter extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
String miAddr = sharedPrefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, null);
|
String miAddr = sharedPrefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
|
||||||
if (miAddr != null && miAddr.length() > 0) {
|
if (miAddr.length() > 0) {
|
||||||
GBDevice miDevice = new GBDevice(miAddr, "MI", DeviceType.MIBAND);
|
GBDevice miDevice = new GBDevice(miAddr, "MI", DeviceType.MIBAND);
|
||||||
if (!availableDevices.contains(miDevice)) {
|
if (!availableDevices.contains(miDevice)) {
|
||||||
availableDevices.add(miDevice);
|
availableDevices.add(miDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String pebbleEmuAddr = sharedPrefs.getString("pebble_emu_addr", "");
|
||||||
|
String pebbleEmuPort = sharedPrefs.getString("pebble_emu_port", "");
|
||||||
|
if (pebbleEmuAddr.length() >= 7 && pebbleEmuPort.length() > 0) {
|
||||||
|
GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", DeviceType.PEBBLE);
|
||||||
|
if (!availableDevices.contains(pebbleEmuDevice)) {
|
||||||
|
availableDevices.add(pebbleEmuDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deviceList.retainAll(availableDevices);
|
deviceList.retainAll(availableDevices);
|
||||||
for (GBDevice dev : availableDevices) {
|
for (GBDevice dev : availableDevices) {
|
||||||
if (!deviceList.contains(dev)) {
|
if (!deviceList.contains(dev)) {
|
||||||
|
@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
|
||||||
@ -35,5 +36,37 @@ public class SettingsActivity extends AbstractSettingsActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final Preference pebbleEmuAddr = findPreference("pebble_emu_addr");
|
||||||
|
pebbleEmuAddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||||
|
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(refreshIntent);
|
||||||
|
preference.setSummary(newVal.toString());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
final Preference pebbleEmuPort = findPreference("pebble_emu_port");
|
||||||
|
pebbleEmuPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||||
|
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(refreshIntent);
|
||||||
|
preference.setSummary(newVal.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getPreferenceKeysWithSummary() {
|
||||||
|
return new String[]{
|
||||||
|
"pebble_emu_addr",
|
||||||
|
"pebble_emu_port"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,16 @@ public class DeviceSupportFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized DeviceSupport createDeviceSupport(String deviceAddress) throws GBException {
|
public synchronized DeviceSupport createDeviceSupport(String deviceAddress) throws GBException {
|
||||||
DeviceSupport deviceSupport = createBTDeviceSupport(deviceAddress);
|
DeviceSupport deviceSupport;
|
||||||
|
if (deviceAddress.indexOf(":") == deviceAddress.lastIndexOf(":")) { // only one colon
|
||||||
|
deviceSupport = createTCPDeviceSupport(deviceAddress);
|
||||||
|
} else {
|
||||||
|
deviceSupport = createBTDeviceSupport(deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
if (deviceSupport != null) {
|
if (deviceSupport != null) {
|
||||||
return deviceSupport;
|
return deviceSupport;
|
||||||
}
|
}
|
||||||
// support for other kinds of transports
|
|
||||||
|
|
||||||
// no device found, check transport availability and warn
|
// no device found, check transport availability and warn
|
||||||
checkBtAvailability();
|
checkBtAvailability();
|
||||||
@ -68,4 +73,16 @@ public class DeviceSupportFactory {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DeviceSupport createTCPDeviceSupport(String deviceAddress) throws GBException {
|
||||||
|
try {
|
||||||
|
GBDevice gbDevice = new GBDevice(deviceAddress, "Pebble qemu", DeviceType.PEBBLE); //FIXME, do not hardcode
|
||||||
|
DeviceSupport deviceSupport = new ServiceDeviceSupport(new PebbleSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||||
|
deviceSupport.setContext(gbDevice, mBtAdapter, mContext);
|
||||||
|
return deviceSupport;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new GBException("cannot connect to " + deviceAddress, e); // FIXME: localize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
@ -37,14 +39,17 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
|
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
|
||||||
private final PebbleProtocol mPebbleProtocol;
|
private final PebbleProtocol mPebbleProtocol;
|
||||||
private final PebbleSupport mPebbleSupport;
|
private final PebbleSupport mPebbleSupport;
|
||||||
|
private boolean mIsTCP = false;
|
||||||
private BluetoothAdapter mBtAdapter = null;
|
private BluetoothAdapter mBtAdapter = null;
|
||||||
private BluetoothSocket mBtSocket = null;
|
private BluetoothSocket mBtSocket = null;
|
||||||
|
private Socket mTCPSocket = null; // for emulator
|
||||||
private InputStream mInStream = null;
|
private InputStream mInStream = null;
|
||||||
private OutputStream mOutStream = null;
|
private OutputStream mOutStream = null;
|
||||||
private boolean mQuit = false;
|
private boolean mQuit = false;
|
||||||
private boolean mIsConnected = false;
|
private boolean mIsConnected = false;
|
||||||
private boolean mIsInstalling = false;
|
private boolean mIsInstalling = false;
|
||||||
private int mConnectionAttempts = 0;
|
private int mConnectionAttempts = 0;
|
||||||
|
|
||||||
private PBWReader mPBWReader = null;
|
private PBWReader mPBWReader = null;
|
||||||
private int mAppInstallToken = -1;
|
private int mAppInstallToken = -1;
|
||||||
private ZipInputStream mZis = null;
|
private ZipInputStream mZis = null;
|
||||||
@ -66,14 +71,25 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean connect(String btDeviceAddress) {
|
protected boolean connect(String btDeviceAddress) {
|
||||||
BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(btDeviceAddress);
|
|
||||||
ParcelUuid uuids[] = btDevice.getUuids();
|
|
||||||
GBDevice.State originalState = gbDevice.getState();
|
GBDevice.State originalState = gbDevice.getState();
|
||||||
try {
|
try {
|
||||||
|
// contains only one ":"? then it is addr:port
|
||||||
|
int firstColon = btDeviceAddress.indexOf(":");
|
||||||
|
if (firstColon == btDeviceAddress.lastIndexOf(":")) {
|
||||||
|
mIsTCP = true;
|
||||||
|
InetAddress serverAddr = InetAddress.getByName(btDeviceAddress.substring(0, firstColon));
|
||||||
|
mTCPSocket = new Socket(serverAddr, Integer.parseInt(btDeviceAddress.substring(firstColon + 1)));
|
||||||
|
mInStream = mTCPSocket.getInputStream();
|
||||||
|
mOutStream = mTCPSocket.getOutputStream();
|
||||||
|
} else {
|
||||||
|
mIsTCP = false;
|
||||||
|
BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(btDeviceAddress);
|
||||||
|
ParcelUuid uuids[] = btDevice.getUuids();
|
||||||
mBtSocket = btDevice.createRfcommSocketToServiceRecord(uuids[0].getUuid());
|
mBtSocket = btDevice.createRfcommSocketToServiceRecord(uuids[0].getUuid());
|
||||||
mBtSocket.connect();
|
mBtSocket.connect();
|
||||||
mInStream = mBtSocket.getInputStream();
|
mInStream = mBtSocket.getInputStream();
|
||||||
mOutStream = mBtSocket.getOutputStream();
|
mOutStream = mBtSocket.getOutputStream();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
gbDevice.setState(originalState);
|
gbDevice.setState(originalState);
|
||||||
@ -187,11 +203,14 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mIsTCP) {
|
||||||
|
mInStream.skip(6);
|
||||||
|
}
|
||||||
int bytes = mInStream.read(buffer, 0, 4);
|
int bytes = mInStream.read(buffer, 0, 4);
|
||||||
|
|
||||||
if (bytes < 4) {
|
if (bytes < 4) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.wrap(buffer);
|
ByteBuffer buf = ByteBuffer.wrap(buffer);
|
||||||
buf.order(ByteOrder.BIG_ENDIAN);
|
buf.order(ByteOrder.BIG_ENDIAN);
|
||||||
short length = buf.getShort();
|
short length = buf.getShort();
|
||||||
@ -214,6 +233,10 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
bytes += mInStream.read(buffer, bytes + 4, length - bytes);
|
bytes += mInStream.read(buffer, bytes + 4, length - bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIsTCP) {
|
||||||
|
mInStream.skip(2);
|
||||||
|
}
|
||||||
|
|
||||||
GBDeviceEvent deviceEvent = mPebbleProtocol.decodeResponse(buffer);
|
GBDeviceEvent deviceEvent = mPebbleProtocol.decodeResponse(buffer);
|
||||||
if (deviceEvent == null) {
|
if (deviceEvent == null) {
|
||||||
LOG.info("unhandled message to endpoint " + endpoint + " (" + length + " bytes)");
|
LOG.info("unhandled message to endpoint " + endpoint + " (" + length + " bytes)");
|
||||||
@ -261,15 +284,31 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void write_real(byte[] bytes) {
|
||||||
|
try {
|
||||||
|
if (mIsTCP) {
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(bytes.length + 8);
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
buf.putShort((short) 0xfeed);
|
||||||
|
buf.putShort((short) 1);
|
||||||
|
buf.putShort((short) bytes.length);
|
||||||
|
buf.put(bytes);
|
||||||
|
buf.putShort((short) 0xbeef);
|
||||||
|
mOutStream.write(buf.array());
|
||||||
|
mOutStream.flush();
|
||||||
|
} else {
|
||||||
|
mOutStream.write(bytes);
|
||||||
|
mOutStream.flush();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public void write(byte[] bytes) {
|
synchronized public void write(byte[] bytes) {
|
||||||
// block writes if app installation in in progress
|
// block writes if app installation in in progress
|
||||||
if (mIsConnected && (!mIsInstalling || mInstallState == PebbleAppInstallState.WAIT_SLOT)) {
|
if (mIsConnected && (!mIsInstalling || mInstallState == PebbleAppInstallState.WAIT_SLOT)) {
|
||||||
try {
|
write_real(bytes);
|
||||||
mOutStream.write(bytes);
|
|
||||||
mOutStream.flush();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,13 +410,8 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
if (!mIsInstalling) {
|
if (!mIsInstalling) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int length = bytes.length;
|
LOG.info("got " + bytes.length + "bytes for writeInstallApp()");
|
||||||
LOG.info("got " + length + "bytes for writeInstallApp()");
|
write_real(bytes);
|
||||||
try {
|
|
||||||
mOutStream.write(bytes);
|
|
||||||
mOutStream.flush();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void installApp(Uri uri, int appId) {
|
public void installApp(Uri uri, int appId) {
|
||||||
|
@ -77,6 +77,16 @@
|
|||||||
android:key="pebble_force_untested"
|
android:key="pebble_force_untested"
|
||||||
android:title="@string/pref_title_pebble_forceuntested"
|
android:title="@string/pref_title_pebble_forceuntested"
|
||||||
android:summary="@string/pref_summary_pebble_forceuntested" />
|
android:summary="@string/pref_summary_pebble_forceuntested" />
|
||||||
|
<EditTextPreference
|
||||||
|
android:digits="0123456789."
|
||||||
|
android:key="pebble_emu_addr"
|
||||||
|
android:maxLength="15"
|
||||||
|
android:title="Emulator IP" />
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="pebble_emu_port"
|
||||||
|
android:maxLength="5"
|
||||||
|
android:title="Emulator Port" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
Loading…
Reference in New Issue
Block a user