diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7622dc4763..87b25f32de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
* Initial support for Redmi Buds 8 Active
* Initial support for iTECH Active 3 (MoYoung / Da Fit)
* Initial support for ZL02D (MoYoung / Da Fit)
+* Experimental support for Amazfit Active 3 Premium, Cheetah 2 Pro, T-Rex Ultra 2
* Experimental support for Sony WH-1000XM6
* Add and adjust default sleep range to 18:00
* Add auto export of gpx files
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
index d699aeecd0..7f67784b4c 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
@@ -661,7 +661,7 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
}
public boolean supportsFtpServer(final GBDevice device) {
- return false;
+ return supportsWifiHotspot(device);
}
public boolean hasGps(final GBDevice device) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitActive3PremiumCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitActive3PremiumCoordinator.java
new file mode 100644
index 0000000000..3282878d95
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitActive3PremiumCoordinator.java
@@ -0,0 +1,94 @@
+/* Copyright (C) 2026 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.zeppos.watches;
+
+import androidx.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class AmazfitActive3PremiumCoordinator extends ZeppOsCoordinator {
+ @Override
+ public boolean isExperimental() {
+ return true;
+ }
+
+ @Override
+ public ConnectionType getConnectionType() {
+ return ConnectionType.BOTH;
+ }
+
+ @Override
+ public List getDeviceBluetoothNames() {
+ // never seen, assumptions
+ return Arrays.asList(
+ "Amazfit Active 3 Premium",
+ "Active 3 Premium"
+ );
+ }
+
+ @Override
+ public Set getDeviceSources() {
+ return new HashSet<>(Arrays.asList(
+ 10944768, // chinese mainland version
+ 10944769,
+ 10944771,
+ 10948867
+ ));
+ }
+
+ @Override
+ public int getDeviceNameResource() {
+ return R.string.devicetype_amazfit_active_3_premium;
+ }
+
+ @Override
+ public boolean mainMenuHasMoreSection() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsControlCenter() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsToDoList() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsWifiHotspot(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBluetoothPhoneCalls(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public DeviceKind getDeviceKind(@NonNull GBDevice device) {
+ return DeviceKind.WATCH;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitCheetah2ProCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitCheetah2ProCoordinator.java
new file mode 100644
index 0000000000..cf650542be
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitCheetah2ProCoordinator.java
@@ -0,0 +1,93 @@
+/* Copyright (C) 2026 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.zeppos.watches;
+
+import androidx.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class AmazfitCheetah2ProCoordinator extends ZeppOsCoordinator {
+ @Override
+ public boolean isExperimental() {
+ return true;
+ }
+
+ @Override
+ public ConnectionType getConnectionType() {
+ return ConnectionType.BOTH;
+ }
+
+ @Override
+ public List getDeviceBluetoothNames() {
+ // never seen, assumption
+ return Arrays.asList(
+ "Amazfit Cheetah 2 Pro",
+ "Cheetah 2 Pro"
+ );
+ }
+
+ @Override
+ public Set getDeviceSources() {
+ return new HashSet<>(Arrays.asList(
+ 11010304, // chinese mainland version
+ 11010305,
+ 11010307
+ ));
+ }
+
+ @Override
+ public int getDeviceNameResource() {
+ return R.string.devicetype_amazfit_cheetah_2_pro;
+ }
+
+ @Override
+ public boolean mainMenuHasMoreSection() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsControlCenter() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsToDoList() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsWifiHotspot(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBluetoothPhoneCalls(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public DeviceKind getDeviceKind(@NonNull GBDevice device) {
+ return DeviceKind.WATCH;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitTRexUltra2Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitTRexUltra2Coordinator.java
new file mode 100644
index 0000000000..7d3cf73a55
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/watches/AmazfitTRexUltra2Coordinator.java
@@ -0,0 +1,83 @@
+/* Copyright (C) 2026 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.zeppos.watches;
+
+import androidx.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class AmazfitTRexUltra2Coordinator extends ZeppOsCoordinator {
+ @Override
+ public boolean isExperimental() {
+ return true;
+ }
+
+ @Override
+ public List getDeviceBluetoothNames() {
+ // never seen, assumptions
+ return Arrays.asList(
+ "Amazfit T-Rex Ultra 2",
+ "T-Rex Ultra 2"
+ );
+ }
+
+ @Override
+ public Set getDeviceSources() {
+ return new HashSet<>(Arrays.asList(
+ 10879232, // chinese mainland version
+ 10879233,
+ 10879235
+ ));
+ }
+
+ @Override
+ public int getDeviceNameResource() {
+ return R.string.devicetype_amazfit_trex_ultra_2;
+ }
+
+ @Override
+ public boolean supportsControlCenter() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsToDoList() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsWifiHotspot(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBluetoothPhoneCalls(final GBDevice device) {
+ return true;
+ }
+
+ @Override
+ public DeviceKind getDeviceKind(@NonNull GBDevice device) {
+ return DeviceKind.WATCH;
+ }
+}
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 ad6e7be818..4cc38ad56f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
@@ -237,6 +237,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.straps.AmazfitH
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActive2RoundCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActive2NfcCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActive2SquareCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActive3PremiumCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActiveCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActiveEdgeCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitActiveMaxCoordinator;
@@ -247,6 +248,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.Amazfit
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitBip5Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitBip5UnityCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitBip6Coordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitCheetah2ProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitCheetahProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitCheetahRoundCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitCheetahSquareCoordinator;
@@ -263,6 +265,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.Amazfit
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitTRex3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitTRex3Pro44mmCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitTRex3Pro48mmCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitTRexUltra2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitTRexUltraCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.MiBand7Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.freearc.HuaweiFreearcCoordinator;
@@ -572,12 +575,14 @@ public enum DeviceType {
AMAZFITBIP3(AmazfitBip3Coordinator.class),
AMAZFITBIP3PRO(AmazfitBip3ProCoordinator.class),
AMAZFITCHEETAHPRO(AmazfitCheetahProCoordinator.class),
+ AMAZFITCHEETAH2PRO(AmazfitCheetah2ProCoordinator.class),
AMAZFITCHEETAHSQUARE(AmazfitCheetahSquareCoordinator.class),
AMAZFITCHEETAHROUND(AmazfitCheetahRoundCoordinator.class),
AMAZFITBIP5(AmazfitBip5Coordinator.class),
AMAZFITBIP5UNITY(AmazfitBip5UnityCoordinator.class),
AMAZFITBIP6(AmazfitBip6Coordinator.class),
AMAZFITTREXULTRA(AmazfitTRexUltraCoordinator.class),
+ AMAZFITTREXULTRA2(AmazfitTRexUltra2Coordinator.class),
AMAZFITGTRMINI(AmazfitGTRMiniCoordinator.class),
AMAZFITFALCON(AmazfitFalconCoordinator.class),
AMAZFITBALANCE(AmazfitBalanceCoordinator.class),
@@ -587,6 +592,7 @@ public enum DeviceType {
AMAZFITACTIVE2(AmazfitActive2RoundCoordinator.class),
AMAZFITACTIVE2NFC(AmazfitActive2NfcCoordinator.class),
AMAZFITACTIVE2SQUARE(AmazfitActive2SquareCoordinator.class),
+ AMAZFITACTIVE3PREMIUM(AmazfitActive3PremiumCoordinator.class),
AMAZFITACTIVEEDGE(AmazfitActiveEdgeCoordinator.class),
AMAZFITACTIVEMAX(AmazfitActiveMaxCoordinator.class),
AMAZFITHELIORING(AmazfitHelioRingCoordinator.class),
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsDeviceSources.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsDeviceSources.kt
index 1efb8344a1..afe575a85a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsDeviceSources.kt
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsDeviceSources.kt
@@ -1,7 +1,8 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos
object ZeppOsDeviceSources {
- // jq '.[] | [.value.productId, .value.productVersion, .deviceSource] | @csv' -r devices.json
+ // jq '.[] | [.value.productId, .value.productVersion, .deviceSource] | @csv' -r devices.json | \
+ // sed 's/,/, /g; s/^/ZeppOsDeviceInfo(/; s/$/),/'
// TODO: A few are missing: mi band 7, amazfit band 7, amazfit gtr mini
val DEVICE_SOURCES = listOf(
ZeppOsDeviceInfo(94, 256, 224),
@@ -15,6 +16,13 @@ object ZeppOsDeviceSources {
ZeppOsDeviceInfo(115, 259, 247),
ZeppOsDeviceInfo(116, 257, 251),
ZeppOsDeviceInfo(117, 259, 254),
+ ZeppOsDeviceInfo(103, 256, 260),
+ ZeppOsDeviceInfo(103, 257, 261),
+ ZeppOsDeviceInfo(103, 258, 262),
+ ZeppOsDeviceInfo(103, 259, 263),
+ ZeppOsDeviceInfo(103, 260, 264),
+ ZeppOsDeviceInfo(103, 261, 265),
+ ZeppOsDeviceInfo(103, 262, 266),
ZeppOsDeviceInfo(63, 256, 414),
ZeppOsDeviceInfo(63, 257, 415),
ZeppOsDeviceInfo(113, 256, 418),
@@ -22,6 +30,7 @@ object ZeppOsDeviceSources {
ZeppOsDeviceInfo(93, 258, 6095106),
ZeppOsDeviceInfo(100, 256, 6553856),
ZeppOsDeviceInfo(100, 257, 6553857),
+ ZeppOsDeviceInfo(103, 263, 6750471),
ZeppOsDeviceInfo(120, 257, 7864577),
ZeppOsDeviceInfo(121, 256, 7930112),
ZeppOsDeviceInfo(121, 257, 7930113),
@@ -82,6 +91,13 @@ object ZeppOsDeviceSources {
ZeppOsDeviceInfo(163, 259, 10682627),
ZeppOsDeviceInfo(165, 257, 10813697),
ZeppOsDeviceInfo(165, 259, 10813699),
+ ZeppOsDeviceInfo(166, 256, 10879232),
+ ZeppOsDeviceInfo(166, 257, 10879233),
+ ZeppOsDeviceInfo(166, 259, 10879235),
+ ZeppOsDeviceInfo(167, 256, 10944768),
+ ZeppOsDeviceInfo(167, 257, 10944769),
+ ZeppOsDeviceInfo(167, 259, 10944771),
+ ZeppOsDeviceInfo(167, 4355, 10948867),
)
fun resolve(productId: Int, productVersion: Int): ZeppOsDeviceInfo? {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8958f57029..c057802467 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1907,10 +1907,12 @@
Amazfit Active 2 (Round)
Amazfit Active 2 (Square)
Amazfit Active 2 NFC
+ Amazfit Active 3 Premium
Amazfit Active Edge
Amazfit Cheetah (Square)
Amazfit Cheetah (Round)
Amazfit Cheetah Pro
+ Amazfit Cheetah 2 Pro
Amazfit GTS 3
Amazfit GTS 4
Amazfit GTS 4 Mini
@@ -1929,6 +1931,7 @@
Amazfit T-Rex 3 Pro (44mm)
Amazfit T-Rex 3 Pro (48mm)
Amazfit T-Rex Ultra
+ Amazfit T-Rex Ultra 2
Amazfit Band 5
Amazfit Band 7
Amazfit Neo
diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml
index 2e00f54cda..1531373357 100644
--- a/app/src/main/res/xml/changelog_master.xml
+++ b/app/src/main/res/xml/changelog_master.xml
@@ -10,6 +10,7 @@
Initial support for Redmi Buds 8 Active
Initial support for iTECH Active 3 (MoYoung / Da Fit)
Initial support for ZL02D (MoYoung / Da Fit)
+ Experimental support for Amazfit Active 3 Premium, Cheetah 2 Pro, T-Rex Ultra 2
Experimental support for Sony WH-1000XM6
Add and adjust default sleep range to 18:00
Add auto export of gpx files
diff --git a/src/mainline/fastlane/metadata/android/en-US/changelogs/247.txt b/src/mainline/fastlane/metadata/android/en-US/changelogs/247.txt
index a24cb3cf41..345e8ddb3d 100644
--- a/src/mainline/fastlane/metadata/android/en-US/changelogs/247.txt
+++ b/src/mainline/fastlane/metadata/android/en-US/changelogs/247.txt
@@ -1,4 +1,4 @@
-• Support for 14 new devices
+• Support for 17 new devices
• Auto export of GPX files
• FossWallet support
• Fossil Q: extensive improvements - find device, vibrate on call, hand calibration, button actions, music/volume control, and more