From 0745a374a551f26cc73accf6a54313bdc3dd51f6 Mon Sep 17 00:00:00 2001 From: Me7c7 Date: Fri, 6 Sep 2024 16:39:26 +0300 Subject: [PATCH] Huawei: Continuous skin temperature measurement switch --- .../devices/huawei/HuaweiConstants.java | 1 + .../devices/huawei/HuaweiCoordinator.java | 11 ++++++ .../huawei/HuaweiSettingsCustomizer.java | 2 + .../devices/huawei/packets/FitnessData.java | 19 +++++++++ .../devices/huawei/packets/LocaleConfig.java | 20 ++++++++++ .../devices/huawei/HuaweiSupportProvider.java | 32 +++++++++++++++ .../SetSkinTemperatureMeasurement.java | 39 +++++++++++++++++++ .../requests/SetTemperatureUnitSetting.java | 38 ++++++++++++++++++ app/src/main/res/drawable/ic_temperature.xml | 12 ++++++ app/src/main/res/values/strings.xml | 2 + ...esettings_temperature_automatic_enable.xml | 10 +++++ 11 files changed, 186 insertions(+) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetSkinTemperatureMeasurement.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetTemperatureUnitSetting.java create mode 100644 app/src/main/res/drawable/ic_temperature.xml create mode 100644 app/src/main/res/xml/devicesettings_temperature_automatic_enable.xml diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java index 447746208..4cd555a92 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java @@ -82,6 +82,7 @@ public final class HuaweiConstants { public static final String PREF_HUAWEI_ACCOUNT = "huawei_account"; public static final String PREF_HUAWEI_DND_LIFT_WRIST_TYPE = "dnd_lift_wrist_type"; // SharedPref for 0x01 0x1D public static final String PREF_HUAWEI_DEBUG_REQUEST = "debug_huawei_request"; + public static final String PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT = "continuous_skin_temperature_measurement"; public static final String PKG_NAME = "com.huawei.devicegroupmanage"; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index f38d4d627..71f3a5fb4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -220,6 +220,9 @@ public class HuaweiCoordinator { deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_heartrate_automatic_enable); if (supportsSPo2()) deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_spo_automatic_enable); + if(supportsTemperature()) { + deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_temperature_automatic_enable); + } // Notifications final List notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS); @@ -266,6 +269,9 @@ public class HuaweiCoordinator { // Currently on main setting menu. /*if (supportsLanguageSetting()) deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY, R.xml.devicesettings_language_generic);*/ + if(supportsTemperature()) { + deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY, R.xml.devicesettings_temperature_scale_cf); + } // Developer final List developer = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DEVELOPER); @@ -391,6 +397,11 @@ public class HuaweiCoordinator { return supportsCommandForService(0x07, 0x29); } + // 0x1d - SupportTemperature + // 0xba - SupportTemperatureClassification + // 0x43 - SupportTemperatureStudy + public boolean supportsTemperature() { return supportsExpandCapability(0x1d); } + public boolean supportsEventAlarm() { return supportsCommandForService(0x08, 0x01); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java index ae2fbe205..75c7a43e8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java @@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.XTimePreference; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_DEBUG_REQUEST; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_TRUSLEEP; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_WORKMODE; @@ -104,6 +105,7 @@ public class HuaweiSettingsCustomizer implements DeviceSpecificSettingsCustomize handler.addPreferenceHandlerFor(PREF_HUAWEI_WORKMODE); handler.addPreferenceHandlerFor(PREF_HUAWEI_TRUSLEEP); handler.addPreferenceHandlerFor(PREF_HUAWEI_DEBUG_REQUEST); + handler.addPreferenceHandlerFor(PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT); final Preference forceOptions = handler.findPreference(PREF_FORCE_OPTIONS); if (forceOptions != null) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FitnessData.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FitnessData.java index 6f0d93509..806718164 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FitnessData.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FitnessData.java @@ -577,6 +577,25 @@ public class FitnessData { } } + public static class SkinTemperatureMeasurement { + public static final byte id = 0x2a; + + public static class Request extends HuaweiPacket { + public Request(ParamsProvider paramsProvider, boolean temperatureSwitch) { + super(paramsProvider); + + this.serviceId = FitnessData.id; + this.commandId = id; + + this.tlv = new HuaweiTLV() + .put(0x01, (byte)0x01) + .put(0x02, temperatureSwitch); + + this.complete = true; + } + } + } + public static class Type { // TODO: enum? diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/LocaleConfig.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/LocaleConfig.java index d729fe48a..cd6e0bbd7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/LocaleConfig.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/LocaleConfig.java @@ -49,4 +49,24 @@ public class LocaleConfig { public static final byte metric = 0x00; public static final byte imperial = 0x01; } + + public static class SetTemperatureUnitSetting extends HuaweiPacket { + public static final byte id = 0x05; + + public SetTemperatureUnitSetting( + ParamsProvider paramsProvider, + byte isFahrenheit + ) { + super(paramsProvider); + + this.serviceId = LocaleConfig.id; + this.commandId = id; + + this.tlv = new HuaweiTLV() + .put(0x01, isFahrenheit); + + this.complete = true; + } + } + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index ca3862ab1..de9ca73fb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -121,6 +121,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetA import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetAutomaticSpoRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetDisconnectNotification; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetMediumToStrengthThresholdRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetSkinTemperatureMeasurement; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetTemperatureUnitSetting; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.StopFindPhoneRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.StopNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetFitnessTotalsRequest; @@ -925,6 +927,14 @@ public class HuaweiSupportProvider { setTrusleep(); break; } + case HuaweiConstants.PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT: { + setContinuousSkinTemperatureMeasurement(); + break; + } + case DeviceSettingsPreferenceConst.PREF_TEMPERATURE_SCALE_CF: { + setTemperatureUnit(); + break; + } case DeviceSettingsPreferenceConst.PREF_NOTIFICATION_ENABLE: { setNotificationStatus(); break; @@ -1661,6 +1671,28 @@ public class HuaweiSupportProvider { } } + public void setTemperatureUnit() { + try { + SetTemperatureUnitSetting setTemperatureUnitSetting = new SetTemperatureUnitSetting(this); + setTemperatureUnitSetting.doPerform(); + } catch (IOException e) { + // TODO: Use translatable string + GB.toast(context, "Failed to set temperature unit", Toast.LENGTH_SHORT, GB.ERROR, e); + LOG.error("Failed to configure TemperatureUnitSetting", e); + } + } + + public void setContinuousSkinTemperatureMeasurement() { + try { + SetSkinTemperatureMeasurement skinTemperatureMeasurement = new SetSkinTemperatureMeasurement(this); + skinTemperatureMeasurement.doPerform(); + } catch (IOException e) { + // TODO: Use translatable string + GB.toast(context, "Failed to configure continuous skin temperature measurement", Toast.LENGTH_SHORT, GB.ERROR, e); + LOG.error("Failed to configure SkinTemperatureMeasurement", e); + } + } + public void setDnd() { try { SendDndDeleteRequest sendDndDeleteReq = new SendDndDeleteRequest(this); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetSkinTemperatureMeasurement.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetSkinTemperatureMeasurement.java new file mode 100644 index 000000000..50c2ec88e --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetSkinTemperatureMeasurement.java @@ -0,0 +1,39 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider; + +public class SetSkinTemperatureMeasurement extends Request { + private static final Logger LOG = LoggerFactory.getLogger(SetSkinTemperatureMeasurement.class); + + public SetSkinTemperatureMeasurement(HuaweiSupportProvider support) { + super(support); + this.serviceId = FitnessData.id; + this.commandId = FitnessData.SkinTemperatureMeasurement.id; + } + + @Override + protected List createRequest() throws RequestCreationException { + boolean temperatureSwitch = GBApplication + .getDeviceSpecificSharedPrefs(this.getDevice().getAddress()) + .getBoolean(HuaweiConstants.PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT, false); + try { + return new FitnessData.SkinTemperatureMeasurement.Request(paramsProvider, temperatureSwitch).serialize(); + } catch (HuaweiPacket.CryptoException e) { + throw new RequestCreationException(e); + } + } + + @Override + protected void processResponse() { + LOG.debug("handle Set SkinTemperatureMeasurement"); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetTemperatureUnitSetting.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetTemperatureUnitSetting.java new file mode 100644 index 000000000..471692c09 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SetTemperatureUnitSetting.java @@ -0,0 +1,38 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.LocaleConfig; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider; + +public class SetTemperatureUnitSetting extends Request { + private static final Logger LOG = LoggerFactory.getLogger(SetLanguageSettingRequest.class); + + public SetTemperatureUnitSetting(HuaweiSupportProvider support) { + super(support); + this.serviceId = LocaleConfig.id; + this.commandId = LocaleConfig.SetTemperatureUnitSetting.id; + } + + @Override + protected List createRequest() throws RequestCreationException { + String temperatureScale = GBApplication.getDeviceSpecificSharedPrefs(this.getDevice().getAddress()).getString(DeviceSettingsPreferenceConst.PREF_TEMPERATURE_SCALE_CF, ""); + byte isFahrenheit = (byte) ((temperatureScale.equals("f")) ? 1 : 0); + try { + return new LocaleConfig.SetTemperatureUnitSetting(paramsProvider, isFahrenheit).serialize(); + } catch (HuaweiPacket.CryptoException e) { + throw new RequestCreationException(e); + } + } + + @Override + protected void processResponse() { + LOG.debug("handle Set Temperature unit"); + } +} diff --git a/app/src/main/res/drawable/ic_temperature.xml b/app/src/main/res/drawable/ic_temperature.xml new file mode 100644 index 000000000..1ad32524c --- /dev/null +++ b/app/src/main/res/drawable/ic_temperature.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3d22a65c..4a1009579 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2750,6 +2750,8 @@ none ask auto + Continuous skin temperature measurement + Temperature retrieval is not currently supported. This setting only enable continuous measurement on the device Menu Some buttons cannot be configured because their functions are hard-coded in the watch firmware.\n\nWarning: long-pressing the upper button when a watchface from the official Fossil app is installed will also toggle between showing/hiding widgets. diff --git a/app/src/main/res/xml/devicesettings_temperature_automatic_enable.xml b/app/src/main/res/xml/devicesettings_temperature_automatic_enable.xml new file mode 100644 index 000000000..239331f21 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_temperature_automatic_enable.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file