diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUCoordinator.java new file mode 100644 index 000000000..e79baeb2f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUCoordinator.java @@ -0,0 +1,105 @@ +/* Copyright (C) 2017-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti, João Paulo Barraca, Nephiel, vanous + + 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.amazfitbipu; + +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.R; +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +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 AmazfitBipUCoordinator extends HuamiCoordinator { + private static final Logger LOG = LoggerFactory.getLogger(AmazfitBipUCoordinator.class); + + @Override + public DeviceType getDeviceType() { + return DeviceType.AMAZFITBIPU; + } + + @NonNull + @Override + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + try { + BluetoothDevice device = candidate.getDevice(); + String name = device.getName(); + if (name != null && (name.equalsIgnoreCase("Amazfit Bip U"))) { + return DeviceType.AMAZFITBIPU; + } + } catch (Exception ex) { + LOG.error("unable to check device support", ex); + } + return DeviceType.UNKNOWN; + } + + @Override + public InstallHandler findInstallHandler(Uri uri, Context context) { + AmazfitBipUFWInstallHandler handler = new AmazfitBipUFWInstallHandler(uri, context); + return handler.isValid() ? handler : null; + } + + @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; + } + + @Override + public int[] getSupportedDeviceSpecificSettings(GBDevice device) { + return new int[]{ + R.xml.devicesettings_amazfitbips, + R.xml.devicesettings_timeformat, + R.xml.devicesettings_wearlocation, + R.xml.devicesettings_custom_emoji_font, + R.xml.devicesettings_liftwrist_display, + R.xml.devicesettings_sync_calendar, + R.xml.devicesettings_expose_hr_thirdparty, + R.xml.devicesettings_high_mtu, + R.xml.devicesettings_device_actions, + R.xml.devicesettings_pairingkey + }; + } + + @Override + public int getBondingStyle() { + return BONDING_STYLE_REQUIRE_KEY; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWHelper.java new file mode 100644 index 000000000..06b2abae2 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWHelper.java @@ -0,0 +1,40 @@ +/* Copyright (C) 2020 Andreas Shimokawa + + 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.amazfitbipu; + +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.amazfitbipu.AmazfitBipUFirmwareInfo; + +public class AmazfitBipUFWHelper extends HuamiFWHelper { + + public AmazfitBipUFWHelper(Uri uri, Context context) throws IOException { + super(uri, context); + } + + @Override + protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) { + firmwareInfo = new AmazfitBipUFirmwareInfo(wholeFirmwareBytes); + if (!firmwareInfo.isHeaderValid()) { + throw new IllegalArgumentException("Not a an Amazfit Bip U firmware"); + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWInstallHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWInstallHandler.java new file mode 100644 index 000000000..e0d8fce9b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbipu/AmazfitBipUFWInstallHandler.java @@ -0,0 +1,49 @@ +/* Copyright (C) 2020 Andreas Shimokawa + + 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.amazfitbipu; + +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 AmazfitBipUFWInstallHandler extends AbstractMiBandFWInstallHandler { + AmazfitBipUFWInstallHandler(Uri uri, Context context) { + super(uri, context); + } + + @Override + protected String getFwUpgradeNotice() { + return mContext.getString(R.string.fw_upgrade_notice_amazfitbip, helper.getHumanFirmwareVersion()); + } + + @Override + protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException { + return new AmazfitBipUFWHelper(uri, context); + } + + @Override + protected boolean isSupportedDeviceType(GBDevice device) { + return device.getType() == DeviceType.AMAZFITBIPU; + } +} 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 4fa9851c4..874e919b0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -52,6 +52,7 @@ public enum DeviceType { AMAZFITBIPS_LITE(25, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_bips_lite), AMAZFITGTR2(26, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_amazfit_gtr2), AMAZFITGTS2(27, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_gts2), + AMAZFITBIPU(28, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_bipu), LIVEVIEW(30, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_liveview), 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), @@ -85,6 +86,7 @@ public enum DeviceType { VIBRATISSIMO(300, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo), SONY_SWR12(310, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_sonyswr12), TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_test); + private final int key; @DrawableRes private final int defaultIcon; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUFirmwareInfo.java new file mode 100644 index 000000000..c86c263ee --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUFirmwareInfo.java @@ -0,0 +1,93 @@ +/* Copyright (C) 2020 Andreas Shimokawa + + 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.amazfitbipu; + +import java.util.HashMap; +import java.util.Map; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +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.service.devices.huami.miband4.MiBand4FirmwareInfo; +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; + +public class AmazfitBipUFirmwareInfo extends HuamiFirmwareInfo { + + private static Map crcToVersion = new HashMap<>(); + + static { + // no known fw yet + } + + public AmazfitBipUFirmwareInfo(byte[] bytes) { + super(bytes); + } + + @Override + protected HuamiFirmwareType determineFirmwareType(byte[] bytes) { + + GBDevice device = GBApplication.app().getDeviceManager().getSelectedDevice(); + + if (ArrayUtils.equals(bytes, MiBand4FirmwareInfo.FW_HEADER, MiBand4FirmwareInfo.FW_HEADER_OFFSET)) { + if (searchString32BitAligned(bytes, "Amazfit Bip U")) { + return HuamiFirmwareType.FIRMWARE; + } + return HuamiFirmwareType.INVALID; + + } + + if (ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET) || + ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET_NEW)) { + return HuamiFirmwareType.RES_COMPRESSED; + } + + if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER)) { + return HuamiFirmwareType.WATCHFACE; + } + if (ArrayUtils.startsWith(bytes, GPS_ALMANAC_HEADER)) { + return HuamiFirmwareType.GPS_ALMANAC; + } + if (ArrayUtils.startsWith(bytes, GPS_CEP_HEADER)) { + return HuamiFirmwareType.GPS_CEP; + } + if (ArrayUtils.startsWith(bytes, NEWFT_HEADER)) { + if (bytes[10] == 0x01 || bytes[10] == 0x06 || bytes[10] == 0x03) { + return HuamiFirmwareType.FONT; + } else if (bytes[10] == 0x02 || bytes[10] == 0x0A) { + return HuamiFirmwareType.FONT_LATIN; + } + } + 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.AMAZFITBIPU; + } + + @Override + protected Map getCrcMap() { + return crcToVersion; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUSupport.java new file mode 100644 index 000000000..56e20fce5 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbipu/AmazfitBipUSupport.java @@ -0,0 +1,46 @@ +/* Copyright (C) 2017-2020 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.amazfitbipu; + +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.amazfitbipu.AmazfitBipUFWHelper; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbips.AmazfitBipSSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.UpdateFirmwareOperation; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.UpdateFirmwareOperation2020; + +public class AmazfitBipUSupport extends AmazfitBipSSupport { + + @Override + public boolean supportsSunriseSunsetWindHumidity() { + return true; + } + + @Override + public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException { + return new AmazfitBipUFWHelper(uri, context); + } + + @Override + public UpdateFirmwareOperation createUpdateFirmwareOperation(Uri uri) { + return new UpdateFirmwareOperation2020(uri, this); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d230dd02..a87597b7a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -785,6 +785,7 @@ Amazfit T-Rex Amazfit Bip S Amazfit Bip S Lite + Amazfit Bip U Amazfit GTR 2 Amazfit GTS 2 Vibratissimo