diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java index 568c167fc..352353451 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java @@ -26,12 +26,14 @@ import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; -import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; -public class AmazfitGTRCoordinator extends AmazfitBipCoordinator { +public class AmazfitGTRCoordinator extends HuamiCoordinator { private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTRCoordinator.class); @Override @@ -64,4 +66,34 @@ public class AmazfitGTRCoordinator extends AmazfitBipCoordinator { public int getBondingStyle() { return BONDING_STYLE_REQUIRE_KEY; } + + @Override + public boolean supportsHeartRateMeasurement(GBDevice device) { + return true; + } + + @Override + public boolean supportsActivityTracks() { + return true; + } + + @Override + public boolean supportsWeather() { + return true; + } + + @Override + public boolean supportsMusicInfo() { + return true; + } + public int[] getSupportedDeviceSpecificSettings(GBDevice device) { + return new int[]{ + R.xml.devicesettings_amazfitgtr, + R.xml.devicesettings_wearlocation, + R.xml.devicesettings_liftwrist_display, + R.xml.devicesettings_disconnectnotification, + R.xml.devicesettings_expose_hr_thirdparty, + R.xml.devicesettings_pairingkey + }; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRFWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRFWHelper.java index ea770d694..a24d8e26e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRFWHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRFWHelper.java @@ -33,7 +33,6 @@ public class AmazfitGTRFWHelper extends HuamiFWHelper { super(uri, context); } - @NonNull @Override protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) { firmwareInfo = new AmazfitGTRFirmwareInfo(wholeFirmwareBytes); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java index 7f9414456..cd13cbc87 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java @@ -9,6 +9,7 @@ import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; @@ -18,6 +19,11 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; public class AmazfitGTSCoordinator extends HuamiCoordinator { private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTSCoordinator.class); + @Override + public DeviceType getDeviceType() { + return DeviceType.AMAZFITGTS; + } + @NonNull @Override public DeviceType getSupportedType(GBDeviceCandidate candidate) { @@ -34,8 +40,9 @@ public class AmazfitGTSCoordinator extends HuamiCoordinator { } @Override - public DeviceType getDeviceType() { - return DeviceType.AMAZFITGTS; + public InstallHandler findInstallHandler(Uri uri, Context context) { + AmazfitGTSFWInstallHandler handler = new AmazfitGTSFWInstallHandler(uri, context); + return handler.isValid() ? handler : null; } @Override @@ -43,11 +50,6 @@ public class AmazfitGTSCoordinator extends HuamiCoordinator { return BONDING_STYLE_REQUIRE_KEY; } - @Override - public InstallHandler findInstallHandler(Uri uri, Context context) { - return null; - } - @Override public boolean supportsHeartRateMeasurement(GBDevice device) { return true; @@ -68,4 +70,14 @@ public class AmazfitGTSCoordinator extends HuamiCoordinator { return true; } + public int[] getSupportedDeviceSpecificSettings(GBDevice device) { + return new int[]{ + R.xml.devicesettings_amazfitgtr, + R.xml.devicesettings_wearlocation, + R.xml.devicesettings_liftwrist_display, + R.xml.devicesettings_disconnectnotification, + R.xml.devicesettings_expose_hr_thirdparty, + R.xml.devicesettings_pairingkey + }; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWHelper.java new file mode 100644 index 000000000..78a9a2c5b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWHelper.java @@ -0,0 +1,41 @@ +/* Copyright (C) 2016-2019 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + + 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.amazfitgts; + +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.amazfitgts.AmazfitGTSFirmwareInfo; + +public class AmazfitGTSFWHelper extends HuamiFWHelper { + + public AmazfitGTSFWHelper(Uri uri, Context context) throws IOException { + super(uri, context); + } + + @Override + protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) { + firmwareInfo = new AmazfitGTSFirmwareInfo(wholeFirmwareBytes); + if (!firmwareInfo.isHeaderValid()) { + throw new IllegalArgumentException("Not a an Amazifit GTS firmware"); + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWInstallHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWInstallHandler.java new file mode 100644 index 000000000..8b0957ddf --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSFWInstallHandler.java @@ -0,0 +1,50 @@ +/* Copyright (C) 2015-2019 Andreas Shimokawa, Carsten Pfeiffer + + 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.amazfitgts; + +import android.content.Context; +import android.net.Uri; + +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRFWHelper; +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 AmazfitGTSFWInstallHandler extends AbstractMiBandFWInstallHandler { + AmazfitGTSFWInstallHandler(Uri uri, Context context) { + super(uri, context); + } + + @Override + protected String getFwUpgradeNotice() { + return mContext.getString(R.string.fw_upgrade_notice_amazfitgts, helper.getHumanFirmwareVersion()); + } + + @Override + protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException { + return new AmazfitGTRFWHelper(uri, context); + } + + @Override + protected boolean isSupportedDeviceType(GBDevice device) { + return device.getType() == DeviceType.AMAZFITGTS; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index bf728fdc8..92c0e49c9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -1645,11 +1645,11 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { LOG.warn("Device not initialized yet, so not sending weather info"); return; } - boolean supportsConditionString = false; + boolean supportsConditionString = true; Version version = new Version(gbDevice.getFirmwareVersion()); - if (version.compareTo(new Version("0.0.8.74")) >= 0) { - supportsConditionString = true; + if (gbDevice.getType() == DeviceType.AMAZFITBIP && version.compareTo(new Version("0.0.8.74")) < 0) { + supportsConditionString = false; } MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr/AmazfitGTRFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr/AmazfitGTRFirmwareInfo.java index d4830455b..4c15f6b9e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr/AmazfitGTRFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgtr/AmazfitGTRFirmwareInfo.java @@ -26,10 +26,10 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareT import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; public class AmazfitGTRFirmwareInfo extends HuamiFirmwareInfo { - private static final int FW_OFFSET = 2; + private static final int FW_OFFSET = 3; private static final byte[] FW_HEADER = new byte[]{ - 0x09, 0x20, (byte) 0x99, 0x12, 0x01, 0x08 // completely nonsense probably + 0x20, (byte) 0x99, 0x12, 0x01, 0x08 // completely nonsense probably }; private static final byte[] GPS_ALMANAC_HEADER = new byte[]{ // probably wrong diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSFirmwareInfo.java new file mode 100644 index 000000000..d61e3bec0 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSFirmwareInfo.java @@ -0,0 +1,116 @@ +/* Copyright (C) 2017-2019 Andreas Shimokawa, Carsten Pfeiffer + + 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.amazfitgts; + +import java.util.HashMap; +import java.util.Map; + +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType; +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; + +public class AmazfitGTSFirmwareInfo extends HuamiFirmwareInfo { + private static final int FW_OFFSET = 3; + + private static final byte[] FW_HEADER = new byte[]{ + 0x20, (byte) 0x99, 0x12, 0x01, 0x08 // completely nonsense probably + }; + + private static final byte[] GPS_ALMANAC_HEADER = new byte[]{ // probably wrong + (byte) 0xa0, (byte) 0x80, 0x08, 0x00, (byte) 0x8b, 0x07 + }; + + private static final byte[] GPS_CEP_HEADER = new byte[]{ // probably wrong + 0x2a, 0x12, (byte) 0xa0, 0x02 + }; + + // gps detection is totally bogus, just the first 16 bytes + private static final byte[][] GPS_HEADERS = { + new byte[]{ + 0x73, 0x75, 0x68, (byte) 0xd0, 0x70, 0x73, (byte) 0xbb, 0x5a, + 0x3e, (byte) 0xc3, (byte) 0xd3, 0x09, (byte) 0x9e, 0x1d, (byte) 0xd3, (byte) 0xc9 + } + }; + private static Map crcToVersion = new HashMap<>(); + + static { + // firmware + + // Latin Firmware + + // resources + + // font + + // gps + crcToVersion.put(62532, "18344,eb2f43f,126"); + } + + public AmazfitGTSFirmwareInfo(byte[] bytes) { + super(bytes); + } + + @Override + protected HuamiFirmwareType determineFirmwareType(byte[] bytes) { + if (ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET_NEW)) { + return HuamiFirmwareType.RES_COMPRESSED; + } + if (ArrayUtils.equals(bytes, FW_HEADER, FW_OFFSET)) { + if (searchString32BitAligned(bytes, "Amazfit GTS")) { + return HuamiFirmwareType.FIRMWARE; + } + return HuamiFirmwareType.INVALID; + } + if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER)) { + return HuamiFirmwareType.WATCHFACE; + } + if (ArrayUtils.startsWith(bytes, NEWFT_HEADER)) { + if (bytes[10] == 0x01) { + return HuamiFirmwareType.FONT; + } else if (bytes[10] == 0x02) { + return HuamiFirmwareType.FONT_LATIN; + } + } + + if (ArrayUtils.startsWith(bytes, GPS_ALMANAC_HEADER)) { + return HuamiFirmwareType.GPS_ALMANAC; + } + if (ArrayUtils.startsWith(bytes, GPS_CEP_HEADER)) { + return HuamiFirmwareType.GPS_CEP; + } + + for (byte[] gpsHeader : GPS_HEADERS) { + if (ArrayUtils.startsWith(bytes, gpsHeader)) { + return HuamiFirmwareType.GPS; + } + } + + return HuamiFirmwareType.INVALID; + } + + @Override + public boolean isGenerallyCompatibleWith(GBDevice device) { + return isHeaderValid() && device.getType() == DeviceType.AMAZFITGTS; + } + + @Override + protected Map getCrcMap() { + return crcToVersion; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSSupport.java index 8b1fa09ee..bc7fb2dfa 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts/AmazfitGTSSupport.java @@ -1,6 +1,15 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts; +import android.content.Context; +import android.net.Uri; + +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRFWHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSFWHelper; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport; public class AmazfitGTSSupport extends AmazfitBipSupport { @@ -20,4 +29,16 @@ public class AmazfitGTSSupport extends AmazfitBipSupport { super.sendNotificationNew(notificationSpec, true); } + + @Override + public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException { + return new AmazfitGTSFWHelper(uri, context); + } + + @Override + protected AmazfitGTSSupport setDisplayItems(TransactionBuilder builder) { + // not supported yet + return this; + } + } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 60cb70bc3..121563b01 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,7 @@ \n \nCOMPLETELY UNTESTED, PROBABLY YOU NEED TO FLASH A BEATS_W FIRMWARE IF YOUR DEVICE NAME IS \"Amazfit Band 2\" You are about to install the %s firmware on your Amazfit GTR.\n\nPlease make sure to install the .fw file, then the .res file, and finally the .gps file. Your watch will reboot after installing the .fw file.\n\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.\n\nPROCEED AT YOUR OWN RISK! + You are about to install the %s firmware on your Amazfit GTS.\n\nPlease make sure to install the .fw file, then the .res file, and finally the .gps file. Your watch will reboot after installing the .fw file.\n\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.\n\nPROCEED AT YOUR OWN RISK! You are about to install the %s firmware on your Mi Band 3.\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 Mi Band 4.\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 %1$s and %2$s firmware, instead of the ones currently on your Mi Band.