mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-07-08 22:51:37 +02:00
SoFlow SO6: First working lock&unlock
needs key
This commit is contained in:
parent
5db9d36d1a
commit
74517f12a3
|
@ -556,6 +556,8 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
|
||||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_RESPONSE_DURING_SCREEN_LIGHTING);
|
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_RESPONSE_DURING_SCREEN_LIGHTING);
|
||||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_LANGUAGE);
|
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_LANGUAGE);
|
||||||
|
|
||||||
|
addPreferenceHandlerFor("lock");
|
||||||
|
|
||||||
String sleepTimeState = prefs.getString(PREF_SLEEP_TIME, PREF_DO_NOT_DISTURB_OFF);
|
String sleepTimeState = prefs.getString(PREF_SLEEP_TIME, PREF_DO_NOT_DISTURB_OFF);
|
||||||
boolean sleepTimeScheduled = sleepTimeState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);
|
boolean sleepTimeScheduled = sleepTimeState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class SoFlowCoordinator extends AbstractBLEDeviceCoordinator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBondingStyle() {
|
public int getBondingStyle() {
|
||||||
return BONDING_STYLE_REQUIRE_KEY;
|
return BONDING_STYLE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,18 +21,17 @@ import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||||
|
@ -47,19 +46,21 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfoProfile;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.CryptoUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
|
|
||||||
public static final UUID UUID_CHARACTERISICS_NOTIFICATION = UUID.fromString("60000002-0000-1000-8000-00805f9b34fb");
|
public static final UUID UUID_CHARACTERISICS_NOTIFICATION = UUID.fromString("60000002-0000-1000-8000-00805f9b34fb");
|
||||||
public static final UUID UUID_CHARACTERISICS_WRITE = UUID.fromString("60000002-0000-1000-8000-00805f9b34fb");
|
public static final UUID UUID_CHARACTERISICS_WRITE = UUID.fromString("60000003-0000-1000-8000-00805f9b34fb");
|
||||||
public static final byte[] COMMAND_REQUEST_SESSION = new byte[]{0x06, 0x01, 0x01, 0x00, 00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
public static final byte[] COMMAND_REQUEST_SESSION = new byte[]{0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
public static final byte[] COMMAND_LOCK = new byte[]{0x05, 0x0c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
public static final byte[] COMMAND_UNLOCK = new byte[]{0x05, 0x01, 0x06, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SoFlowSupport.class);
|
private static final Logger LOG = LoggerFactory.getLogger(SoFlowSupport.class);
|
||||||
private final DeviceInfoProfile<SoFlowSupport> deviceInfoProfile;
|
private final DeviceInfoProfile<SoFlowSupport> deviceInfoProfile;
|
||||||
private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
|
private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
|
||||||
private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo();
|
|
||||||
private final IntentListener mListener = new IntentListener() {
|
private final IntentListener mListener = new IntentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void notify(Intent intent) {
|
public void notify(Intent intent) {
|
||||||
|
@ -70,6 +71,9 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private byte[] aesKey;
|
||||||
|
private byte[] session = new byte[]{0, 0, 0, 0};
|
||||||
|
|
||||||
public SoFlowSupport() {
|
public SoFlowSupport() {
|
||||||
super(LOG);
|
super(LOG);
|
||||||
addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS);
|
addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS);
|
||||||
|
@ -85,9 +89,11 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
|
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
|
||||||
|
aesKey = getSecretKey();
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||||
requestDeviceInfo(builder);
|
requestDeviceInfo(builder);
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISICS_NOTIFICATION), true);
|
builder.notify(getCharacteristic(UUID_CHARACTERISICS_NOTIFICATION), true);
|
||||||
|
writeEncrypted(builder, COMMAND_REQUEST_SESSION);
|
||||||
setInitialized(builder);
|
setInitialized(builder);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +107,13 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeEncrypted(TransactionBuilder builder, byte[] data) {
|
||||||
|
try {
|
||||||
|
builder.write(getCharacteristic(UUID_CHARACTERISICS_WRITE), CryptoUtils.encryptAES(data, aesKey));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("error while encrypting data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useAutoConnect() {
|
public boolean useAutoConnect() {
|
||||||
|
@ -115,27 +128,81 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getSecretKey() {
|
protected byte[] getSecretKey() {
|
||||||
byte[] authKeyBytes = new byte[16];
|
byte[] authKeyBytes;
|
||||||
|
|
||||||
SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||||
|
|
||||||
String authKey = sharedPrefs.getString("authkey", null);
|
String authKey = sharedPrefs.getString("authkey", null);
|
||||||
if (authKey != null && !authKey.isEmpty()) {
|
if (authKey != null && !authKey.isEmpty()) {
|
||||||
authKey = authKey.trim();
|
authKey = authKey.trim();
|
||||||
byte[] srcBytes = authKey.getBytes();
|
if (authKey.length() == 34 && authKey.startsWith("0x")) {
|
||||||
if (authKey.length() == 34 && authKey.substring(0, 2).equals("0x")) {
|
authKeyBytes = GB.hexStringToByteArray(authKey.substring(2));
|
||||||
srcBytes = GB.hexStringToByteArray(authKey.substring(2));
|
|
||||||
} else if (authKey.length() == 32) {
|
} else if (authKey.length() == 32) {
|
||||||
srcBytes = GB.hexStringToByteArray(authKey);
|
authKeyBytes = GB.hexStringToByteArray(authKey);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
System.arraycopy(srcBytes, 0, authKeyBytes, 0, Math.min(srcBytes.length, 16));
|
|
||||||
return authKeyBytes;
|
return authKeyBytes;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
||||||
|
BluetoothGattCharacteristic characteristic) {
|
||||||
|
if (super.onCharacteristicChanged(gatt, characteristic)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID characteristicUUID = characteristic.getUuid();
|
||||||
|
if (UUID_CHARACTERISICS_NOTIFICATION.equals(characteristicUUID)) {
|
||||||
|
try {
|
||||||
|
byte[] data = CryptoUtils.decryptAES(characteristic.getValue(), aesKey);
|
||||||
|
if (data[0] == 0x06 && data[1] == 0x01 && data[2] == 0x07) {
|
||||||
|
session[0] = data[3];
|
||||||
|
session[1] = data[4];
|
||||||
|
session[2] = data[5];
|
||||||
|
session[3] = data[6];
|
||||||
|
LOG.info("Got session");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSendConfiguration(String config) {
|
||||||
|
TransactionBuilder builder;
|
||||||
|
try {
|
||||||
|
builder = performInitialized("Sending configuration for option: " + config);
|
||||||
|
if ("lock".equals(config)) {
|
||||||
|
SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||||
|
boolean lock = sharedPrefs.getBoolean("lock", false);
|
||||||
|
if (lock) {
|
||||||
|
COMMAND_LOCK[4] = session[0];
|
||||||
|
COMMAND_LOCK[5] = session[1];
|
||||||
|
COMMAND_LOCK[6] = session[2];
|
||||||
|
COMMAND_LOCK[7] = session[3];
|
||||||
|
writeEncrypted(builder, COMMAND_LOCK);
|
||||||
|
} else {
|
||||||
|
COMMAND_UNLOCK[9] = session[0];
|
||||||
|
COMMAND_UNLOCK[10] = session[1];
|
||||||
|
COMMAND_UNLOCK[11] = session[2];
|
||||||
|
COMMAND_UNLOCK[12] = session[3];
|
||||||
|
writeEncrypted(builder, COMMAND_UNLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.queue(getQueue());
|
||||||
|
} catch (IOException e) {
|
||||||
|
GB.toast("Error setting configuration", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNotification(NotificationSpec notificationSpec) {
|
public void onNotification(NotificationSpec notificationSpec) {
|
||||||
}
|
}
|
||||||
|
@ -266,19 +333,6 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
|
||||||
BluetoothGattCharacteristic characteristic) {
|
|
||||||
if (super.onCharacteristicChanged(gatt, characteristic)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID characteristicUUID = characteristic.getUuid();
|
|
||||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCharacteristicRead(BluetoothGatt gatt,
|
public boolean onCharacteristicRead(BluetoothGatt gatt,
|
||||||
BluetoothGattCharacteristic characteristic, int status) {
|
BluetoothGattCharacteristic characteristic, int status) {
|
||||||
|
@ -291,11 +345,6 @@ public class SoFlowSupport extends AbstractBTLEDeviceSupport {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSendConfiguration(String config) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReadConfiguration(String config) {
|
public void onReadConfiguration(String config) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user