Amazfit Bip: Initial experimental firmware update support
USE AT YOUR OWN RISK: NOTE: During update your device is named a Mi Band 1) Flash .gps (installation will take a while after transfer) 2) Flash .res 3) Flash .fw (device will reboot) 4) Gadgetbridge wont notice that update was successfull, known bug.
This commit is contained in:
parent
ebc1cedf55
commit
12d9b7812f
|
@ -52,10 +52,9 @@ public class AmazfitBipCooordinator extends MiBand2Coordinator {
|
|||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InstallHandler findInstallHandler(Uri uri, Context context) {
|
||||
return null; // not supported yet
|
||||
AmazfitBipFWInstallHandler handler = new AmazfitBipFWInstallHandler(uri, context);
|
||||
return handler.isValid() ? handler : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* Copyright (C) 2016-2017 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 <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipFirmwareInfo;
|
||||
|
||||
public class AmazfitBipFWHelper extends AbstractMiBandFWHelper {
|
||||
|
||||
public AmazfitBipFWHelper(Uri uri, Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
private AmazfitBipFirmwareInfo firmwareInfo;
|
||||
|
||||
@Override
|
||||
public String format(int version) {
|
||||
return AmazfitBipFirmwareInfo.toVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmwareVersion() {
|
||||
return firmwareInfo.getFirmwareVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmware2Version() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHumanFirmwareVersion2() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getWhitelistedFirmwareVersions() {
|
||||
return AmazfitBipFirmwareInfo.getWhitelistedVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
|
||||
return firmwareInfo.isGenerallyCompatibleWith(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFirmware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) {
|
||||
firmwareInfo = new AmazfitBipFirmwareInfo(wholeFirmwareBytes);
|
||||
if (!firmwareInfo.isHeaderValid()) {
|
||||
throw new IllegalArgumentException("Not a an Amazifit Bip firmware");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
firmwareInfo.checkValid();
|
||||
}
|
||||
|
||||
public AmazfitBipFirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright (C) 2016-2017 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 <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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 AmazfitBipFWInstallHandler extends AbstractMiBandFWInstallHandler {
|
||||
AmazfitBipFWInstallHandler(Uri uri, Context context) {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException {
|
||||
return new AmazfitBipFWHelper(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedDeviceType(GBDevice device) {
|
||||
return device.getType() == DeviceType.AMAZFITBIP;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* Copyright (C) 2016-2017 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 <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.FirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
|
||||
public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
// total crap maybe
|
||||
private static final byte[] GPS_HEADER = new byte[]{
|
||||
(byte) 0xcb, 0x51, (byte) 0xc1, 0x30, 0x41, (byte) 0x9e, 0x5e, (byte) 0xd3,
|
||||
0x51, 0x35, (byte) 0xdf, 0x66, (byte) 0xed, (byte) 0xd9, 0x5f, (byte) 0xa7
|
||||
};
|
||||
|
||||
// guessed - at least it is the same accross current versions and different from other devices
|
||||
private static final byte[] FW_HEADER = new byte[]{
|
||||
0x3f, 0x34, 0x00, 0x20, 0x27, 0x35, 0x00, 0x20,
|
||||
0x0d, 0x31, 0x03, 0x00, 0x15, 0x35, 0x00, 0x20
|
||||
};
|
||||
|
||||
private static final int FW_HEADER_OFFSET = 0x40;
|
||||
|
||||
private static final byte[] RES_HEADER = new byte[]{ // HMRES resources file (*.res)
|
||||
0x48, 0x4d, 0x52, 0x45, 0x53
|
||||
};
|
||||
|
||||
|
||||
static {
|
||||
// firmware
|
||||
crcToVersion.put(25257, "0.0.8.74");
|
||||
|
||||
// resources
|
||||
crcToVersion.put(12586, "0.0.8.74 (RES)");
|
||||
|
||||
// gps
|
||||
}
|
||||
|
||||
public AmazfitBipFirmwareInfo(byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FirmwareType determineFirmwareType(byte[] bytes) {
|
||||
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
|
||||
return FirmwareType.RES;
|
||||
}
|
||||
if (ArrayUtils.startsWith(bytes, GPS_HEADER)) {
|
||||
return FirmwareType.GPS;
|
||||
}
|
||||
if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET)) {
|
||||
// TODO: this is certainly not a correct validation, but it works for now
|
||||
return FirmwareType.FIRMWARE;
|
||||
}
|
||||
return FirmwareType.INVALID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerallyCompatibleWith(GBDevice device) {
|
||||
return isHeaderValid() && device.getType() == DeviceType.AMAZFITBIP;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,9 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -35,8 +38,10 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
|||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipUpdateFirmwareOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
public class AmazfitBipSupport extends MiBand2Support {
|
||||
|
@ -113,6 +118,14 @@ public class AmazfitBipSupport extends MiBand2Support {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onInstallApp(Uri uri) {
|
||||
try {
|
||||
new AmazfitBipUpdateFirmwareOperation(uri, this).perform();
|
||||
} catch (IOException ex) {
|
||||
GB.toast(getContext(), "Firmware cannot be installed: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void onSendWeather(WeatherSpec weatherSpec) {
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("Sending weather forecast");
|
||||
|
|
|
@ -19,8 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2;
|
|||
public enum FirmwareType {
|
||||
FIRMWARE((byte) 0),
|
||||
FONT((byte) 1),
|
||||
UNKNOWN1((byte) 2),
|
||||
UNKNOWN2((byte) 3),
|
||||
RES((byte) 2),
|
||||
GPS((byte) 3),
|
||||
INVALID(Byte.MIN_VALUE);
|
||||
|
||||
private final byte value;
|
||||
|
|
|
@ -53,7 +53,7 @@ public class Mi2FirmwareInfo {
|
|||
0x4b
|
||||
};
|
||||
|
||||
private static Map<Integer,String> crcToVersion = new HashMap<>();
|
||||
protected static Map<Integer,String> crcToVersion = new HashMap<>();
|
||||
static {
|
||||
// firmware
|
||||
crcToVersion.put(41899, "1.0.0.39");
|
||||
|
@ -89,7 +89,7 @@ public class Mi2FirmwareInfo {
|
|||
firmwareType = determineFirmwareType(bytes);
|
||||
}
|
||||
|
||||
private FirmwareType determineFirmwareType(byte[] bytes) {
|
||||
protected FirmwareType determineFirmwareType(byte[] bytes) {
|
||||
if (ArrayUtils.startsWith(bytes, FT_HEADER)) {
|
||||
return FirmwareType.FONT;
|
||||
}
|
||||
|
|
|
@ -49,10 +49,10 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
|||
private static final Logger LOG = LoggerFactory.getLogger(UpdateFirmwareOperation.class);
|
||||
|
||||
private final Uri uri;
|
||||
private final BluetoothGattCharacteristic fwCControlChar;
|
||||
private final BluetoothGattCharacteristic fwCDataChar;
|
||||
final Prefs prefs = GBApplication.getPrefs();
|
||||
private Mi2FirmwareInfo firmwareInfo;
|
||||
protected final BluetoothGattCharacteristic fwCControlChar;
|
||||
protected final BluetoothGattCharacteristic fwCDataChar;
|
||||
protected final Prefs prefs = GBApplication.getPrefs();
|
||||
protected Mi2FirmwareInfo firmwareInfo;
|
||||
|
||||
public UpdateFirmwareOperation(Uri uri, MiBand2Support support) {
|
||||
super(support);
|
||||
|
|
Loading…
Reference in New Issue