From b902ee96c3c349ba23e915353dc9b8c21bac0989 Mon Sep 17 00:00:00 2001 From: MrYoranimo Date: Wed, 6 Dec 2023 01:02:11 +0100 Subject: [PATCH] Xiaomi: improve battery level and charger status processing Because the reporting of battery state is inconsistent between different models, the device's battery state was not correctly processed in GB. For at least the firmware on the Xiaomi Watch S1 Active, the charger state is broadcast through a separate message from the message containing the battery level. Even though the battery level was requested by GB upon receiving this broadcast, the charger state got discarded as it was expected to also be included in the result of the subsequent request. This patch changes the name of the `Charger` message to `DeviceState` and includes more fields that may be presented by some device models. Furthemore, the broadcast is cached so that the charger state can be processed from this cache instead of the battery level response message. --- .../xiaomi/services/XiaomiSystemService.java | 23 +++++++++++++++---- app/src/main/proto/xiaomi.proto | 15 +++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiSystemService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiSystemService.java index fae2b7cb8..313d84165 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiSystemService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiSystemService.java @@ -74,10 +74,11 @@ public class XiaomiSystemService extends AbstractXiaomiService implements Xiaomi public static final int CMD_PASSWORD_SET = 21; public static final int CMD_DISPLAY_ITEMS_GET = 29; public static final int CMD_DISPLAY_ITEMS_SET = 30; - public static final int CMD_CHARGER = 79; + public static final int CMD_DEVICE_STATE = 79; // Not null if we're installing a firmware private XiaomiFWHelper fwHelper = null; + private XiaomiProto.DeviceState cachedDeviceState = null; public XiaomiSystemService(final XiaomiSupport support) { super(support); @@ -129,8 +130,13 @@ public class XiaomiSystemService extends AbstractXiaomiService implements Xiaomi case CMD_DISPLAY_ITEMS_GET: handleDisplayItems(cmd.getSystem().getDisplayItems()); return; - case CMD_CHARGER: - // charger event, request battery state + case CMD_DEVICE_STATE: + // some devices (e.g. Xiaomi Watch S1 Active) only broadcast the charger state through + // this message, so this will need to be kept cached to process when the battery levels + // get requested + cachedDeviceState = cmd.getSystem().getDeviceState(); + + // request battery state to request battery level and charger state on supported models getSupport().sendCommand("request battery state", COMMAND_TYPE, CMD_BATTERY); return; } @@ -250,7 +256,16 @@ public class XiaomiSystemService extends AbstractXiaomiService implements Xiaomi final GBDeviceEventBatteryInfo batteryInfo = new GBDeviceEventBatteryInfo(); batteryInfo.batteryIndex = 0; batteryInfo.level = battery.getLevel(); - switch (battery.getState()) { + + int chargerState = battery.getState(); + + // if device state is cached and the charging state there is set, take the charger status + // from there + if (cachedDeviceState != null && cachedDeviceState.hasChargingState()) { + chargerState = cachedDeviceState.getChargingState(); + } + + switch (chargerState) { case 1: batteryInfo.state = BatteryState.BATTERY_CHARGING; break; diff --git a/app/src/main/proto/xiaomi.proto b/app/src/main/proto/xiaomi.proto index ce3abe326..e3c49081b 100644 --- a/app/src/main/proto/xiaomi.proto +++ b/app/src/main/proto/xiaomi.proto @@ -130,7 +130,7 @@ message System { optional VibrationPatternAck vibrationPatternAck = 43; // 2, 79 - optional Charger charger = 49; + optional DeviceState deviceState = 49; } message Power { @@ -299,8 +299,17 @@ message Vibration { optional uint32 ms = 2; } -message Charger { - optional uint32 state = 1; // 1 charging, 2 not charging +message DeviceActivityState { + optional uint32 activityType = 1; + optional uint32 currentActivityState = 2; +} + +message DeviceState { + optional uint32 chargingState = 1; // 1 charging, 2 not charging + optional uint32 wearingState = 2; // 1 wearing, 2 not wearing + optional uint32 sleepState = 3; // 1 sleep detected, 2 no sleep detected + optional uint32 warningState = 4; // ? + optional DeviceActivityState activityState = 5; } //