From 8531cfb0a1d9cce894bcc2c5ee9417d7fafa2dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Fri, 6 Oct 2023 09:32:22 +0100 Subject: [PATCH] Mi Band 8: Start handling config changes --- .../service/AbstractDeviceSupport.java | 6 ++ .../service/devices/xiaomi/XiaomiSupport.java | 26 ++++-- .../services/AbstractXiaomiService.java | 10 +++ .../xiaomi/services/XiaomiHealthService.java | 32 ++++++- .../xiaomi/services/XiaomiMusicService.java | 10 ++- .../xiaomi/services/XiaomiSystemService.java | 90 ++++++++++++------- 6 files changed, 129 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index 244b40949..78b1c1d87 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -97,6 +97,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlRecei import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID; import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_ID; @@ -558,6 +559,11 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { LocalBroadcastManager.getInstance(context).sendBroadcast(messageIntent); } + protected Prefs getDevicePrefs() { + return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())); + } + + @Override public String customStringFilter(String inputString) { return inputString; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java index 48e9523da..be4583572 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java @@ -24,7 +24,6 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.content.Context; import android.location.Location; import android.net.Uri; -import android.widget.Toast; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; @@ -65,6 +64,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.Xiao import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiSystemService; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiWeatherService; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class XiaomiSupport extends AbstractBTLEDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(XiaomiSupport.class); @@ -211,10 +211,16 @@ public class XiaomiSupport extends AbstractBTLEDeviceSupport { @Override public void onSendConfiguration(final String config) { - // TODO - // TODO user info - // TODO 24h - GB.toast("Error setting configuration", Toast.LENGTH_LONG, GB.ERROR); + final Prefs prefs = getDevicePrefs(); + + // Check if any of the services handles this config + for (final AbstractXiaomiService service : mServiceMap.values()) { + if (service.onSendConfiguration(config, prefs)) { + return; + } + } + + LOG.warn("Unhandled config changed: {}", config); } @Override @@ -455,4 +461,14 @@ public class XiaomiSupport extends AbstractBTLEDeviceSupport { .build() ); } + + public void sendCommand(final String taskName, final int type, final int subtype) { + sendCommand( + taskName, + XiaomiProto.Command.newBuilder() + .setType(type) + .setSubtype(subtype) + .build() + ); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/AbstractXiaomiService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/AbstractXiaomiService.java index 7f8b9ca12..3a1d73b3a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/AbstractXiaomiService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/AbstractXiaomiService.java @@ -42,6 +42,16 @@ public abstract class AbstractXiaomiService { } + /** + * Handle a preference change. + * @param config the preference key + * @param prefs the device preferences + * @return true if the preference was handled, false otherwise + */ + public boolean onSendConfiguration(final String config, final Prefs prefs) { + return false; + } + protected XiaomiSupport getSupport() { return mSupport; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiHealthService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiHealthService.java index c1b02ec00..fa701bef4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiHealthService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiHealthService.java @@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class XiaomiHealthService extends AbstractXiaomiService { private static final Logger LOG = LoggerFactory.getLogger(XiaomiHealthService.class); @@ -73,8 +74,7 @@ public class XiaomiHealthService extends AbstractXiaomiService { return; } - // TODO - LOG.warn("Unhandled health command"); + LOG.warn("Unknown health command {}", cmd.getSubtype()); } @Override @@ -82,7 +82,29 @@ public class XiaomiHealthService extends AbstractXiaomiService { setUserInfo(builder); } + @Override + public boolean onSendConfiguration(final String config, final Prefs prefs) { + switch (config) { + case ActivityUser.PREF_USER_HEIGHT_CM: + case ActivityUser.PREF_USER_WEIGHT_KG: + case ActivityUser.PREF_USER_YEAR_OF_BIRTH: + case ActivityUser.PREF_USER_GENDER: + case ActivityUser.PREF_USER_CALORIES_BURNT: + case ActivityUser.PREF_USER_STEPS_GOAL: + case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS: + case ActivityUser.PREF_USER_ACTIVETIME_MINUTES: + final TransactionBuilder builder = getSupport().createTransactionBuilder("set user info"); + setUserInfo(builder); + builder.queue(getSupport().getQueue()); + return true; + } + + return false; + } + public void setUserInfo(final TransactionBuilder builder) { + LOG.debug("Setting user info"); + final ActivityUser activityUser = new ActivityUser(); final int birthYear = activityUser.getYearOfBirth(); final byte birthMonth = 7; // not in user attributes @@ -126,6 +148,8 @@ public class XiaomiHealthService extends AbstractXiaomiService { } public void onHeartRateTest() { + LOG.debug("Trigger heart rate one-shot test"); + realtimeStarted = true; realtimeOneShot = true; @@ -139,6 +163,8 @@ public class XiaomiHealthService extends AbstractXiaomiService { } public void enableRealtimeStats(final boolean enable) { + LOG.debug("Enable realtime stats: {}", enable); + if (realtimeStarted == enable) { // same state, ignore return; @@ -158,6 +184,8 @@ public class XiaomiHealthService extends AbstractXiaomiService { } private void handleRealtimeStats(final XiaomiProto.RealTimeStats realTimeStats) { + LOG.debug("Got realtime stats"); + if (realtimeOneShot) { if (realTimeStats.getHeartRate() <= 10) { return; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiMusicService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiMusicService.java index ee71faece..cdb03c89f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiMusicService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiMusicService.java @@ -66,10 +66,12 @@ public class XiaomiMusicService extends AbstractXiaomiService { switch (cmd.getSubtype()) { case CMD_MUSIC_GET: + LOG.debug("Got music request from watch"); mediaManager.refresh(); sendMusicStateToDevice(); - break; + return; case CMD_MUSIC_BUTTON: + LOG.debug("Got music button from watch: {}", music.getMediaKey().getKey()); final GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl(); switch (music.getMediaKey().getKey()) { case BUTTON_PLAY: @@ -97,10 +99,10 @@ public class XiaomiMusicService extends AbstractXiaomiService { } // FIXME sometimes this is not triggering a device update? getSupport().evaluateGBDeviceEvent(deviceEventMusicControl); - break; - default: - LOG.warn("Unhandled music command {}", cmd.getSubtype()); + return; } + + LOG.warn("Unknown music command {}", cmd.getSubtype()); } public void onSetMusicState(final MusicStateSpec stateSpec) { 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 8fa898e67..46852e5ac 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 @@ -65,35 +65,13 @@ public class XiaomiSystemService extends AbstractXiaomiService { // TODO switch (cmd.getSubtype()) { case CMD_DEVICE_INFO: - final XiaomiProto.DeviceInfo deviceInfo = cmd.getSystem().getDeviceInfo(); - final GBDeviceEventVersionInfo gbDeviceEventVersionInfo = new GBDeviceEventVersionInfo(); - gbDeviceEventVersionInfo.fwVersion = deviceInfo.getFirmware(); - //gbDeviceEventVersionInfo.fwVersion2 = "N/A"; - gbDeviceEventVersionInfo.hwVersion = deviceInfo.getModel(); - final GBDeviceEventUpdateDeviceInfo gbDeviceEventUpdateDeviceInfo = new GBDeviceEventUpdateDeviceInfo("SERIAL: ", deviceInfo.getSerialNumber()); - - getSupport().evaluateGBDeviceEvent(gbDeviceEventVersionInfo); - getSupport().evaluateGBDeviceEvent(gbDeviceEventUpdateDeviceInfo); + handleDeviceInfo(cmd.getSystem().getDeviceInfo()); return; case CMD_BATTERY: - final XiaomiProto.Battery battery = cmd.getSystem().getPower().getBattery(); - final GBDeviceEventBatteryInfo batteryInfo = new GBDeviceEventBatteryInfo(); - batteryInfo.batteryIndex = 0; - batteryInfo.level = battery.getLevel(); - switch (battery.getState()) { - case 1: - batteryInfo.state = BatteryState.BATTERY_CHARGING; - break; - case 2: - batteryInfo.state = BatteryState.BATTERY_NORMAL; - break; - default: - batteryInfo.state = BatteryState.UNKNOWN; - LOG.warn("Unknown battery state {}", battery.getState()); - } - getSupport().evaluateGBDeviceEvent(batteryInfo); + handleBattery(cmd.getSystem().getPower().getBattery()); return; case CMD_FIND_PHONE: + LOG.debug("Got find phone: {}", cmd.getSystem().getFindDevice()); final GBDeviceEventFindPhone findPhoneEvent = new GBDeviceEventFindPhone(); if (cmd.getSystem().getFindDevice() == 0) { findPhoneEvent.event = GBDeviceEventFindPhone.Event.START; @@ -104,20 +82,29 @@ public class XiaomiSystemService extends AbstractXiaomiService { return; case CMD_CHARGER: // charger event, request battery state - getSupport().sendCommand( - "request battery state", - XiaomiProto.Command.newBuilder() - .setType(COMMAND_TYPE) - .setSubtype(CMD_BATTERY) - .build() - ); + getSupport().sendCommand("request battery state", COMMAND_TYPE, CMD_BATTERY); return; - default: - LOG.warn("Unknown config command {}", cmd.getSubtype()); } + + LOG.warn("Unknown config command {}", cmd.getSubtype()); + } + + @Override + public boolean onSendConfiguration(final String config, final Prefs prefs) { + switch (config) { + case DeviceSettingsPreferenceConst.PREF_TIMEFORMAT: + final TransactionBuilder builder = getSupport().createTransactionBuilder("set time format"); + setCurrentTime(builder); + builder.queue(getSupport().getQueue()); + return true; + } + + return super.onSendConfiguration(config, prefs); } public void setCurrentTime(final TransactionBuilder builder) { + LOG.debug("Setting current time"); + final Calendar now = GregorianCalendar.getInstance(); final TimeZone tz = TimeZone.getDefault(); @@ -155,7 +142,42 @@ public class XiaomiSystemService extends AbstractXiaomiService { ); } + private void handleDeviceInfo(final XiaomiProto.DeviceInfo deviceInfo) { + LOG.debug("Got device info: fw={} hw={} sn={}", deviceInfo.getFirmware(), deviceInfo.getModel(), deviceInfo.getSerialNumber()); + + final GBDeviceEventVersionInfo gbDeviceEventVersionInfo = new GBDeviceEventVersionInfo(); + gbDeviceEventVersionInfo.fwVersion = deviceInfo.getFirmware(); + //gbDeviceEventVersionInfo.fwVersion2 = "N/A"; + gbDeviceEventVersionInfo.hwVersion = deviceInfo.getModel(); + final GBDeviceEventUpdateDeviceInfo gbDeviceEventUpdateDeviceInfo = new GBDeviceEventUpdateDeviceInfo("SERIAL: ", deviceInfo.getSerialNumber()); + + getSupport().evaluateGBDeviceEvent(gbDeviceEventVersionInfo); + getSupport().evaluateGBDeviceEvent(gbDeviceEventUpdateDeviceInfo); + } + + private void handleBattery(final XiaomiProto.Battery battery) { + LOG.debug("Got battery: {}", battery.getLevel()); + + final GBDeviceEventBatteryInfo batteryInfo = new GBDeviceEventBatteryInfo(); + batteryInfo.batteryIndex = 0; + batteryInfo.level = battery.getLevel(); + switch (battery.getState()) { + case 1: + batteryInfo.state = BatteryState.BATTERY_CHARGING; + break; + case 2: + batteryInfo.state = BatteryState.BATTERY_NORMAL; + break; + default: + batteryInfo.state = BatteryState.UNKNOWN; + LOG.warn("Unknown battery state {}", battery.getState()); + } + getSupport().evaluateGBDeviceEvent(batteryInfo); + } + public void onFindPhone(final boolean start) { + LOG.debug("Find phone: {}", start); + if (!start) { // Stop on watch getSupport().sendCommand(