mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-08-26 17:21:31 +02:00
Mi Watch Lite: Refactor to use XiaomiCharacteristic
This commit is contained in:
parent
84dff5b8df
commit
d953fd5b5b
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.miwatch;
|
package nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.miwatch;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -28,8 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.XiaomiCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.XiaomiCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miwatch.MiWatchLiteSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiPlaintextSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport;
|
|
||||||
|
|
||||||
public class MiWatchLiteCoordinator extends XiaomiCoordinator {
|
public class MiWatchLiteCoordinator extends XiaomiCoordinator {
|
||||||
@Override
|
@Override
|
||||||
@ -62,6 +61,6 @@ public class MiWatchLiteCoordinator extends XiaomiCoordinator {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends DeviceSupport> getDeviceSupportClass() {
|
public Class<? extends DeviceSupport> getDeviceSupportClass() {
|
||||||
return MiWatchLiteSupport.class;
|
return XiaomiPlaintextSupport.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -143,7 +143,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.withingssteelhr.WithingsStee
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.miband8.MiBand8Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.miband8.MiBand8Coordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.zetime.ZeTimeCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.zetime.ZeTimeCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miwatch.MiWatchLiteCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.miwatch.MiWatchLiteCoordinator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For every supported device, a device type constant must exist.
|
* For every supported device, a device type constant must exist.
|
||||||
|
@ -1,151 +0,0 @@
|
|||||||
/* Copyright (C) 2023 Andreas Shimokawa
|
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
|
||||||
|
|
||||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published
|
|
||||||
by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Gadgetbridge is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.miwatch;
|
|
||||||
|
|
||||||
import android.bluetooth.BluetoothGatt;
|
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiAuthService;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
|
||||||
|
|
||||||
public class MiWatchLiteSupport extends XiaomiSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MiWatchLiteSupport.class);
|
|
||||||
|
|
||||||
private static final UUID UUID_CHARACTERISTIC_MAIN = UUID.fromString("16186f02-0000-1000-8000-00807f9b34fb");
|
|
||||||
private static final UUID UUID_CHARACTERISTIC_UNK1 = UUID.fromString("16186f01-0000-1000-8000-00807f9b34fb");
|
|
||||||
private static final UUID UUID_CHARACTERISTIC_UNK2 = UUID.fromString("16186f03-0000-1000-8000-00807f9b34fb");
|
|
||||||
private static final UUID UUID_CHARACTERISTIC_UNK3 = UUID.fromString("16186f04-0000-1000-8000-00807f9b34fb");
|
|
||||||
private static final UUID UUID_CHARACTERISTIC_UNK4 = UUID.fromString("16186f05-0000-1000-8000-00807f9b34fb");
|
|
||||||
|
|
||||||
public MiWatchLiteSupport() {
|
|
||||||
super(); // FIXME: no we do not want to do this!! This adds supported characteristics which we do not have - but we have to.
|
|
||||||
addSupportedService(UUID.fromString("16186f00-0000-1000-8000-00807f9b34fb"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
|
||||||
|
|
||||||
// FIXME why is this needed?
|
|
||||||
getDevice().setFirmwareVersion("...");
|
|
||||||
//getDevice().setFirmwareVersion2("...");
|
|
||||||
enableNotifications(builder, true);
|
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
|
||||||
builder.requestMtu(247);
|
|
||||||
String userId = getUserId(gbDevice);
|
|
||||||
|
|
||||||
final XiaomiProto.Auth auth = XiaomiProto.Auth.newBuilder()
|
|
||||||
.setUserId(userId)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final XiaomiProto.Command command = XiaomiProto.Command.newBuilder()
|
|
||||||
.setType(XiaomiAuthService.COMMAND_TYPE)
|
|
||||||
.setSubtype(XiaomiAuthService.CMD_SEND_USERID)
|
|
||||||
.setAuth(auth)
|
|
||||||
.build();
|
|
||||||
sendCommand(builder, command);
|
|
||||||
|
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
|
|
||||||
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableNotifications(TransactionBuilder builder, boolean enable) {
|
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_MAIN), enable);
|
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_UNK1), enable);
|
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_UNK2), enable);
|
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_UNK3), enable);
|
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_UNK4), enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String getUserId(final GBDevice device) {
|
|
||||||
final SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress());
|
|
||||||
|
|
||||||
final String authKey = sharedPrefs.getString("authkey", null);
|
|
||||||
if (StringUtils.isNotBlank(authKey)) {
|
|
||||||
return authKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "0000000000";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendCommand(final TransactionBuilder builder, final nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto.Command command) {
|
|
||||||
final byte[] commandBytes = command.toByteArray();
|
|
||||||
final int commandLength = 2 + commandBytes.length;
|
|
||||||
if (commandLength > getMTU()) {
|
|
||||||
LOG.warn("Command with {} bytes is too large for MTU of {}", commandLength, getMTU());
|
|
||||||
}
|
|
||||||
builder.write(getCharacteristic(UUID_CHARACTERISTIC_MAIN), new byte[]{0x00, 0x00, 0x00, 0x00, 0x01, 0x00});
|
|
||||||
builder.wait(500);
|
|
||||||
|
|
||||||
final ByteBuffer buf = ByteBuffer.allocate(commandLength).order(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
buf.put((byte) 1);
|
|
||||||
buf.put((byte) 0);
|
|
||||||
buf.put(commandBytes);
|
|
||||||
LOG.debug("Sending command {} as {}", GB.hexdump(commandBytes), GB.hexdump(buf.array()));
|
|
||||||
builder.write(getCharacteristic(UUID_CHARACTERISTIC_MAIN), buf.array());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
|
||||||
BluetoothGattCharacteristic characteristic) {
|
|
||||||
if (super.onCharacteristicChanged(gatt, characteristic)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID characteristicUUID = characteristic.getUuid();
|
|
||||||
|
|
||||||
final byte[] success_bytes = new byte[]{0x00, 0x00, 0x01, 0x01, 0x00, 0x00};
|
|
||||||
final byte[] ping_request = new byte[]{0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
|
|
||||||
if (characteristicUUID.equals(UUID_CHARACTERISTIC_UNK1)) {
|
|
||||||
if (Arrays.equals(ping_request, characteristic.getValue())) {
|
|
||||||
TransactionBuilder builder = new TransactionBuilder("reply ping");
|
|
||||||
builder.write(getCharacteristic(UUID_CHARACTERISTIC_UNK1), new byte[]{0x00, 0x00, 0x01, 0x01});
|
|
||||||
builder.queue(getQueue());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (ArrayUtils.startsWith(characteristic.getValue(), new byte[]{1, 0, 8})) {
|
|
||||||
TransactionBuilder builder = new TransactionBuilder("ack whatever");
|
|
||||||
builder.write(getCharacteristic(UUID_CHARACTERISTIC_UNK1), new byte[]{0x00, 0x00, 0x01, 0x00});
|
|
||||||
builder.queue(getQueue());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,8 +38,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
|||||||
|
|
||||||
public class XiaomiCharacteristic {
|
public class XiaomiCharacteristic {
|
||||||
public static final byte[] PAYLOAD_ACK = new byte[]{0, 0, 3, 0};
|
public static final byte[] PAYLOAD_ACK = new byte[]{0, 0, 3, 0};
|
||||||
public static final byte[] PAYLOAD_CHUNKED_START_ACK = new byte[]{0, 0, 1, 1};
|
|
||||||
public static final byte[] PAYLOAD_CHUNKED_END_ACK = new byte[]{0, 0, 1, 0};
|
|
||||||
|
|
||||||
private final Logger LOG;
|
private final Logger LOG;
|
||||||
|
|
||||||
@ -301,13 +299,13 @@ public class XiaomiCharacteristic {
|
|||||||
|
|
||||||
private void sendChunkStartAck() {
|
private void sendChunkStartAck() {
|
||||||
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked start ack");
|
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked start ack");
|
||||||
builder.write(bluetoothGattCharacteristic, PAYLOAD_CHUNKED_START_ACK);
|
builder.write(bluetoothGattCharacteristic, new byte[]{0x00, 0x00, 0x01, 0x01});
|
||||||
builder.queue(mSupport.getQueue());
|
builder.queue(mSupport.getQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendChunkEndAck() {
|
private void sendChunkEndAck() {
|
||||||
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked end ack");
|
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked end ack");
|
||||||
builder.write(bluetoothGattCharacteristic, PAYLOAD_CHUNKED_END_ACK);
|
builder.write(bluetoothGattCharacteristic, new byte[]{0x00, 0x00, 0x01, 0x00});
|
||||||
builder.queue(mSupport.getQueue());
|
builder.queue(mSupport.getQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,12 +68,13 @@ public class XiaomiEncryptedSupport extends XiaomiSupport {
|
|||||||
final BluetoothGattCharacteristic btCharacteristicActivityData = getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_ACTIVITY_DATA);
|
final BluetoothGattCharacteristic btCharacteristicActivityData = getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_ACTIVITY_DATA);
|
||||||
final BluetoothGattCharacteristic btCharacteristicDataUpload = getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_DATA_UPLOAD);
|
final BluetoothGattCharacteristic btCharacteristicDataUpload = getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_DATA_UPLOAD);
|
||||||
|
|
||||||
if (btCharacteristicCommandRead == null || btCharacteristicCommandWrite == null || btCharacteristicActivityData == null || btCharacteristicDataUpload == null) {
|
if (btCharacteristicCommandRead == null || btCharacteristicCommandWrite == null) {
|
||||||
LOG.warn("Characteristics are null, will attempt to reconnect");
|
LOG.warn("Characteristics are null, will attempt to reconnect");
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.WAITING_FOR_RECONNECT, getContext()));
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.WAITING_FOR_RECONNECT, getContext()));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO move this initialization to upstream class
|
||||||
this.characteristicCommandRead = new XiaomiCharacteristic(this, btCharacteristicCommandRead, authService);
|
this.characteristicCommandRead = new XiaomiCharacteristic(this, btCharacteristicCommandRead, authService);
|
||||||
this.characteristicCommandRead.setEncrypted(true);
|
this.characteristicCommandRead.setEncrypted(true);
|
||||||
this.characteristicCommandRead.setHandler(this::handleCommandBytes);
|
this.characteristicCommandRead.setHandler(this::handleCommandBytes);
|
||||||
@ -96,6 +97,7 @@ public class XiaomiEncryptedSupport extends XiaomiSupport {
|
|||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_COMMAND_WRITE), true);
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_COMMAND_WRITE), true);
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_ACTIVITY_DATA), true);
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_ACTIVITY_DATA), true);
|
||||||
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_DATA_UPLOAD), true);
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_XIAOMI_DATA_UPLOAD), true);
|
||||||
|
|
||||||
authService.startEncryptedHandshake(builder);
|
authService.startEncryptedHandshake(builder);
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
/* Copyright (C) 2023 Andreas Shimokawa
|
||||||
|
|
||||||
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Gadgetbridge is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
|
public class XiaomiPlaintextSupport extends XiaomiSupport {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(XiaomiPlaintextSupport.class);
|
||||||
|
|
||||||
|
private static final UUID UUID_CHARACTERISTIC_MAIN_READ = UUID.fromString("16186f01-0000-1000-8000-00807f9b34fb");
|
||||||
|
private static final UUID UUID_CHARACTERISTIC_MAIN_WRITE = UUID.fromString("16186f02-0000-1000-8000-00807f9b34fb");
|
||||||
|
private static final UUID UUID_CHARACTERISTIC_ACTIVITY_DATA = UUID.fromString("16186f03-0000-1000-8000-00807f9b34fb");
|
||||||
|
private static final UUID UUID_CHARACTERISTIC_DATA_UPLOAD = UUID.fromString("16186f04-0000-1000-8000-00807f9b34fb");
|
||||||
|
private static final UUID UUID_CHARACTERISTIC_UNK5 = UUID.fromString("16186f05-0000-1000-8000-00807f9b34fb");
|
||||||
|
|
||||||
|
public XiaomiPlaintextSupport() {
|
||||||
|
super();
|
||||||
|
addSupportedService(UUID.fromString("16186f00-0000-1000-8000-00807f9b34fb"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
||||||
|
final BluetoothGattCharacteristic btCharacteristicCommandRead = getCharacteristic(UUID_CHARACTERISTIC_MAIN_READ);
|
||||||
|
final BluetoothGattCharacteristic btCharacteristicCommandWrite = getCharacteristic(UUID_CHARACTERISTIC_MAIN_WRITE);
|
||||||
|
final BluetoothGattCharacteristic btCharacteristicActivityData = getCharacteristic(UUID_CHARACTERISTIC_ACTIVITY_DATA);
|
||||||
|
final BluetoothGattCharacteristic btCharacteristicDataUpload = getCharacteristic(UUID_CHARACTERISTIC_DATA_UPLOAD);
|
||||||
|
|
||||||
|
if (btCharacteristicCommandRead == null || btCharacteristicCommandWrite == null) {
|
||||||
|
LOG.warn("Characteristics are null, will attempt to reconnect");
|
||||||
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.WAITING_FOR_RECONNECT, getContext()));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO move this initialization to upstream class
|
||||||
|
this.characteristicCommandRead = new XiaomiCharacteristic(this, btCharacteristicCommandRead, authService);
|
||||||
|
this.characteristicCommandRead.setEncrypted(false);
|
||||||
|
this.characteristicCommandRead.setHandler(this::handleCommandBytes);
|
||||||
|
this.characteristicCommandWrite = new XiaomiCharacteristic(this, btCharacteristicCommandWrite, authService);
|
||||||
|
this.characteristicCommandRead.setEncrypted(false);
|
||||||
|
this.characteristicActivityData = new XiaomiCharacteristic(this, btCharacteristicActivityData, authService);
|
||||||
|
this.characteristicActivityData.setHandler(healthService.getActivityFetcher()::addChunk);
|
||||||
|
this.characteristicCommandRead.setEncrypted(false);
|
||||||
|
this.characteristicDataUpload = new XiaomiCharacteristic(this, btCharacteristicDataUpload, authService);
|
||||||
|
this.characteristicCommandRead.setEncrypted(false);
|
||||||
|
|
||||||
|
// FIXME why is this needed?
|
||||||
|
getDevice().setFirmwareVersion("...");
|
||||||
|
//getDevice().setFirmwareVersion2("...");
|
||||||
|
|
||||||
|
enableNotifications(builder, true);
|
||||||
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||||
|
builder.requestMtu(247);
|
||||||
|
String userId = getUserId(gbDevice);
|
||||||
|
|
||||||
|
final XiaomiProto.Auth auth = XiaomiProto.Auth.newBuilder()
|
||||||
|
.setUserId(userId)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final XiaomiProto.Command command = XiaomiProto.Command.newBuilder()
|
||||||
|
.setType(XiaomiAuthService.COMMAND_TYPE)
|
||||||
|
.setSubtype(XiaomiAuthService.CMD_SEND_USERID)
|
||||||
|
.setAuth(auth)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
sendCommand(builder, command);
|
||||||
|
|
||||||
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
|
||||||
|
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableNotifications(TransactionBuilder builder, boolean enable) {
|
||||||
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_MAIN_WRITE), enable);
|
||||||
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_MAIN_READ), enable);
|
||||||
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_ACTIVITY_DATA), enable);
|
||||||
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_DATA_UPLOAD), enable);
|
||||||
|
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_UNK5), enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getUserId(final GBDevice device) {
|
||||||
|
final SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress());
|
||||||
|
|
||||||
|
final String authKey = sharedPrefs.getString("authkey", null);
|
||||||
|
if (StringUtils.isNotBlank(authKey)) {
|
||||||
|
return authKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0000000000";
|
||||||
|
}
|
||||||
|
}
|
@ -394,12 +394,14 @@ public abstract class XiaomiSupport extends AbstractBTLEDeviceSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendCommand(final TransactionBuilder builder, final XiaomiProto.Command command) {
|
public void sendCommand(final TransactionBuilder builder, final XiaomiProto.Command command) {
|
||||||
|
// FIXME builder is ignored
|
||||||
final byte[] commandBytes = command.toByteArray();
|
final byte[] commandBytes = command.toByteArray();
|
||||||
LOG.debug("Sending command {}", GB.hexdump(commandBytes));
|
LOG.debug("Sending command {}", GB.hexdump(commandBytes));
|
||||||
this.characteristicCommandWrite.write(commandBytes);
|
this.characteristicCommandWrite.write(commandBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendCommand(final TransactionBuilder builder, final byte[] commandBytes) {
|
public void sendCommand(final TransactionBuilder builder, final byte[] commandBytes) {
|
||||||
|
// FIXME builder is ignored
|
||||||
this.characteristicCommandWrite.write(commandBytes);
|
this.characteristicCommandWrite.write(commandBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user