1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 12:56:49 +01:00

Amazfit Cor 2: Give own device type id, support flashing the firmware **UNTESTED**

This commit is contained in:
Andreas Shimokawa 2019-05-09 12:42:59 +02:00
parent 19be1121c9
commit 41e607ce9b
12 changed files with 324 additions and 18 deletions

View File

@ -46,8 +46,7 @@ public class AmazfitCorCoordinator extends HuamiCoordinator {
try {
BluetoothDevice device = candidate.getDevice();
String name = device.getName();
if (name != null && (name.equalsIgnoreCase("Amazfit Band") || name.equalsIgnoreCase("Amazfit Cor")
|| name.equalsIgnoreCase("Amazfit Band 2") || name.equalsIgnoreCase("Amazfit Cor 2"))) {
if (name != null && (name.equalsIgnoreCase("Amazfit Band") || name.equalsIgnoreCase("Amazfit Cor"))) {
return DeviceType.AMAZFITCOR;
}
} catch (Exception ex) {

View File

@ -0,0 +1,83 @@
/* Copyright (C) 2017-2019 Andreas Shimokawa, Daniele Gobbetti, João
Paulo Barraca, Matthieu Baerts
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.huami.amazfitcor2;
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.HuamiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class AmazfitCor2Coordinator extends HuamiCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AmazfitCor2Coordinator.class);
@Override
public DeviceType getDeviceType() {
return DeviceType.AMAZFITCOR2;
}
@NonNull
@Override
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
try {
BluetoothDevice device = candidate.getDevice();
String name = device.getName();
if (name != null && (name.equalsIgnoreCase("Amazfit Band 2") || name.equalsIgnoreCase("Amazfit Cor 2"))) {
return DeviceType.AMAZFITCOR2;
}
} catch (Exception ex) {
LOG.error("unable to check device support", ex);
}
return DeviceType.UNKNOWN;
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
AmazfitCor2FWInstallHandler handler = new AmazfitCor2FWInstallHandler(uri, context);
return handler.isValid() ? handler : null;
}
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return true;
}
@Override
public boolean supportsWeather() {
return true;
}
@Override
public boolean supportsMusicInfo() {
return true;
}
@Override
public boolean supportsUnicodeEmojis() {
return true;
}
}

View File

@ -0,0 +1,40 @@
/* 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor2;
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.amazfitcor2.AmazfitCor2FirmwareInfo;
public class AmazfitCor2FWHelper extends HuamiFWHelper {
public AmazfitCor2FWHelper(Uri uri, Context context) throws IOException {
super(uri, context);
}
@Override
protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) {
firmwareInfo = new AmazfitCor2FirmwareInfo(wholeFirmwareBytes);
if (!firmwareInfo.isHeaderValid()) {
throw new IllegalArgumentException("Not a an Amazfit Cor 2 firmware");
}
}
}

View File

@ -0,0 +1,49 @@
/* 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor2;
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 AmazfitCor2FWInstallHandler extends AbstractMiBandFWInstallHandler {
AmazfitCor2FWInstallHandler(Uri uri, Context context) {
super(uri, context);
}
@Override
protected String getFwUpgradeNotice() {
return mContext.getString(R.string.fw_upgrade_notice_amazfitcor, helper.getHumanFirmwareVersion());
}
@Override
protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException {
return new AmazfitCor2FWHelper(uri, context);
}
@Override
protected boolean isSupportedDeviceType(GBDevice device) {
return device.getType() == DeviceType.AMAZFITCOR2;
}
}

View File

@ -37,6 +37,7 @@ public enum DeviceType {
AMAZFITBIP(12, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_bip),
AMAZFITCOR(13, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_amazfit_cor),
MIBAND3(14, R.drawable.ic_device_miband2, R.drawable.ic_device_miband2_disabled, R.string.devicetype_miband3),
AMAZFITCOR2(15, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_amazfit_cor2),
VIBRATISSIMO(20, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo),
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),

View File

@ -30,6 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor2.AmazfitCor2Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.BFH16DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900.CasioGB6900DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
@ -133,6 +134,9 @@ public class DeviceSupportFactory {
case AMAZFITCOR:
deviceSupport = new ServiceDeviceSupport(new AmazfitCorSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case AMAZFITCOR2:
deviceSupport = new ServiceDeviceSupport(new AmazfitCor2Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case VIBRATISSIMO:
deviceSupport = new ServiceDeviceSupport(new VibratissimoSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;

View File

@ -50,7 +50,7 @@ public abstract class HuamiFirmwareInfo {
protected static final int FONT_TYPE_OFFSET = 0x9;
private HuamiFirmwareType firmwareType = HuamiFirmwareType.FIRMWARE;
private HuamiFirmwareType firmwareType;
public String toVersion(int crc16) {
String version = getCrcMap().get(crc16);
@ -60,16 +60,16 @@ public abstract class HuamiFirmwareInfo {
version = searchFirmwareVersion(bytes);
break;
case RES:
version = "RES " + Integer.toString(bytes[5]);
version = "RES " + bytes[5];
break;
case RES_COMPRESSED:
version = "RES " + Integer.toString(bytes[14]);
version = "RES " + bytes[14];
break;
case FONT:
version = "FONT " + Integer.toString(bytes[4]);
version = "FONT " + bytes[4];
break;
case FONT_LATIN:
version = "FONT LATIN " + Integer.toString(bytes[4]);
version = "FONT LATIN " + bytes[4];
break;
}
}
@ -163,7 +163,7 @@ public abstract class HuamiFirmwareInfo {
if (word == 0x642e2564) {
word = buf.getInt();
if (word == 0x00000000) {
byte version[] = new byte[8];
byte[] version = new byte[8];
buf.get(version);
return new String(version);
}

View File

@ -51,8 +51,8 @@ public class AmazfitCorFirmwareInfo extends HuamiFirmwareInfo {
crcToVersion.put(64977, "RES 1.0.6.76");
crcToVersion.put(60501, "RES 1.0.7.52-71");
crcToVersion.put(31263, "RES 1.0.7.77-91");
crcToVersion.put(20920, "RES 1.2.5.00-65");
crcToVersion.put(25397, "RES 1.2.7.20-69");
crcToVersion.put(20920, "RES 1.2.5.00-69");
crcToVersion.put(25397, "RES 1.2.7.20");
// font
crcToVersion.put(61054, "8");
@ -65,12 +65,6 @@ public class AmazfitCorFirmwareInfo extends HuamiFirmwareInfo {
@Override
protected HuamiFirmwareType determineFirmwareType(byte[] bytes) {
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
if (bytes.length < 700000) { // dont know how to distinguish from Bip .res
return HuamiFirmwareType.INVALID;
}
return HuamiFirmwareType.RES;
}
if (ArrayUtils.equals(bytes, RES_HEADER, COMPRESSED_RES_HEADER_OFFSET) || ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET)) {
return HuamiFirmwareType.RES_COMPRESSED;
}
@ -90,6 +84,9 @@ public class AmazfitCorFirmwareInfo extends HuamiFirmwareInfo {
return HuamiFirmwareType.FONT_LATIN;
}
}
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
return HuamiFirmwareType.RES;
}
return HuamiFirmwareType.INVALID;
}

View File

@ -0,0 +1,90 @@
/* Copyright (C) 2017-2019 Andreas Shimokawa, 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor2;
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 AmazfitCor2FirmwareInfo extends HuamiFirmwareInfo {
// this is the same as Bip
private static final byte[] FW_HEADER = new byte[]{
0x00, (byte) 0x98, 0x00, 0x20, (byte) 0xA5, 0x04, 0x00, 0x20, (byte) 0xAD, 0x04, 0x00, 0x20, (byte) 0xC5, 0x04, 0x00, 0x20
};
private static final int COMPRESSED_RES_HEADER_OFFSET = 0x9;
private static final int COMPRESSED_RES_HEADER_OFFSET_NEW = 0xd;
private static Map<Integer, String> crcToVersion = new HashMap<>();
static {
// font
crcToVersion.put(61054, "8");
crcToVersion.put(62291, "9 (Latin)");
}
public AmazfitCor2FirmwareInfo(byte[] bytes) {
super(bytes);
}
@Override
protected HuamiFirmwareType determineFirmwareType(byte[] bytes) {
if (ArrayUtils.equals(bytes, RES_HEADER, COMPRESSED_RES_HEADER_OFFSET) || ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET_NEW) || ArrayUtils.equals(bytes, NEWRES_HEADER, COMPRESSED_RES_HEADER_OFFSET)) {
return HuamiFirmwareType.RES_COMPRESSED;
}
if (ArrayUtils.startsWith(bytes, FW_HEADER)) {
// FIXME: It would certainly better if we could check for "Cor 2" when the device name is "Cor 2" and for "Band 2" when it is "Band 2"
if (searchString32BitAligned(bytes, "Amazfit Cor 2")) {
return HuamiFirmwareType.FIRMWARE;
}
if (searchString32BitAligned(bytes, "Amazfit Band 2")) {
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;
}
}
// somebody might have unpacked the compressed res
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
return HuamiFirmwareType.RES;
}
return HuamiFirmwareType.INVALID;
}
@Override
public boolean isGenerallyCompatibleWith(GBDevice device) {
return isHeaderValid() && device.getType() == DeviceType.AMAZFITCOR2;
}
@Override
protected Map<Integer, String> getCrcMap() {
return crcToVersion;
}
}

View File

@ -0,0 +1,40 @@
/* 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor2;
import android.content.Context;
import android.net.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor2.AmazfitCor2FWHelper;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor.AmazfitCorSupport;
public class AmazfitCor2Support extends AmazfitCorSupport {
private static final Logger LOG = LoggerFactory.getLogger(AmazfitCor2Support.class);
@Override
public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException {
return new AmazfitCor2FWHelper(uri, context);
}
}

View File

@ -41,7 +41,6 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.jyou.BFH16DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.casiogb6900.CasioGB6900DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.EXRIZUK8Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusCoordinator;
@ -49,15 +48,17 @@ import nodomain.freeyourgadget.gadgetbridge.devices.hplus.MakibesF68Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.Q8Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor.AmazfitCorCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor2.AmazfitCor2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2HRXCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband3.MiBand3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.id115.ID115Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.jyou.BFH16DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miscale2.MiScale2DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miscale2.MiScale2DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.roidmi.Roidmi1Coordinator;
@ -201,6 +202,7 @@ public class DeviceHelper {
result.add(new MiScale2DeviceCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new AmazfitBipCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new AmazfitCorCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new AmazfitCor2Coordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand3Coordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand2HRXCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand2Coordinator()); // Note: MiBand2 must come before MiBand because detection is hacky, atm

View File

@ -621,6 +621,7 @@
<string name="devicetype_miband3">Mi Band 3</string>
<string name="devicetype_amazfit_bip">Amazfit Bip</string>
<string name="devicetype_amazfit_cor">Amazfit Cor</string>
<string name="devicetype_amazfit_cor2">Amazfit Cor 2</string>
<string name="devicetype_vibratissimo">Vibratissimo</string>
<string name="devicetype_liveview">LiveView</string>
<string name="devicetype_hplus">HPlus</string>