From c24ef44055cce52ae2bd897163dc7fe6da7f130a Mon Sep 17 00:00:00 2001 From: thermatk Date: Thu, 22 Sep 2022 00:56:22 +0200 Subject: [PATCH] Amazfit GTR 3: Initial support (#2900) Co-authored-by: thermatk Co-committed-by: thermatk --- README.md | 2 +- .../devices/huami/HuamiConst.java | 1 + .../amazfitgtr3/AmazfitGTR3Coordinator.java | 63 +++++++++++++++++++ .../amazfitgtr3/AmazfitGTR3FWHelper.java | 44 +++++++++++++ .../AmazfitGTR3FWInstallHandler.java | 49 +++++++++++++++ .../gadgetbridge/model/DeviceType.java | 1 + .../service/DeviceSupportFactory.java | 3 + .../amazfitgtr3/AmazfitGTR3FirmwareInfo.java | 60 ++++++++++++++++++ .../huami/amazfitgtr3/AmazfitGTR3Support.java | 39 ++++++++++++ .../gadgetbridge/util/DeviceHelper.java | 2 + app/src/main/res/values/strings.xml | 2 + 11 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3Coordinator.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWHelper.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWInstallHandler.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3FirmwareInfo.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3Support.java diff --git a/README.md b/README.md index 486d4bbe4..52788a2a5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ vendor's servers. - [Bip](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip) - [Bip Lite](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-Lite), [Bip S](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-S), [Bip U](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-U) [**\[!\]**](#special-pairing-procedures) - [Cor](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor), [Cor 2](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor-2) - - [GTR](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR) [**\[!\]**](#special-pairing-procedures) + - [GTR](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 3](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR-3) [**\[!\]**](#special-pairing-procedures) - [GTS](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS), [GTS 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS), [GTS 3](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS-3) [**\[!\]**](#special-pairing-procedures) - [Neo](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Neo) [**\[!\]**](#special-pairing-procedures) - T-Rex [**\[!\]**](#special-pairing-procedures) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiConst.java index da7bb531f..5626d5bb6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiConst.java @@ -56,6 +56,7 @@ public class HuamiConst { public static final String AMAZFIT_NEO_NAME = "Amazfit Neo"; public static final String AMAZFIT_X = "Amazfit X"; public static final String AMAZFIT_GTS3_NAME = "Amazfit GTS 3"; + public static final String AMAZFIT_GTR3_NAME = "Amazfit GTR 3"; public static final String XIAOMI_SMART_BAND7_NAME = "Xiaomi Smart Band 7"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3Coordinator.java new file mode 100644 index 000000000..f34ea492f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3Coordinator.java @@ -0,0 +1,63 @@ +/* Copyright (C) 2022 José Rebelo + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3; + +import android.bluetooth.BluetoothDevice; +import android.content.Context; +import android.net.Uri; + +import androidx.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.Huami2021Coordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +public class AmazfitGTR3Coordinator extends Huami2021Coordinator { + private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR3Coordinator.class); + + @NonNull + @Override + public DeviceType getSupportedType(final GBDeviceCandidate candidate) { + try { + final BluetoothDevice device = candidate.getDevice(); + final String name = device.getName(); + if (name != null && name.startsWith(HuamiConst.AMAZFIT_GTR3_NAME) && !name.contains("Pro")) { + return DeviceType.AMAZFITGTR3; + } + } catch (final Exception e) { + LOG.error("unable to check device support", e); + } + + return DeviceType.UNKNOWN; + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.AMAZFITGTR3; + } + + @Override + public InstallHandler findInstallHandler(final Uri uri, final Context context) { + final AmazfitGTR3FWInstallHandler handler = new AmazfitGTR3FWInstallHandler(uri, context); + return handler.isValid() ? handler : null; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWHelper.java new file mode 100644 index 000000000..991396c68 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWHelper.java @@ -0,0 +1,44 @@ +/* Copyright (C) 2022 José Rebelo + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3; + +import android.content.Context; +import android.net.Uri; + +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr3.AmazfitGTR3FirmwareInfo; + +public class AmazfitGTR3FWHelper extends HuamiFWHelper { + public AmazfitGTR3FWHelper(final Uri uri, final Context context) throws IOException { + super(uri, context); + } + + @Override + public long getMaxExpectedFileSize() { + return 1024 * 1024 * 128; // 128.0MB + } + + @Override + protected void determineFirmwareInfo(final byte[] wholeFirmwareBytes) { + firmwareInfo = new AmazfitGTR3FirmwareInfo(wholeFirmwareBytes); + if (!firmwareInfo.isHeaderValid()) { + throw new IllegalArgumentException("Not a Amazfit GTR 3 firmware"); + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWInstallHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWInstallHandler.java new file mode 100644 index 000000000..97b5b86c0 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr3/AmazfitGTR3FWInstallHandler.java @@ -0,0 +1,49 @@ +/* Copyright (C) 2022 José Rebelo + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3; + +import android.content.Context; +import android.net.Uri; + +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWInstallHandler; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +class AmazfitGTR3FWInstallHandler extends AbstractMiBandFWInstallHandler { + AmazfitGTR3FWInstallHandler(Uri uri, Context context) { + super(uri, context); + } + + @Override + protected String getFwUpgradeNotice() { + return mContext.getString(R.string.fw_upgrade_notice_amazfit_gtr3, helper.getHumanFirmwareVersion()); + } + + @Override + protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException { + return new AmazfitGTR3FWHelper(uri, context); + } + + @Override + protected boolean isSupportedDeviceType(GBDevice device) { + return device.getType() == DeviceType.AMAZFITGTR3; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java index 9e2ccd28b..743b8c6a9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -67,6 +67,7 @@ public enum DeviceType { AMAZFITPOPPRO(10040, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_pop_pro), MIBAND7(10041, R.drawable.ic_device_miband6, R.drawable.ic_device_miband6_disabled, R.string.devicetype_miband7), AMAZFITGTS3(10042, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_gts3), + AMAZFITGTR3(10043, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_amazfit_gtr3), HPLUS(40, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_hplus), MAKIBESF68(41, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_makibes_f68), EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_exrizu_k8), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java index 62ccd2273..39434b1a9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -56,6 +56,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr.Ama import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr.AmazfitGTRSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr2.AmazfitGTR2Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr2.AmazfitGTR2eSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr3.AmazfitGTR3Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts.AmazfitGTSSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts2.AmazfitGTS2MiniSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts2.AmazfitGTS2Support; @@ -184,6 +185,8 @@ public class DeviceSupportFactory { return new ServiceDeviceSupport(new MiBand6Support()); case AMAZFITGTS3: return new ServiceDeviceSupport(new AmazfitGTS3Support()); + case AMAZFITGTR3: + return new ServiceDeviceSupport(new AmazfitGTR3Support()); case MIBAND7: return new ServiceDeviceSupport(new MiBand7Support()); case AMAZFITBIP: diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3FirmwareInfo.java new file mode 100644 index 000000000..9c3782de2 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3FirmwareInfo.java @@ -0,0 +1,60 @@ +/* Copyright (C) 2022 José Rebelo + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr3; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021FirmwareInfo; + +public class AmazfitGTR3FirmwareInfo extends Huami2021FirmwareInfo { + private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR3FirmwareInfo.class); + + private static final Map crcToVersion = new HashMap() {{ + // firmware + }}; + + public AmazfitGTR3FirmwareInfo(final byte[] bytes) { + super(bytes); + } + + @Override + public String deviceName() { + return HuamiConst.AMAZFIT_GTR3_NAME; + } + + @Override + public byte[] getExpectedFirmwareHeader() { + return new byte[]{0x00, 0x00, 0x50}; // Probably bogus, only checked against 2 firmware files + } + + @Override + public boolean isGenerallyCompatibleWith(final GBDevice device) { + return isHeaderValid() && device.getType() == DeviceType.AMAZFITGTR3; + } + + @Override + protected Map getCrcMap() { + return crcToVersion; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3Support.java new file mode 100644 index 000000000..b6bad994b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr3/AmazfitGTR3Support.java @@ -0,0 +1,39 @@ +/* Copyright (C) 2022 José Rebelo + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr3; + +import android.content.Context; +import android.net.Uri; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3.AmazfitGTR3FWHelper; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Support; + +public class AmazfitGTR3Support extends Huami2021Support { + private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR3Support.class); + + @Override + public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException { + return new AmazfitGTR3FWHelper(uri, context); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java index fbff8b45b..524345009 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -80,6 +80,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitx.AmazfitXCoord import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband6.MiBand6Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband7.MiBand7Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts3.AmazfitGTS3Coordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3.AmazfitGTR3Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppe.ZeppECoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr2.AmazfitGTR2eCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSCoordinator; @@ -288,6 +289,7 @@ public class DeviceHelper { result.add(new MiBand6Coordinator()); result.add(new MiBand7Coordinator()); result.add(new AmazfitGTS3Coordinator()); + result.add(new AmazfitGTR3Coordinator()); result.add(new MiBand2HRXCoordinator()); result.add(new MiBand2Coordinator()); // Note: MiBand2 and all of the above must come before MiBand because detection is hacky, atm result.add(new MiBandCoordinator()); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1252b9b65..478c14977 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -133,6 +133,7 @@ You are about to install the %s firmware on your Mi Band 6.\n\nPlease make sure to install the .fw file, and after that the .res file. Your band will reboot after installing the .fw file.\n\nNote: You do not have to install .res if it is exactly the same as the one previously installed.\n\nPROCEED AT YOUR OWN RISK! You are about to install the %s firmware on your Xiaomi Smart Band 7.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK! You are about to install the %s firmware on your Amazfit GTS 3.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK! + You are about to install the %s firmware on your Amazfit GTR 3.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK! You are about to install the %s firmware on your Amazfit X.\n\nPlease make sure to install the .fw file, and after that the .res file. Your band will reboot after installing the .fw file.\n\nNote: You do not have to install .res if it is exactly the same as the one previously installed.\n\nPROCEED AT YOUR OWN RISK! You are about to install the %s firmware on your Amazfit Neo. \n @@ -1065,6 +1066,7 @@ Mi Band 6 Xiaomi Smart Band 7 Amazfit GTS 3 + Amazfit GTR 3 Amazfit Band 5 Amazfit Neo Amazfit Bip