mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-24 17:45:50 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
0845d15ba2
@ -2313,15 +2313,24 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisplayItemsNew(TransactionBuilder builder, int defaultSettings, Map<String, Integer> keyIdMap) {
|
||||
protected HuamiSupport setDisplayItemsNew(TransactionBuilder builder, boolean isShortcuts, int defaultSettings, Map<String, Integer> keyIdMap) {
|
||||
if (gbDevice.getFirmwareVersion() == null) {
|
||||
LOG.warn("Device not initialized yet, won't set menu items");
|
||||
return this;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
Set<String> pages = prefs.getStringSet(HuamiConst.PREF_DISPLAY_ITEMS, new HashSet<>(Arrays.asList(getContext().getResources().getStringArray(defaultSettings))));
|
||||
LOG.info("Setting display items to " + (pages == null ? "none" : pages));
|
||||
Set<String> pages;
|
||||
byte menuType;
|
||||
if (isShortcuts) {
|
||||
menuType = (byte) 0xfd;
|
||||
pages = prefs.getStringSet(HuamiConst.PREF_SHORTCUTS, new HashSet<>(Arrays.asList(getContext().getResources().getStringArray(R.array.pref_bips_shortcuts_default))));
|
||||
LOG.info("Setting shortcuts to " + (pages == null ? "none" : pages));
|
||||
} else {
|
||||
menuType = (byte) 0xff;
|
||||
pages = prefs.getStringSet(HuamiConst.PREF_DISPLAY_ITEMS, new HashSet<>(Arrays.asList(getContext().getResources().getStringArray(defaultSettings))));
|
||||
LOG.info("Setting display items to " + (pages == null ? "none" : pages));
|
||||
}
|
||||
|
||||
if (pages != null) {
|
||||
byte[] command = new byte[keyIdMap.size() * 4 + 1];
|
||||
@ -2336,7 +2345,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
||||
if (pages.contains(key)) {
|
||||
command[pos++] = (byte) index++;
|
||||
command[pos++] = 0x00;
|
||||
command[pos++] = (byte) 0xff;
|
||||
command[pos++] = menuType;
|
||||
command[pos++] = (byte) id;
|
||||
}
|
||||
}
|
||||
@ -2348,7 +2357,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
||||
if (!pages.contains(key)) {
|
||||
command[pos++] = (byte) index++;
|
||||
command[pos++] = 0x01;
|
||||
command[pos++] = (byte) 0xff;
|
||||
command[pos++] = (byte) menuType;
|
||||
command[pos++] = (byte) id;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class AmazfitBand5Support extends MiBand5Support {
|
||||
keyIdMap.put("stress", 0x1c);
|
||||
keyIdMap.put("cycles", 0x1d);
|
||||
|
||||
setDisplayItemsNew(builder, R.array.pref_amazfitband5_display_items_default, keyIdMap);
|
||||
setDisplayItemsNew(builder, false, R.array.pref_amazfitband5_display_items_default, keyIdMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -132,59 +132,22 @@ public class AmazfitBipSSupport extends AmazfitBipSupport {
|
||||
keyIdMap.put("music", 0x0b);
|
||||
keyIdMap.put("settings", 0x13);
|
||||
|
||||
setDisplayItemsNew(builder, R.array.pref_bips_display_items_default, keyIdMap);
|
||||
setDisplayItemsNew(builder, false, R.array.pref_bips_display_items_default, keyIdMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitBipSSupport setShortcuts(TransactionBuilder builder) {
|
||||
if (gbDevice.getFirmwareVersion() == null) {
|
||||
LOG.warn("Device not initialized yet, won't set shortcuts");
|
||||
return this;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
Set<String> pages = prefs.getStringSet(HuamiConst.PREF_SHORTCUTS, new HashSet<>(Arrays.asList(getContext().getResources().getStringArray(R.array.pref_bips_shortcuts_default))));
|
||||
LOG.info("Setting shortcuts to " + (pages == null ? "none" : pages));
|
||||
byte[] command = new byte[]{
|
||||
0x1E,
|
||||
0x00, 0x00, (byte) 0xFD, 0x01, // Status
|
||||
0x01, 0x00, (byte) 0xFD, 0x11, // Alipay
|
||||
0x02, 0x00, (byte) 0xFD, 0x10, // NFC
|
||||
0x03, 0x00, (byte) 0xFD, 0x19, // PAI
|
||||
0x04, 0x00, (byte) 0xFD, 0x02, // HR
|
||||
0x05, 0x00, (byte) 0xFD, 0x0B, // Music
|
||||
0x06, 0x00, (byte) 0xFD, 0x04, // Weather
|
||||
};
|
||||
|
||||
String[] keys = {"status", "alipay", "nfc", "pai", "hr", "music", "weather"};
|
||||
byte[] ids = {1, 17, 16, 25, 2, 11, 4};
|
||||
|
||||
if (pages != null) {
|
||||
// it seem that we first have to put all ENABLED items into the array
|
||||
int pos = 1;
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
String key = keys[i];
|
||||
byte id = ids[i];
|
||||
if (pages.contains(key)) {
|
||||
command[pos + 1] = 0x00;
|
||||
command[pos + 3] = id;
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
// And then all DISABLED ones
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
String key = keys[i];
|
||||
byte id = ids[i];
|
||||
if (!pages.contains(key)) {
|
||||
command[pos + 1] = 0x01;
|
||||
command[pos + 3] = id;
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
writeToChunked(builder, 2, command);
|
||||
}
|
||||
Map<String, Integer> keyIdMap = new LinkedHashMap<>();
|
||||
keyIdMap.put("status", 0x01);
|
||||
keyIdMap.put("alipay", 0x11);
|
||||
keyIdMap.put("nfc", 0x10);
|
||||
keyIdMap.put("pai", 0x19);
|
||||
keyIdMap.put("hr", 0x02);
|
||||
keyIdMap.put("music", 0x0b);
|
||||
keyIdMap.put("weather", 0x04);
|
||||
|
||||
setDisplayItemsNew(builder, true, R.array.pref_bips_display_items_default, keyIdMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class AmazfitGTSSupport extends AmazfitBipSupport {
|
||||
keyIdMap.put("more", 0x07);
|
||||
keyIdMap.put("settings", 0x13);
|
||||
|
||||
setDisplayItemsNew(builder, R.array.pref_gts_display_items_default, keyIdMap);
|
||||
setDisplayItemsNew(builder, false, R.array.pref_gts_display_items_default, keyIdMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class MiBand5Support extends MiBand4Support {
|
||||
keyIdMap.put("stress", 0x1c);
|
||||
keyIdMap.put("cycles", 0x1d);
|
||||
|
||||
setDisplayItemsNew(builder, R.array.pref_miband5_display_items_default, keyIdMap);
|
||||
setDisplayItemsNew(builder, false, R.array.pref_miband5_display_items_default, keyIdMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,8 @@ import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
@ -57,6 +59,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Weather;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
|
||||
@ -134,6 +137,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
try {
|
||||
getSecretKey();
|
||||
} catch (IllegalAccessException e) {
|
||||
GB.toast("erro getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
new TransactionBuilder("init fail")
|
||||
.add(new SetDeviceStateAction(getDeviceSupport().getDevice(), GBDevice.State.AUTHENTICATION_REQUIRED, getContext()))
|
||||
.queue(getDeviceSupport().getQueue());
|
||||
return;
|
||||
}
|
||||
|
||||
saveRawActivityFiles = getDeviceSpecificPreferences().getBoolean("save_raw_activity_files", false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
@ -573,10 +586,26 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
}
|
||||
|
||||
private void negotiateSymmetricKey() {
|
||||
queueWrite(new VerifyPrivateKeyRequest(
|
||||
this.getSecretKey(),
|
||||
this
|
||||
));
|
||||
try {
|
||||
queueWrite(new VerifyPrivateKeyRequest(
|
||||
this.getSecretKey(),
|
||||
this
|
||||
));
|
||||
} catch (IllegalAccessException e) {
|
||||
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
getDeviceSupport().getDevice().setState(GBDevice.State.AUTHENTICATION_REQUIRED);
|
||||
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
|
||||
getDeviceSupport().getQueue().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void toast(final String data){
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(getContext(), data, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -628,7 +657,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
public void onFetchActivityData() {
|
||||
syncSettings();
|
||||
|
||||
queueWrite(new VerifyPrivateKeyRequest(this.getSecretKey(), this));
|
||||
negotiateSymmetricKey();
|
||||
queueWrite(new FileLookupRequest(FileHandle.ACTIVITY_FILE, this) {
|
||||
@Override
|
||||
public void handleFileLookup(final short fileHandle) {
|
||||
@ -948,17 +977,20 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
}
|
||||
|
||||
|
||||
public byte[] getSecretKey() {
|
||||
public byte[] getSecretKey() throws IllegalAccessException {
|
||||
byte[] authKeyBytes = new byte[16];
|
||||
|
||||
SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(getDeviceSupport().getDevice().getAddress());
|
||||
|
||||
String authKey = sharedPrefs.getString("authkey", null);
|
||||
if (authKey != null && !authKey.isEmpty()) {
|
||||
byte[] srcBytes = authKey.trim().getBytes();
|
||||
if (authKey.length() == 34 && authKey.startsWith("0x")) {
|
||||
srcBytes = GB.hexStringToByteArray(authKey.substring(2));
|
||||
authKey = authKey.replace(" ", "");
|
||||
authKey = authKey.replace("0x", "");
|
||||
if(authKey.length() != 32){
|
||||
throw new IllegalAccessException("Key should be 16 bytes long as hex string");
|
||||
}
|
||||
byte[] srcBytes = GB.hexStringToByteArray(authKey);
|
||||
|
||||
System.arraycopy(srcBytes, 0, authKeyBytes, 0, Math.min(srcBytes.length, 16));
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@ -38,6 +39,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.foss
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CRC32C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public abstract class FileEncryptedGetRequest extends FossilRequest {
|
||||
private short handle;
|
||||
@ -72,7 +74,12 @@ public abstract class FileEncryptedGetRequest extends FossilRequest {
|
||||
private void initDecryption() {
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES/CTR/NoPadding");
|
||||
keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
|
||||
try {
|
||||
keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
|
||||
} catch (IllegalAccessException e) {
|
||||
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
iv = new byte[16];
|
||||
|
@ -91,7 +91,13 @@ public class FileEncryptedPutRequest extends FossilRequest {
|
||||
|
||||
this.prepareFilePackets(this.file);
|
||||
|
||||
SecretKeySpec keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
|
||||
SecretKeySpec keySpec = null;
|
||||
try {
|
||||
keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
|
||||
} catch (IllegalAccessException e) {
|
||||
GB.toast("error getting key: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user