mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Zepp OS: Add debug support for more config types
As seen when requesting all config arguments from the Amazfit GTR 4.
This commit is contained in:
+4
@@ -35,6 +35,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
|
||||
@@ -549,6 +550,9 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
|
||||
}
|
||||
developer.add(R.xml.devicesettings_keep_activity_data_on_device);
|
||||
developer.add(R.xml.devicesettings_huami2021_fetch_operation_time_unit);
|
||||
if (BuildConfig.DEBUG) {
|
||||
developer.add(R.xml.devicesettings_zeppos_request_all_configs);
|
||||
}
|
||||
|
||||
return deviceSpecificSettings;
|
||||
}
|
||||
|
||||
+14
-1
@@ -320,7 +320,20 @@ public class ZeppOsSupport extends AbstractDeviceSupport
|
||||
|
||||
@Override
|
||||
public void onTestNewFunction() {
|
||||
|
||||
//final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("test new function");
|
||||
//configService.requestConfig(
|
||||
// builder,
|
||||
// ZeppOsConfigService.ConfigGroup.AGPS,
|
||||
// true,
|
||||
// Collections.singletonList(ZeppOsConfigService.ConfigArg.AGPS_UNK_0x08)
|
||||
//);
|
||||
//configService.requestConfig(
|
||||
// builder,
|
||||
// ZeppOsConfigService.ConfigGroup.WORKOUT,
|
||||
// true,
|
||||
// Collections.singletonList(ZeppOsConfigService.ConfigArg.WORKOUT_HEART_RATE_ZONES)
|
||||
//);
|
||||
//builder.queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+36
-10
@@ -79,12 +79,14 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsS
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiLanguageType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigIntUnbound;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigBoolean;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigByte;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigByteList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigDatetimeHhMm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigInt;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigShort;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigShortList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigString;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigStringList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config.ConfigTimestamp;
|
||||
@@ -362,7 +364,13 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
public void requestConfig(final ZeppOsTransactionBuilder builder, final ConfigGroup config) {
|
||||
requestConfig(builder, config, true, ZeppOsConfigService.ConfigArg.getAllArgsForConfigGroup(config));
|
||||
if (BuildConfig.DEBUG && getSupport().getDevicePrefs().getBoolean("zepp_os_request_all_config_args", false)) {
|
||||
LOG.debug("Requesting all config args for {}", config);
|
||||
requestConfig(builder, config, true, Collections.emptyList());
|
||||
} else {
|
||||
// More conservative approach, since we may get config types we don't know how to parse
|
||||
requestConfig(builder, config, true, ZeppOsConfigService.ConfigArg.getAllArgsForConfigGroup(config));
|
||||
}
|
||||
}
|
||||
|
||||
public void requestConfig(final ZeppOsTransactionBuilder builder,
|
||||
@@ -429,13 +437,13 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
STRING(0x20),
|
||||
STRING_LIST(0x21),
|
||||
SHORT(0x01),
|
||||
// TODO 0x02
|
||||
SHORT_LIST(0x02),
|
||||
INT(0x03),
|
||||
BYTE(0x10),
|
||||
BYTE_LIST(0x11),
|
||||
DATETIME_HH_MM(0x30),
|
||||
TIMESTAMP_MILLIS(0x40),
|
||||
// TODO 0x50
|
||||
INT_UNBOUND(0x50),
|
||||
;
|
||||
|
||||
private final byte value;
|
||||
@@ -461,6 +469,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
|
||||
public enum ConfigArg {
|
||||
// AGPS
|
||||
AGPS_UNK_0x08(ConfigGroup.AGPS, ConfigType.INT_UNBOUND, 0x08, null), // TODO ?
|
||||
AGPS_UPDATE_TIME(ConfigGroup.AGPS, ConfigType.TIMESTAMP_MILLIS, 0x09, PREF_AGPS_UPDATE_TIME),
|
||||
AGPS_EXPIRE_TIME(ConfigGroup.AGPS, ConfigType.TIMESTAMP_MILLIS, 0x0a, PREF_AGPS_EXPIRE_TIME),
|
||||
|
||||
@@ -543,6 +552,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
WORKOUT_DETECTION_ALERT(ConfigGroup.WORKOUT, ConfigType.BOOL, 0x41, PREF_WORKOUT_DETECTION_ALERT),
|
||||
WORKOUT_DETECTION_SENSITIVITY(ConfigGroup.WORKOUT, ConfigType.BYTE, 0x42, PREF_WORKOUT_DETECTION_SENSITIVITY),
|
||||
WORKOUT_POOL_SWIMMING_SIZE(ConfigGroup.WORKOUT, ConfigType.BYTE, 0x51, null), // TODO ?
|
||||
WORKOUT_HEART_RATE_ZONES(ConfigGroup.WORKOUT, ConfigType.SHORT_LIST, 0x05, null),
|
||||
|
||||
// System
|
||||
TIME_FORMAT(ConfigGroup.SYSTEM, ConfigType.BYTE, 0x01, PREF_TIMEFORMAT),
|
||||
@@ -1069,6 +1079,13 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
argPrefs = convertShortToPrefs(configArg, valShort);
|
||||
}
|
||||
break;
|
||||
case SHORT_LIST:
|
||||
final ConfigShortList valShortList = ConfigShortList.consume(buf, includesConstraints);
|
||||
LOG.info("Got {} ({}) = {}", configArg, String.format("0x%02x", configArgByte), valShortList);
|
||||
if (configArg != null) {
|
||||
// TODO
|
||||
}
|
||||
break;
|
||||
case INT:
|
||||
final ConfigInt valInt = ConfigInt.consume(buf, includesConstraints);
|
||||
LOG.info("Got {} ({}) = {}", configArg, String.format("0x%02x", configArgByte), valInt);
|
||||
@@ -1108,6 +1125,13 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
argPrefs = convertTimestampToPrefs(configArg, valTimestamp);
|
||||
}
|
||||
break;
|
||||
case INT_UNBOUND:
|
||||
final ConfigIntUnbound valIntUnbound = ConfigIntUnbound.consume(buf, includesConstraints);
|
||||
LOG.info("Got {} ({}) = {}", configArg, String.format("0x%02x", configArgByte), valIntUnbound);
|
||||
if (configArg != null) {
|
||||
// TODO
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG.error("No parser for {}", configArg);
|
||||
// Abort, since we don't know how to parse this type or how many bytes it is
|
||||
@@ -1391,13 +1415,15 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
decoder = null;
|
||||
}
|
||||
|
||||
if (decoder != null) {
|
||||
prefs = singletonMap(configArg.getPrefKey(), decoder.decode(value.getValue()));
|
||||
if (includesConstraints) {
|
||||
prefs.put(
|
||||
DeviceSettingsUtils.getPrefPossibleValuesKey(configArg.getPrefKey()),
|
||||
TextUtils.join(",", decodeByteValues(possibleValues, decoder))
|
||||
);
|
||||
if (configArg.getPrefKey() != null) {
|
||||
if (decoder != null) {
|
||||
prefs = singletonMap(configArg.getPrefKey(), decoder.decode(value.getValue()));
|
||||
if (includesConstraints) {
|
||||
prefs.put(
|
||||
DeviceSettingsUtils.getPrefPossibleValuesKey(configArg.getPrefKey()),
|
||||
TextUtils.join(",", decodeByteValues(possibleValues, decoder))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class ConfigIntUnbound {
|
||||
private final int value;
|
||||
|
||||
public ConfigIntUnbound(final int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static ConfigIntUnbound consume(final ByteBuffer buf, final boolean includesConstraints) {
|
||||
final int value = buf.getInt();
|
||||
|
||||
// Looks to have no constraints at all
|
||||
|
||||
return new ConfigIntUnbound(value);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(Locale.ROOT, "ConfigIntUnbound{value=%s}", String.format("0x%08x", value));
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.config;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class ConfigShortList {
|
||||
private final short[] values;
|
||||
|
||||
private final int minCount;
|
||||
private final int maxCount;
|
||||
private final short minValue;
|
||||
private final short maxValue;
|
||||
|
||||
public ConfigShortList(final short[] values,
|
||||
final int minCount,
|
||||
final int maxCount,
|
||||
final short minValue,
|
||||
final short maxValue) {
|
||||
this.values = values;
|
||||
this.minCount = minCount;
|
||||
this.maxCount = maxCount;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
public static ConfigShortList consume(final ByteBuffer buf, final boolean includesConstraints) {
|
||||
final int numValues = buf.get() & 0xff;
|
||||
final short[] values = new short[numValues];
|
||||
for (int i = 0; i < numValues; i++) {
|
||||
values[i] = buf.getShort();
|
||||
}
|
||||
|
||||
if (!includesConstraints) {
|
||||
return new ConfigShortList(
|
||||
values,
|
||||
0,
|
||||
Integer.MAX_VALUE,
|
||||
Short.MIN_VALUE,
|
||||
Short.MAX_VALUE
|
||||
);
|
||||
}
|
||||
|
||||
// only seen in WORKOUT 0x05 in what looks like HR zones: [80,100,120,140,160,180]
|
||||
final int minCount = buf.get() & 0xff; // 6
|
||||
final int maxCount = buf.get() & 0xff; // 6
|
||||
final short minValue = buf.getShort(); // 30
|
||||
final short maxValue = buf.getShort(); // 220
|
||||
|
||||
return new ConfigShortList(
|
||||
values,
|
||||
minCount,
|
||||
maxCount,
|
||||
minValue,
|
||||
maxValue
|
||||
);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("ConfigShortList{values=[");
|
||||
|
||||
for (short value : values) {
|
||||
sb.append(value).append(",");
|
||||
}
|
||||
if (values.length > 0) {
|
||||
sb.setLength(sb.length() - 1); // remove last ,
|
||||
}
|
||||
sb.append("]");
|
||||
|
||||
if (maxCount != Integer.MAX_VALUE) {
|
||||
sb.append(", minCount=").append(minCount);
|
||||
sb.append(", maxCount=").append(maxCount);
|
||||
sb.append(", minValue=").append(minValue);
|
||||
sb.append(", maxValue=").append(maxValue);
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_settings_applications"
|
||||
android:key="zepp_os_request_all_config_args"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="Some may fail to be parsed - check the logs for errors."
|
||||
android:title="Request all config args" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user