mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Zepp OS: Decouple implementation from HuamiSupport
This commit is contained in:
Generated
+3
@@ -5,6 +5,7 @@
|
||||
<w>adhikary</w>
|
||||
<w>afanasev</w>
|
||||
<w>affero</w>
|
||||
<w>agps</w>
|
||||
<w>alaoui</w>
|
||||
<w>alexey</w>
|
||||
<w>alipay</w>
|
||||
@@ -23,6 +24,7 @@
|
||||
<w>bloß</w>
|
||||
<w>boun</w>
|
||||
<w>breathwork</w>
|
||||
<w>btbr</w>
|
||||
<w>böhler</w>
|
||||
<w>carsten</w>
|
||||
<w>chamorro</w>
|
||||
@@ -110,6 +112,7 @@
|
||||
<w>morpheuz</w>
|
||||
<w>mosenkovs</w>
|
||||
<w>multisport</w>
|
||||
<w>nack</w>
|
||||
<w>nephiel</w>
|
||||
<w>nodomain</w>
|
||||
<w>nordhøy</w>
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/* Copyright (C) 2025 José Rebelo
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.preferences.DevicePrefs;
|
||||
|
||||
public class HuamiDevicePrefs extends DevicePrefs {
|
||||
public HuamiDevicePrefs(final SharedPreferences preferences, final GBDevice gbDevice) {
|
||||
super(preferences, gbDevice);
|
||||
}
|
||||
|
||||
public byte getLanguageId() {
|
||||
byte languageCode = 0x02; // english default
|
||||
|
||||
String localeString = getString("language", "auto");
|
||||
if (StringUtils.isBlank(localeString) || localeString.equals("auto")) {
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
String country = Locale.getDefault().getCountry();
|
||||
|
||||
localeString = language + "_" + country.toUpperCase();
|
||||
}
|
||||
|
||||
final Integer id = HuamiLanguageType.idLookup.get(localeString);
|
||||
if (id != null) {
|
||||
languageCode = id.byteValue();
|
||||
}
|
||||
|
||||
return languageCode;
|
||||
}
|
||||
}
|
||||
+67
-159
@@ -117,7 +117,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.SleepState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WearingState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsCannedMessagesService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsWorldClocksService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MediaManager;
|
||||
@@ -168,7 +167,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ACTIVATE_DISPLAY_ON_LIFT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALLOW_HIGH_MTU;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BT_CONNECTED_ADVERTISEMENT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DISPLAY_ON_LIFT_SENSITIVITY;
|
||||
@@ -288,7 +286,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
public void notify(Intent intent) {
|
||||
String s = intent.getAction();
|
||||
if (DeviceInfoProfile.ACTION_DEVICE_INFO.equals(s)) {
|
||||
handleDeviceInfo((nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo) intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO));
|
||||
handleDeviceInfo(intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -296,8 +294,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
protected BluetoothGattCharacteristic characteristicHRControlPoint;
|
||||
private BluetoothGattCharacteristic characteristicChunked;
|
||||
|
||||
protected BluetoothGattCharacteristic characteristicChunked2021Write;
|
||||
protected BluetoothGattCharacteristic characteristicChunked2021Read;
|
||||
private BluetoothGattCharacteristic characteristicChunked2021Write;
|
||||
private BluetoothGattCharacteristic characteristicChunked2021Read;
|
||||
|
||||
private boolean needsAuth;
|
||||
private volatile boolean telephoneRinging;
|
||||
@@ -312,17 +310,16 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
protected MediaManager mediaManager;
|
||||
private boolean heartRateNotifyEnabled;
|
||||
protected static final int MIN_MTU = 23;
|
||||
protected int mMTU = MIN_MTU;
|
||||
private int mMTU = MIN_MTU;
|
||||
// Keep track of the previous MTU before reconnection, so that we can request it after reconnection
|
||||
private int previousMtu = -1;
|
||||
protected int mActivitySampleSize = 4;
|
||||
|
||||
protected Huami2021ChunkedEncoder huami2021ChunkedEncoder;
|
||||
protected Huami2021ChunkedDecoder huami2021ChunkedDecoder;
|
||||
private Huami2021ChunkedEncoder huami2021ChunkedEncoder;
|
||||
private Huami2021ChunkedDecoder huami2021ChunkedDecoder;
|
||||
|
||||
private final HuamiFetcher fetcher = new HuamiFetcher(this);
|
||||
|
||||
protected SleepAsAndroidSender sleepAsAndroidSender;
|
||||
public HuamiSupport() {
|
||||
this(LOG);
|
||||
}
|
||||
@@ -349,7 +346,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
public void setContext(final GBDevice gbDevice, final BluetoothAdapter btAdapter, final Context context) {
|
||||
super.setContext(gbDevice, btAdapter, context);
|
||||
this.mediaManager = new MediaManager(context);
|
||||
this.sleepAsAndroidSender = new SleepAsAndroidSender(gbDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -454,8 +450,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
byte[] tail = new byte[] { 0, BLETypeConversions.mapTimeZone(calendar, BLETypeConversions.TZ_FLAG_INCLUDE_DST_IN_TZ) };
|
||||
// 0 = adjust reason bitflags? or DST offset?? , timezone
|
||||
// byte[] tail = new byte[] { 0x2 }; // reason
|
||||
byte[] all = BLETypeConversions.join(bytes, tail);
|
||||
return all;
|
||||
return BLETypeConversions.join(bytes, tail);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,7 +517,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
return this;
|
||||
}
|
||||
|
||||
public HuamiSupport enableFurtherNotifications(TransactionBuilder builder, boolean enable) {
|
||||
public void enableFurtherNotifications(TransactionBuilder builder, boolean enable) {
|
||||
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_3_CONFIGURATION), enable);
|
||||
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_6_BATTERY_INFO), enable);
|
||||
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_AUDIO), enable);
|
||||
@@ -532,8 +527,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
if (characteristicChunked2021Read != null) {
|
||||
builder.notify(characteristicChunked2021Read, enable);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -541,19 +534,23 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HuamiDevicePrefs getDevicePrefs() {
|
||||
return new HuamiDevicePrefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()), gbDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectFirstTime() {
|
||||
needsAuth = true;
|
||||
return connect();
|
||||
}
|
||||
|
||||
private HuamiSupport sendDefaultNotification(TransactionBuilder builder, SimpleNotification simpleNotification, short repeat, BtLEAction extraAction) {
|
||||
private void sendDefaultNotification(TransactionBuilder builder, SimpleNotification simpleNotification, short repeat, BtLEAction extraAction) {
|
||||
LOG.info("Sending notification to MiBand: (" + repeat + " times)");
|
||||
NotificationStrategy strategy = getNotificationStrategy();
|
||||
for (short i = 0; i < repeat; i++) {
|
||||
strategy.sendDefaultNotification(builder, simpleNotification, extraAction);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public NotificationStrategy getNotificationStrategy() {
|
||||
@@ -575,27 +572,24 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
private static final byte[] startHeartMeasurementContinuous = new byte[]{0x15, MiBandService.COMMAND_SET__HR_CONTINUOUS, 1};
|
||||
private static final byte[] stopHeartMeasurementContinuous = new byte[]{0x15, MiBandService.COMMAND_SET__HR_CONTINUOUS, 0};
|
||||
|
||||
private HuamiSupport requestBatteryInfo(TransactionBuilder builder) {
|
||||
private void requestBatteryInfo(TransactionBuilder builder) {
|
||||
LOG.debug("Requesting Battery Info!");
|
||||
BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_6_BATTERY_INFO);
|
||||
builder.read(characteristic);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HuamiSupport requestDeviceInfo(TransactionBuilder builder) {
|
||||
public void requestDeviceInfo(TransactionBuilder builder) {
|
||||
LOG.debug("Requesting Device Info!");
|
||||
deviceInfoProfile.requestDeviceInfo(builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of device initialization process. Do not call manually.
|
||||
*
|
||||
* @param transaction
|
||||
* @return
|
||||
*/
|
||||
|
||||
protected HuamiSupport setFitnessGoal(TransactionBuilder transaction) {
|
||||
protected void setFitnessGoal(TransactionBuilder transaction) {
|
||||
LOG.info("Attempting to set Fitness Goal...");
|
||||
BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_8_USER_SETTINGS);
|
||||
if (characteristic != null) {
|
||||
@@ -609,19 +603,17 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
LOG.info("Unable to set Fitness Goal");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of device initialization process. Do not call manually.
|
||||
*
|
||||
* @param transaction
|
||||
* @return
|
||||
*/
|
||||
protected HuamiSupport setUserInfo(TransactionBuilder transaction) {
|
||||
protected void setUserInfo(TransactionBuilder transaction) {
|
||||
BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_8_USER_SETTINGS);
|
||||
if (characteristic == null) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("Attempting to set user info...");
|
||||
@@ -637,7 +629,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
if (alias == null || weight == 0 || height == 0 || birth_year == 0) {
|
||||
LOG.warn("Unable to set user info, make sure it is set up");
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
byte sex = 2; // other
|
||||
@@ -671,16 +663,14 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
};
|
||||
|
||||
transaction.write(characteristic, bytes);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of device initialization process. Do not call manually.
|
||||
*
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
protected HuamiSupport setWearLocation(TransactionBuilder builder) {
|
||||
protected void setWearLocation(TransactionBuilder builder) {
|
||||
LOG.info("Attempting to set wear location...");
|
||||
BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_8_USER_SETTINGS);
|
||||
if (characteristic != null) {
|
||||
@@ -696,7 +686,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
builder.notify(characteristic, false); // TODO: this should actually be in some kind of finally-block in the queue. It should also be sent asynchronously after the notifications have completely arrived and processed.
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -724,7 +713,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
private HuamiSupport setPassword(final TransactionBuilder builder) {
|
||||
private void setPassword(final TransactionBuilder builder) {
|
||||
final boolean passwordEnabled = HuamiCoordinator.getPasswordEnabled(gbDevice.getAddress());
|
||||
final String password = HuamiCoordinator.getPassword(gbDevice.getAddress());
|
||||
|
||||
@@ -732,7 +721,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
if (password == null || password.isEmpty()) {
|
||||
LOG.warn("Invalid password: {}", password);
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@@ -746,12 +735,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
baos.write(0x00);
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to build password command", e);
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
writeToConfiguration(builder, baos.toByteArray());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -759,7 +746,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
*
|
||||
* @param builder
|
||||
*/
|
||||
protected HuamiSupport setHeartrateSleepSupport(TransactionBuilder builder) {
|
||||
protected void setHeartrateSleepSupport(TransactionBuilder builder) {
|
||||
final boolean enableHrSleepSupport = MiBandCoordinator.getHeartrateSleepSupport(gbDevice.getAddress());
|
||||
if (characteristicHRControlPoint != null) {
|
||||
builder.notify(characteristicHRControlPoint, true);
|
||||
@@ -772,17 +759,15 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
builder.notify(characteristicHRControlPoint, false); // TODO: this should actually be in some kind of finally-block in the queue. It should also be sent asynchronously after the notifications have completely arrived and processed.
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateActivityMonitoring(TransactionBuilder builder) {
|
||||
protected void setHeartrateActivityMonitoring(TransactionBuilder builder) {
|
||||
final boolean enableHrActivityMonitoring = HuamiCoordinator.getHeartrateActivityMonitoring(gbDevice.getAddress());
|
||||
final byte[] cmd = {ENDPOINT_DISPLAY, 0x22, 0x00, (byte) (enableHrActivityMonitoring ? 0x01 : 0x00)};
|
||||
writeToConfiguration(builder, cmd);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateAlert(TransactionBuilder builder) {
|
||||
protected void setHeartrateAlert(TransactionBuilder builder) {
|
||||
final boolean enableHrAlert = HuamiCoordinator.getHeartrateAlert(gbDevice.getAddress());
|
||||
final int hrAlertThreshold = HuamiCoordinator.getHeartrateAlertHighThreshold(gbDevice.getAddress());
|
||||
|
||||
@@ -796,25 +781,22 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
writeToConfiguration(builder, cmd);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateStressMonitoring(TransactionBuilder builder) {
|
||||
protected void setHeartrateStressMonitoring(TransactionBuilder builder) {
|
||||
final boolean enableHrStressMonitoring = HuamiCoordinator.getHeartrateStressMonitoring(gbDevice.getAddress());
|
||||
LOG.info("Setting heart rate stress monitoring to {}", enableHrStressMonitoring);
|
||||
final byte[] cmd = new byte[] {(byte) 0xfe, 0x06, 0x00, (byte) (enableHrStressMonitoring ? 0x01 : 0x00)};
|
||||
writeToConfiguration(builder, cmd);
|
||||
return this;
|
||||
}
|
||||
|
||||
private HuamiSupport setHeartrateMeasurementInterval(TransactionBuilder builder, int minutes) {
|
||||
private void setHeartrateMeasurementInterval(TransactionBuilder builder, int minutes) {
|
||||
if (characteristicHRControlPoint != null) {
|
||||
builder.notify(characteristicHRControlPoint, true);
|
||||
LOG.info("Setting heart rate measurement interval to " + minutes + " minutes");
|
||||
builder.write(characteristicHRControlPoint, new byte[]{HuamiService.COMMAND_SET_PERIODIC_HR_MEASUREMENT_INTERVAL, (byte) minutes});
|
||||
builder.notify(characteristicHRControlPoint, false); // TODO: this should actually be in some kind of finally-block in the queue. It should also be sent asynchronously after the notifications have completely arrived and processed.
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void performDefaultNotification(String task, SimpleNotification simpleNotification, short repeat, BtLEAction extraAction) {
|
||||
@@ -1459,14 +1441,12 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
public HuamiSupport sendReboot(TransactionBuilder builder) {
|
||||
public void sendReboot(TransactionBuilder builder) {
|
||||
builder.write(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_FIRMWARE), new byte[] { HuamiService.COMMAND_FIRMWARE_REBOOT});
|
||||
return this;
|
||||
}
|
||||
|
||||
public HuamiSupport sendFactoryReset(TransactionBuilder builder) {
|
||||
public void sendFactoryReset(TransactionBuilder builder) {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_FACTORY_RESET);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2369,7 +2349,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
MiBand2SampleProvider provider = new MiBand2SampleProvider(gbDevice, session);
|
||||
MiBandActivitySample sample = createActivitySample(device, user, ts, provider);
|
||||
sample.setHeartRate(getHeartrateBpm());
|
||||
sleepAsAndroidSender.onHrChanged(sample.getHeartRate(), 0);
|
||||
|
||||
// sample.setSteps(getSteps());
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
@@ -2462,7 +2441,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
if (versionCmd.fwVersion == null) {
|
||||
versionCmd.fwVersion = info.getSoftwareRevision();
|
||||
}
|
||||
if (versionCmd.fwVersion != null && versionCmd.fwVersion.length() > 0 && versionCmd.fwVersion.charAt(0) == 'V') {
|
||||
if (versionCmd.fwVersion != null && !versionCmd.fwVersion.isEmpty() && versionCmd.fwVersion.charAt(0) == 'V') {
|
||||
versionCmd.fwVersion = versionCmd.fwVersion.substring(1);
|
||||
}
|
||||
handleGBDeviceEvent(versionCmd);
|
||||
@@ -2475,28 +2454,27 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
private HuamiSupport sendCalendarEvents(TransactionBuilder builder) {
|
||||
private void sendCalendarEvents(TransactionBuilder builder) {
|
||||
if (characteristicChunked == null) { // all except Mi Band 2
|
||||
sendCalendarEventsAsAlarms(builder);
|
||||
} else {
|
||||
sendCalendarEventsAsReminders(builder);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the events from the android device calendars and set the alarms on the miband.
|
||||
*
|
||||
* @param builder
|
||||
*/
|
||||
private HuamiSupport sendCalendarEventsAsAlarms(TransactionBuilder builder) {
|
||||
private void sendCalendarEventsAsAlarms(TransactionBuilder builder) {
|
||||
DeviceCoordinator coordinator = gbDevice.getDeviceCoordinator();
|
||||
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
||||
int maxAlarms = coordinator.getAlarmSlotCount(gbDevice);
|
||||
int availableSlots = Math.min(prefs.getInt(PREF_RESERVER_ALARMS_CALENDAR, 0), maxAlarms);
|
||||
|
||||
if (availableSlots <= 0) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
CalendarManager upcomingEvents = new CalendarManager(getContext(), getDevice().getAddress());
|
||||
@@ -2519,13 +2497,12 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
iteration++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private HuamiSupport sendCalendarEventsAsReminders(TransactionBuilder builder) {
|
||||
private void sendCalendarEventsAsReminders(TransactionBuilder builder) {
|
||||
boolean syncCalendar = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(PREF_SYNC_CALENDAR, false);
|
||||
if (!syncCalendar) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
final DeviceCoordinator coordinator = gbDevice.getDeviceCoordinator();
|
||||
|
||||
@@ -2586,8 +2563,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
buf.put(new byte[6 + 6 + 1 + 1]); // default value is 0
|
||||
writeToChunked(builder, 2, buf.array());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2763,7 +2738,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
private HuamiSupport setVibrationPattern(final TransactionBuilder builder, final String preferenceKey) {
|
||||
private void setVibrationPattern(final TransactionBuilder builder, final String preferenceKey) {
|
||||
// The preference key has one of the 3 prefixes
|
||||
final String notificationTypeName = preferenceKey.replace(PREF_HUAMI_VIBRATION_COUNT_PREFIX, "")
|
||||
.replace(PREF_HUAMI_VIBRATION_PROFILE_PREFIX, "")
|
||||
@@ -2779,8 +2754,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
);
|
||||
|
||||
setVibrationPattern(builder, notificationType, isTry, vibrationProfile);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3079,7 +3052,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
protected HuamiSupport setDateDisplay(TransactionBuilder builder) {
|
||||
protected void setDateDisplay(TransactionBuilder builder) {
|
||||
DateTimeDisplay dateTimeDisplay = HuamiCoordinator.getDateDisplay(getContext(), gbDevice.getAddress());
|
||||
LOG.info("Setting date display to " + dateTimeDisplay);
|
||||
switch (dateTimeDisplay) {
|
||||
@@ -3090,13 +3063,12 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
writeToConfiguration(builder,HuamiService.DATEFORMAT_DATE_TIME);
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDateFormat(TransactionBuilder builder) {
|
||||
protected void setDateFormat(TransactionBuilder builder) {
|
||||
String dateFormat = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getString("dateformat", "MM/dd/yyyy");
|
||||
if (dateFormat == null) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
switch (dateFormat) {
|
||||
case "MM/dd/yyyy":
|
||||
@@ -3110,10 +3082,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
LOG.warn("unsupported date format " + dateFormat);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private HuamiSupport setTimeFormat(TransactionBuilder builder) {
|
||||
private void setTimeFormat(TransactionBuilder builder) {
|
||||
String timeFormat = GBApplication.getDevicePrefs(gbDevice).getTimeFormat();
|
||||
|
||||
LOG.info("Setting time format to " + timeFormat);
|
||||
@@ -3122,7 +3093,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder,HuamiService.DATEFORMAT_TIME_12_HOURS);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setGoalNotification(TransactionBuilder builder) {
|
||||
@@ -3136,7 +3106,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setActivateDisplayOnLiftWrist(TransactionBuilder builder) {
|
||||
protected void setActivateDisplayOnLiftWrist(TransactionBuilder builder) {
|
||||
ActivateDisplayOnLift displayOnLift = HuamiCoordinator.getActivateDisplayOnLiftWrist(getContext(), gbDevice.getAddress());
|
||||
LOG.info("Setting activate display on lift wrist to " + displayOnLift);
|
||||
|
||||
@@ -3167,10 +3137,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
default:
|
||||
LOG.warn("Unknown display on lift mode {}", displayOnLift);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setActivateDisplayOnLiftWristSensitivity(TransactionBuilder builder) {
|
||||
protected void setActivateDisplayOnLiftWristSensitivity(TransactionBuilder builder) {
|
||||
final ActivateDisplayOnLiftSensitivity sensitivity = HuamiCoordinator.getDisplayOnLiftSensitivity(gbDevice.getAddress());
|
||||
LOG.info("Setting activate display on lift wrist sensitivity to " + sensitivity);
|
||||
|
||||
@@ -3183,8 +3152,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISPLAY_ON_LIFT_WRIST_SPEED_NORMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisplayItems(TransactionBuilder builder) {
|
||||
@@ -3217,7 +3184,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisplayItemsOld(TransactionBuilder builder, boolean isShortcuts, int defaultSettings, Map<String, Integer> keyPosMap) {
|
||||
protected void setDisplayItemsOld(TransactionBuilder builder, boolean isShortcuts, int defaultSettings, Map<String, Integer> keyPosMap) {
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
String pages;
|
||||
List<String> enabledList;
|
||||
@@ -3285,7 +3252,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
|
||||
writeToConfiguration(builder, command);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisplayItemsNew(TransactionBuilder builder, boolean isShortcuts, boolean forceWatchface, int defaultSettings) {
|
||||
@@ -3346,11 +3312,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setShortcuts(TransactionBuilder builder) {
|
||||
return this;
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
}
|
||||
|
||||
protected HuamiSupport setWorkoutActivityTypes(final TransactionBuilder builder) {
|
||||
protected void setWorkoutActivityTypes(final TransactionBuilder builder) {
|
||||
final SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
|
||||
final List<String> defaultActivityTypes = Arrays.asList(HuamiWorkoutScreenActivityType.Freestyle.name().toLowerCase(Locale.ROOT));
|
||||
@@ -3392,16 +3357,14 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
writeToChunked(builder, 9, command.array());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setBeepSounds(TransactionBuilder builder) {
|
||||
protected void setBeepSounds(TransactionBuilder builder) {
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
Set<String> sounds = prefs.getStringSet(PREF_SOUNDS, new HashSet<>(Arrays.asList(getContext().getResources().getStringArray(R.array.pref_amazfitneo_sounds_default))));
|
||||
|
||||
LOG.info("Setting sounds to " + (sounds == null ? "none" : sounds));
|
||||
|
||||
|
||||
if (sounds != null) {
|
||||
final String[] soundOrder = new String[]{"button", "calls", "alarm", "notifications", "inactivity_warning", "sms", "email", "goal"};
|
||||
byte[] command = new byte[]{0x3c, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0};
|
||||
@@ -3414,11 +3377,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
writeToChunked(builder, 2, command);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setRotateWristToSwitchInfo(TransactionBuilder builder) {
|
||||
protected void setRotateWristToSwitchInfo(TransactionBuilder builder) {
|
||||
boolean enable = HuamiCoordinator.getRotateWristToSwitchInfo(gbDevice.getAddress());
|
||||
LOG.info("Setting rotate wrist to cycle info to " + enable);
|
||||
if (enable) {
|
||||
@@ -3426,15 +3387,13 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISABLE_ROTATE_WRIST_TO_SWITCH_INFO);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisplayCaller(TransactionBuilder builder) {
|
||||
protected void setDisplayCaller(TransactionBuilder builder) {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_ENABLE_DISPLAY_CALLER);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDoNotDisturb(TransactionBuilder builder) {
|
||||
protected void setDoNotDisturb(TransactionBuilder builder) {
|
||||
DoNotDisturb doNotDisturb = HuamiCoordinator.getDoNotDisturb(gbDevice.getAddress());
|
||||
boolean doNotDisturbLiftWrist = HuamiCoordinator.getDoNotDisturbLiftWrist(gbDevice.getAddress());
|
||||
LOG.info("Setting do not disturb to {}, wake on lift wrist {}", doNotDisturb, doNotDisturbLiftWrist);
|
||||
@@ -3472,11 +3431,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
writeToConfiguration(builder, data);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setNightMode(TransactionBuilder builder) {
|
||||
protected void setNightMode(TransactionBuilder builder) {
|
||||
String nightMode = MiBand3Coordinator.getNightMode(gbDevice.getAddress());
|
||||
LOG.info("Setting night mode to " + nightMode);
|
||||
|
||||
@@ -3508,11 +3465,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
LOG.error("Invalid night mode: " + nightMode);
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setInactivityWarnings(TransactionBuilder builder) {
|
||||
protected void setInactivityWarnings(TransactionBuilder builder) {
|
||||
boolean enable = HuamiCoordinator.getInactivityWarnings(gbDevice.getAddress());
|
||||
LOG.info("Setting inactivity warnings to " + enable);
|
||||
|
||||
@@ -3562,13 +3517,11 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISABLE_INACTIVITY_WARNINGS);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHourlyChime(TransactionBuilder builder) {
|
||||
protected void setHourlyChime(TransactionBuilder builder) {
|
||||
if (!supportsHourlyChime())
|
||||
return this;
|
||||
return;
|
||||
|
||||
boolean enable = HuamiCoordinator.getHourlyChime(gbDevice.getAddress());
|
||||
LOG.info("Setting hourly chime to " + enable);
|
||||
@@ -3593,15 +3546,13 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISABLE_HOURLY_CHIME);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean supportsHourlyChime() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected HuamiSupport setDisconnectNotification(TransactionBuilder builder) {
|
||||
private void setDisconnectNotification(TransactionBuilder builder) {
|
||||
DisconnectNotificationSetting disconnectNotificationSetting = HuamiCoordinator.getDisconnectNotificationSetting(getContext(), gbDevice.getAddress());
|
||||
LOG.info("Setting disconnect notification to " + disconnectNotificationSetting);
|
||||
|
||||
@@ -3629,10 +3580,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
|
||||
writeToConfiguration(builder, cmd);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private HuamiSupport setDistanceUnit(TransactionBuilder builder) {
|
||||
private void setDistanceUnit(TransactionBuilder builder) {
|
||||
MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit();
|
||||
LOG.info("Setting distance unit to " + unit);
|
||||
if (unit == MiBandConst.DistanceUnit.METRIC) {
|
||||
@@ -3640,10 +3590,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISTANCE_UNIT_IMPERIAL);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setBandScreenUnlock(TransactionBuilder builder) {
|
||||
protected void setBandScreenUnlock(TransactionBuilder builder) {
|
||||
boolean enable = MiBand3Coordinator.getBandScreenUnlock(gbDevice.getAddress());
|
||||
LOG.info("Setting band screen unlock to " + enable);
|
||||
|
||||
@@ -3652,11 +3601,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, MiBand3Service.COMMAND_DISABLE_BAND_SCREEN_UNLOCK);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setLanguage(TransactionBuilder builder) {
|
||||
protected void setLanguage(TransactionBuilder builder) {
|
||||
String localeString = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getString("language", "auto");
|
||||
if (localeString == null || localeString.equals("auto")) {
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
@@ -3704,39 +3651,18 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
Some newer devices seem to support setting the language by id again instead of a locale string
|
||||
Amazfit Bip U and GTS 2 mini tested so far
|
||||
*/
|
||||
protected HuamiSupport setLanguageByIdNew(TransactionBuilder builder) {
|
||||
final byte[] command = new byte[]{0x06, 0x3b, 0x00, getLanguageId(), 0x03};
|
||||
protected void setLanguageByIdNew(TransactionBuilder builder) {
|
||||
final byte[] command = new byte[]{0x06, 0x3b, 0x00, getDevicePrefs().getLanguageId(), 0x03};
|
||||
writeToConfiguration(builder, command);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected byte getLanguageId() {
|
||||
byte language_code = 0x02; // english default
|
||||
|
||||
String localeString = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getString("language", "auto");
|
||||
if (localeString == null || localeString.equals("auto")) {
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
String country = Locale.getDefault().getCountry();
|
||||
|
||||
localeString = language + "_" + country.toUpperCase();
|
||||
}
|
||||
|
||||
Integer id = HuamiLanguageType.idLookup.get(localeString);
|
||||
if (id != null) {
|
||||
language_code = id.byteValue();
|
||||
}
|
||||
|
||||
return language_code;
|
||||
}
|
||||
|
||||
protected HuamiSupport setExposeHRThirdParty(TransactionBuilder builder) {
|
||||
protected void setExposeHRThirdParty(TransactionBuilder builder) {
|
||||
boolean enable = HuamiCoordinator.getExposeHRThirdParty(gbDevice.getAddress());
|
||||
LOG.info("Setting exposure of HR to third party apps to: " + enable);
|
||||
|
||||
@@ -3745,11 +3671,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISABLE_HR_CONNECTION);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setBtConnectedAdvertising(TransactionBuilder builder) {
|
||||
protected void setBtConnectedAdvertising(TransactionBuilder builder) {
|
||||
boolean enable = HuamiCoordinator.getBtConnectedAdvertising(gbDevice.getAddress());
|
||||
LOG.info("Setting connected advertisement to: " + enable);
|
||||
|
||||
@@ -3758,8 +3682,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
} else {
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_DISABLE_BT_CONNECTED_ADVERTISEMENT);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void writeToChunked(TransactionBuilder builder, int type, byte[] data) {
|
||||
@@ -3835,18 +3757,16 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
protected HuamiSupport requestGPSVersion(TransactionBuilder builder) {
|
||||
protected void requestGPSVersion(TransactionBuilder builder) {
|
||||
LOG.info("Requesting GPS version");
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_REQUEST_GPS_VERSION);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport requestAlarms(TransactionBuilder builder) {
|
||||
protected void requestAlarms(TransactionBuilder builder) {
|
||||
LOG.info("Requesting alarms");
|
||||
//FIXME: on older devices only the first one works, and on newer only the last is sufficient
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_REQUEST_ALARMS);
|
||||
writeToConfiguration(builder, HuamiService.COMMAND_REQUEST_ALARMS_WITH_TIMES);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3949,7 +3869,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
|
||||
protected void setMtu(final int mtu) {
|
||||
if (mtu > MIN_MTU && !allowHighMtu()) {
|
||||
if (mtu > MIN_MTU && !getDevicePrefs().allowHighMtu()) {
|
||||
LOG.warn("High MTU is not allowed, ignoring");
|
||||
return;
|
||||
}
|
||||
@@ -3965,22 +3885,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean allowHighMtu() {
|
||||
return getDevicePrefs().getBoolean(PREF_ALLOW_HIGH_MTU, true);
|
||||
}
|
||||
|
||||
public int getActivitySampleSize() {
|
||||
return mActivitySampleSize;
|
||||
}
|
||||
|
||||
public TimeUnit getFetchOperationsTimeUnit() {
|
||||
// This is configurable because using seconds was causing issues on Amazfit GTR 3
|
||||
// However, using minutes can cause issues while fetching workouts shorter than 1 minute
|
||||
final Prefs devicePrefs = getDevicePrefs();
|
||||
final boolean truncate = devicePrefs.getBoolean("huami_truncate_fetch_operation_timestamps", true);
|
||||
return truncate ? TimeUnit.MINUTES : TimeUnit.SECONDS;
|
||||
}
|
||||
|
||||
public boolean force2021Protocol() {
|
||||
return GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean("force_new_protocol", false);
|
||||
}
|
||||
|
||||
+1
-2
@@ -35,9 +35,8 @@ public class AmazfitBand5Support extends MiBand5Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitBand5Support setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
setDisplayItemsNew(builder, true, true, R.array.pref_amazfitband5_shortcuts_default);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -65,13 +65,12 @@ public class AmazfitBipSupport extends HuamiSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitBipSupport setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
Map<String, Integer> keyPosMap = new LinkedHashMap<>();
|
||||
keyPosMap.put("alipay", 1);
|
||||
keyPosMap.put("weather", 2);
|
||||
|
||||
setDisplayItemsOld(builder, true, R.array.pref_bip_shortcuts_default, keyPosMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -99,9 +99,8 @@ public class AmazfitBipSSupport extends AmazfitBipSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitBipSSupport setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
setDisplayItemsNew(builder, true, true, R.array.pref_bips_display_items_default);
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean isDTH(Version version) {
|
||||
|
||||
+2
-3
@@ -24,7 +24,6 @@ import java.io.IOException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbipu.AmazfitBipUFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbips.AmazfitBipSSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.update.UpdateFirmwareOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.update.UpdateFirmwareOperation2020;
|
||||
@@ -32,8 +31,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.upd
|
||||
public class AmazfitBipUSupport extends AmazfitBipSSupport {
|
||||
|
||||
@Override
|
||||
protected HuamiSupport setLanguage(TransactionBuilder builder) {
|
||||
return setLanguageByIdNew(builder);
|
||||
protected void setLanguage(TransactionBuilder builder) {
|
||||
setLanguageByIdNew(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -28,15 +28,14 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts2.AmazfitGTS2MiniFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
|
||||
|
||||
public class AmazfitGTS2MiniSupport extends AmazfitGTS2Support {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTS2MiniSupport.class);
|
||||
|
||||
@Override
|
||||
protected HuamiSupport setLanguage(TransactionBuilder builder) {
|
||||
return setLanguageByIdNew(builder);
|
||||
protected void setLanguage(TransactionBuilder builder) {
|
||||
setLanguageByIdNew(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-6
@@ -61,10 +61,9 @@ public class AmazfitNeoSupport extends MiBand5Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitNeoSupport setFitnessGoal(TransactionBuilder builder) {
|
||||
protected void setFitnessGoal(TransactionBuilder builder) {
|
||||
LOG.info("Attempting to set Fitness Goal...");
|
||||
setNeoFitnessGoal(builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,19 +86,18 @@ public class AmazfitNeoSupport extends MiBand5Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitNeoSupport requestAlarms(TransactionBuilder builder) {
|
||||
return this; //Neo always returns response array with '03' in it which marks alarms unused on connect
|
||||
protected void requestAlarms(TransactionBuilder builder) {
|
||||
//Neo always returns response array with '03' in it which marks alarms unused on connect
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsHourlyChime() { return true; }
|
||||
|
||||
@Override
|
||||
protected AmazfitNeoSupport setHeartrateSleepSupport(TransactionBuilder builder) {
|
||||
protected void setHeartrateSleepSupport(TransactionBuilder builder) {
|
||||
final boolean enableHrSleepSupport = MiBandCoordinator.getHeartrateSleepSupport(gbDevice.getAddress());
|
||||
LOG.info("Setting Amazfit Neo heartrate sleep support to " + enableHrSleepSupport);
|
||||
writeToConfiguration(builder, new byte[] {0x06, 0x3c, 0x00, (byte) (enableHrSleepSupport ? 1 : 0 )});
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -40,9 +40,8 @@ public class AmazfitXSupport extends MiBand5Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AmazfitXSupport setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
setDisplayItemsNew(builder, true, true, R.array.pref_amazfitband5_shortcuts_default);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -42,9 +42,8 @@ public class MiBand5Support extends MiBand4Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MiBand5Support setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
setDisplayItemsNew(builder, true, true, R.array.pref_miband5_shortcuts_default);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -56,9 +56,8 @@ public class MiBand6Support extends MiBand5Support {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MiBand6Support setShortcuts(TransactionBuilder builder) {
|
||||
protected void setShortcuts(TransactionBuilder builder) {
|
||||
setDisplayItemsNew(builder, true, true, R.array.pref_miband6_shortcuts_default);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-3
@@ -100,9 +100,6 @@ public class InitOperation extends AbstractBTLEOperation<HuamiSupport> {
|
||||
byte[] srcBytes = authKey.trim().getBytes();
|
||||
if (authKey.length() == 34 && authKey.startsWith("0x")) {
|
||||
srcBytes = GB.hexStringToByteArray(authKey.substring(2));
|
||||
} else if (authKey.length() == 32 && huamiSupport instanceof ZeppOsSupport) {
|
||||
// All Zepp OS devices require a hex key
|
||||
srcBytes = GB.hexStringToByteArray(authKey);
|
||||
}
|
||||
System.arraycopy(srcBytes, 0, authKeyBytes, 0, Math.min(srcBytes.length, 16));
|
||||
}
|
||||
|
||||
+18
-6
@@ -23,11 +23,13 @@ import androidx.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiDevicePrefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public abstract class AbstractZeppOsService {
|
||||
@@ -67,7 +69,7 @@ public abstract class AbstractZeppOsService {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
// Do nothing by default
|
||||
// TODO implement a "quick initialize" that runs for the same firmware + Gb versions, since
|
||||
// we will already know the capabilities
|
||||
@@ -86,8 +88,8 @@ public abstract class AbstractZeppOsService {
|
||||
return (ZeppOsCoordinator) coordinator;
|
||||
}
|
||||
|
||||
protected Prefs getDevicePrefs() {
|
||||
return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getSupport().getDevice().getAddress()));
|
||||
protected HuamiDevicePrefs getDevicePrefs() {
|
||||
return getSupport().getDevicePrefs();
|
||||
}
|
||||
|
||||
protected void write(final String taskName, final byte b) {
|
||||
@@ -98,11 +100,11 @@ public abstract class AbstractZeppOsService {
|
||||
this.mSupport.writeToChunked2021(taskName, getEndpoint(), data, isEncrypted());
|
||||
}
|
||||
|
||||
protected void write(final TransactionBuilder builder, final byte b) {
|
||||
protected void write(final ZeppOsTransactionBuilder builder, final byte b) {
|
||||
this.write(builder, new byte[]{b});
|
||||
}
|
||||
|
||||
protected void write(final TransactionBuilder builder, final byte[] data) {
|
||||
protected void write(final ZeppOsTransactionBuilder builder, final byte[] data) {
|
||||
this.mSupport.writeToChunked2021(builder, getEndpoint(), data, isEncrypted());
|
||||
}
|
||||
|
||||
@@ -114,6 +116,16 @@ public abstract class AbstractZeppOsService {
|
||||
return getSupport().getContext();
|
||||
}
|
||||
|
||||
protected ZeppOsTransactionBuilder createTransactionBuilder(final String taskName) {
|
||||
return mSupport.createZeppOsTransactionBuilder(taskName);
|
||||
}
|
||||
|
||||
protected void withTransactionBuilder(final String taskName, final Consumer<ZeppOsTransactionBuilder> consumer) {
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder(taskName);
|
||||
consumer.accept(builder);
|
||||
builder.queue(mSupport);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static Boolean booleanFromByte(final byte b) {
|
||||
switch (b) {
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2025 José Rebelo
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
|
||||
public class ZeppOsBtleTransactionBuilder implements ZeppOsTransactionBuilder {
|
||||
private final AbstractBTLEDeviceSupport mSupport;
|
||||
private final TransactionBuilder mBuilder;
|
||||
|
||||
public ZeppOsBtleTransactionBuilder(final AbstractBTLEDeviceSupport mSupport, final String taskName) {
|
||||
this.mSupport = mSupport;
|
||||
this.mBuilder = new TransactionBuilder(taskName);
|
||||
}
|
||||
|
||||
public ZeppOsBtleTransactionBuilder(final AbstractBTLEDeviceSupport mSupport, final TransactionBuilder builder) {
|
||||
this.mSupport = mSupport;
|
||||
this.mBuilder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(final String text, final boolean ongoing, final int percentage, final Context context) {
|
||||
mBuilder.add(new SetProgressAction(text, ongoing, percentage, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceState(final GBDevice device, final GBDevice.State deviceState, final Context context) {
|
||||
mBuilder.add(new SetDeviceStateAction(device, deviceState, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(final UUID characteristic, final boolean enable) {
|
||||
mBuilder.notify(mSupport.getCharacteristic(characteristic), enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final UUID characteristic, final byte[] arr) {
|
||||
mBuilder.write(mSupport.getCharacteristic(characteristic), arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queue(final ZeppOsSupport support) {
|
||||
mBuilder.queue(support.getQueue());
|
||||
}
|
||||
}
|
||||
+228
-175
@@ -21,8 +21,6 @@ import static nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversio
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions.fromUint8;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions.mapTimeZone;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.HEART_RATE_ALL_DAY_MONITORING;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.LANGUAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.LANGUAGE_FOLLOW_PHONE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.SLEEP_HIGH_ACCURACY_MONITORING;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
@@ -63,19 +61,18 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsMapsInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsMusicInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.Huami2021Service;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
@@ -95,14 +92,20 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021ChunkedDecoder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021ChunkedEncoder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.update.UpdateFirmwareOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Handler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiDevicePrefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFetcher;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsFirmwareUpdateOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsAgpsUpdateOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsGpxRouteUploadOperation;
|
||||
@@ -150,13 +153,47 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.RealtimeSamplesAggregator;
|
||||
|
||||
public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferService.DownloadCallback {
|
||||
public class ZeppOsSupport extends AbstractBTLEDeviceSupport
|
||||
implements Huami2021Handler, HuamiFetcher.HuamiFetchSupport, ZeppOsFileTransferService.DownloadCallback {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsSupport.class);
|
||||
|
||||
// Keep track of whether the rawSensor is enabled
|
||||
private boolean rawSensor = false;
|
||||
private ScheduledExecutorService rawSensorScheduler;
|
||||
private RealtimeSamplesAggregator realtimeSamplesAggregator;
|
||||
|
||||
private final DeviceInfoProfile<ZeppOsSupport> deviceInfoProfile;
|
||||
private final IntentListener mListener = intent -> {
|
||||
String s = intent.getAction();
|
||||
if (DeviceInfoProfile.ACTION_DEVICE_INFO.equals(s)) {
|
||||
final DeviceInfo info = intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO);
|
||||
LOG.debug("Device info: {}", info);
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
|
||||
versionCmd.hwVersion = info.getHardwareRevision();
|
||||
versionCmd.fwVersion = info.getFirmwareRevision();
|
||||
if (versionCmd.fwVersion == null) {
|
||||
versionCmd.fwVersion = info.getSoftwareRevision();
|
||||
}
|
||||
if (versionCmd.fwVersion != null && !versionCmd.fwVersion.isEmpty() && versionCmd.fwVersion.charAt(0) == 'V') {
|
||||
versionCmd.fwVersion = versionCmd.fwVersion.substring(1);
|
||||
}
|
||||
handleGBDeviceEvent(versionCmd);
|
||||
}
|
||||
};
|
||||
|
||||
protected static final int MIN_MTU = 23;
|
||||
private int mMTU = MIN_MTU;
|
||||
// Keep track of the previous MTU before reconnection, so that we can request it after reconnection
|
||||
private int previousMtu = -1;
|
||||
|
||||
private Huami2021ChunkedEncoder huami2021ChunkedEncoder;
|
||||
private Huami2021ChunkedDecoder huami2021ChunkedDecoder;
|
||||
|
||||
private final HuamiFetcher fetcher = new HuamiFetcher(this);
|
||||
|
||||
private SleepAsAndroidSender sleepAsAndroidSender;
|
||||
|
||||
// Services
|
||||
private final ZeppOsServicesService servicesService = new ZeppOsServicesService(this);
|
||||
@@ -241,40 +278,36 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}};
|
||||
|
||||
public ZeppOsSupport() {
|
||||
this(LOG);
|
||||
}
|
||||
super(LOG);
|
||||
|
||||
public ZeppOsSupport(final Logger logger) {
|
||||
super(logger);
|
||||
addSupportedService(GattService.UUID_SERVICE_HEART_RATE);
|
||||
addSupportedService(GattService.UUID_SERVICE_DEVICE_INFORMATION);
|
||||
|
||||
addSupportedService(MiBandService.UUID_SERVICE_MIBAND_SERVICE);
|
||||
addSupportedService(HuamiService.UUID_SERVICE_FIRMWARE_SERVICE);
|
||||
|
||||
deviceInfoProfile = new DeviceInfoProfile<>(this);
|
||||
deviceInfoProfile.addListener(mListener);
|
||||
addSupportedProfile(deviceInfoProfile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(final GBDevice gbDevice, final BluetoothAdapter btAdapter, final Context context) {
|
||||
super.setContext(gbDevice, btAdapter, context);
|
||||
heartRateService.setSleepAsAndroidSender(sleepAsAndroidSender);
|
||||
realtimeSamplesAggregator = new RealtimeSamplesAggregator(getContext(), getDevice());
|
||||
final RealtimeSamplesAggregator realtimeSamplesAggregator = new RealtimeSamplesAggregator(getContext(), getDevice());
|
||||
heartRateService.setRealtimeSamplesAggregator(realtimeSamplesAggregator);
|
||||
stepsService.setRealtimeSamplesAggregator(realtimeSamplesAggregator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getAuthFlags() {
|
||||
return 0x00;
|
||||
public HuamiDevicePrefs getDevicePrefs() {
|
||||
return new HuamiDevicePrefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()), gbDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getCryptFlags() {
|
||||
return (byte) 0x80;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not reset the gatt callback implicitly, as that would interrupt operations.
|
||||
* See <a href="https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/2912">#2912</a> for more
|
||||
* information.
|
||||
*/
|
||||
@Override
|
||||
public boolean getImplicitCallbackModify() {
|
||||
return false;
|
||||
public boolean useAutoConnect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -295,12 +328,12 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
setMtu(MIN_MTU);
|
||||
}
|
||||
|
||||
characteristicChunked2021Read = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ);
|
||||
final BluetoothGattCharacteristic characteristicChunked2021Read = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ);
|
||||
if (characteristicChunked2021Read != null && huami2021ChunkedDecoder == null) {
|
||||
huami2021ChunkedDecoder = new Huami2021ChunkedDecoder(this, force2021Protocol());
|
||||
huami2021ChunkedDecoder = new Huami2021ChunkedDecoder(this, true);
|
||||
}
|
||||
|
||||
characteristicChunked2021Write = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_WRITE);
|
||||
final BluetoothGattCharacteristic characteristicChunked2021Write = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_WRITE);
|
||||
if (characteristicChunked2021Write != null && huami2021ChunkedEncoder == null) {
|
||||
huami2021ChunkedEncoder = new Huami2021ChunkedEncoder(getMTU());
|
||||
}
|
||||
@@ -312,8 +345,9 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
|
||||
builder.notify(characteristicChunked2021Read, true);
|
||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.AUTHENTICATING, getContext()));
|
||||
|
||||
authenticationService.startAuthentication(builder);
|
||||
authenticationService.startAuthentication(new ZeppOsBtleTransactionBuilder(this, builder));
|
||||
|
||||
return builder;
|
||||
}
|
||||
@@ -344,8 +378,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
findDeviceService.onFindDevice(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendFindDeviceCommand(boolean start) {
|
||||
private void sendFindDeviceCommand(boolean start) {
|
||||
findDeviceService.sendFindDeviceCommand(start);
|
||||
}
|
||||
|
||||
@@ -355,7 +388,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
voiceMemosService.requestList();
|
||||
}
|
||||
|
||||
super.onFetchRecordedData(dataTypes);
|
||||
fetcher.onFetchRecordedData(dataTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -380,11 +413,11 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
minuteInterval = Math.max(0, minuteInterval);
|
||||
}
|
||||
|
||||
final TransactionBuilder builder = createTransactionBuilder(String.format(Locale.ROOT, "set heart rate interval to: %d min", minuteInterval));
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder(String.format(Locale.ROOT, "set heart rate interval to: %d min", minuteInterval));
|
||||
configService.newSetter()
|
||||
.setByte(HEART_RATE_ALL_DAY_MONITORING, (byte) minuteInterval)
|
||||
.write(builder);
|
||||
builder.queue(getQueue());
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,8 +441,8 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void queueAlarm(final Alarm alarm, final TransactionBuilder builder) {
|
||||
alarmsService.sendAlarm(alarm, builder);
|
||||
public void onSetAlarms(final ArrayList<? extends Alarm> alarms) {
|
||||
alarmsService.onSetAlarms(alarms);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -424,14 +457,9 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
|
||||
@Override
|
||||
public void onSetReminders(final ArrayList<? extends Reminder> reminders) {
|
||||
final TransactionBuilder builder;
|
||||
try {
|
||||
builder = performInitialized("onSetReminders");
|
||||
remindersService.sendReminders(builder, reminders);
|
||||
builder.queue(getQueue());
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Unable to send reminders to device", e);
|
||||
}
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("onSetReminders");
|
||||
remindersService.sendReminders(builder, reminders);
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -471,8 +499,13 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMusicStateToDevice(final MusicSpec musicSpec, final MusicStateSpec musicStateSpec) {
|
||||
musicService.sendMusicState(musicSpec, musicStateSpec);
|
||||
public void onSetMusicState(final MusicStateSpec stateSpec) {
|
||||
musicService.onSetMusicState(stateSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(final MusicSpec musicSpec) {
|
||||
musicService.onSetMusicInfo(musicSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -480,19 +513,6 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
stepsService.onEnableRealtimeSteps(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateFirmwareOperation createUpdateFirmwareOperation(final Uri uri) {
|
||||
throw new UnsupportedOperationException("this method should not be used");
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: Visibility hack for easier refactoring.
|
||||
*/
|
||||
@Override
|
||||
public void setMtu(final int mtu) {
|
||||
super.setMtu(mtu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInstallApp(final Uri uri) {
|
||||
final ZeppOsAgpsInstallHandler agpsHandler = new ZeppOsAgpsInstallHandler(uri, getContext());
|
||||
@@ -652,14 +672,15 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ZeppOsSupport setHeartrateSleepSupport(final TransactionBuilder builder) {
|
||||
public void onEnableHeartRateSleepSupport(boolean enable) {
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("enable heart rate sleep support: " + enable);
|
||||
final boolean enableHrSleepSupport = MiBandCoordinator.getHeartrateSleepSupport(gbDevice.getAddress());
|
||||
|
||||
configService.newSetter()
|
||||
.setBoolean(SLEEP_HIGH_ACCURACY_MONITORING, enableHrSleepSupport)
|
||||
.write(builder);
|
||||
|
||||
return this;
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -676,33 +697,23 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
|
||||
@Override
|
||||
public void onSetTime() {
|
||||
if (!GBApplication.getPrefs().syncTime()) {
|
||||
return;
|
||||
if (GBApplication.getPrefs().syncTime()) {
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("set date and time");
|
||||
setCurrentTime(builder);
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized("set date and time");
|
||||
setCurrentTime(builder);
|
||||
builder.queue(getQueue());
|
||||
CalendarReceiver.forceSync(getDevice());
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Unable to set time on Huami device", ex);
|
||||
}
|
||||
CalendarReceiver.forceSync(getDevice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentTime(TransactionBuilder builder) {
|
||||
if (!GBApplication.getPrefs().syncTime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void setCurrentTime(ZeppOsTransactionBuilder builder) {
|
||||
// It seems that the format sent to the Current Time characteristic changed in newer devices
|
||||
// to kind-of match the GATT spec, but it doesn't quite respect it?
|
||||
// - 11 bytes get sent instead of 10 (extra byte at the end for the offset in quarter-hours?)
|
||||
// - Day of week starts at 0
|
||||
// Otherwise, the command gets rejected with an "Out of Range" error and init fails.
|
||||
|
||||
final Calendar timestamp = createCalendar();
|
||||
final Calendar timestamp = BLETypeConversions.createCalendar();
|
||||
final byte[] year = fromUint16(timestamp.get(Calendar.YEAR));
|
||||
|
||||
final byte[] cmd = {
|
||||
@@ -719,20 +730,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
mapTimeZone(timestamp, BLETypeConversions.TZ_FLAG_INCLUDE_DST_IN_TZ), // TODO: Confirm this
|
||||
};
|
||||
|
||||
builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME), cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HuamiSupport enableNotifications(final TransactionBuilder builder, final boolean enable) {
|
||||
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ), enable);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZeppOsSupport enableFurtherNotifications(final TransactionBuilder builder,
|
||||
final boolean enable) {
|
||||
// Nothing to do here, they are already enabled from enableNotifications
|
||||
return this;
|
||||
builder.write(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -779,7 +777,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
case SleepAsAndroidAction.SET_SUSPENDED:
|
||||
boolean suspended = extras.getBoolean("SUSPENDED", false);
|
||||
setRawSensor(!suspended);
|
||||
enableRealtimeSamplesTimer(!suspended);
|
||||
//FIXME is this really needed? enableRealtimeSamplesTimer(!suspended);
|
||||
sleepAsAndroidSender.pauseTracking(suspended);
|
||||
break;
|
||||
// Received when the app changes the batch size for the movement data
|
||||
@@ -866,86 +864,39 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
setRawSensor(enable);
|
||||
if (enable) {
|
||||
rawSensorScheduler = startRawSensors();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stopRawSensors();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ZeppOsSupport setLanguage(final TransactionBuilder builder) {
|
||||
final String localeString = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())
|
||||
.getString("language", "auto");
|
||||
|
||||
LOG.info("Setting device language to {}", localeString);
|
||||
|
||||
configService.newSetter()
|
||||
.setByte(LANGUAGE, getLanguageId())
|
||||
.setBoolean(LANGUAGE_FOLLOW_PHONE, localeString.equals("auto"))
|
||||
.write(builder);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToChunked(final TransactionBuilder builder,
|
||||
final int type,
|
||||
final byte[] data) {
|
||||
LOG.warn("writeToChunked is not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToChunkedOld(final TransactionBuilder builder, final int type, final byte[] data) {
|
||||
LOG.warn("writeToChunkedOld is not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToConfiguration(final TransactionBuilder builder, final byte[] data) {
|
||||
LOG.warn("writeToConfiguration is not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ZeppOsSupport requestGPSVersion(final TransactionBuilder builder) {
|
||||
LOG.warn("Request GPS version not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
public void requestDisplayItems(final TransactionBuilder builder) {
|
||||
public void requestDisplayItems(final ZeppOsTransactionBuilder builder) {
|
||||
displayItemsService.requestItems(builder, ZeppOsDisplayItemsService.DISPLAY_ITEMS_MENU);
|
||||
}
|
||||
|
||||
public void requestApps(final TransactionBuilder builder) {
|
||||
public void requestApps(final ZeppOsTransactionBuilder builder) {
|
||||
appsService.requestApps(builder);
|
||||
}
|
||||
|
||||
public void requestWatchfaces(final TransactionBuilder builder) {
|
||||
public void requestWatchfaces(final ZeppOsTransactionBuilder builder) {
|
||||
watchfaceService.requestWatchfaces(builder);
|
||||
watchfaceService.requestCurrentWatchface(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void phase2Initialize(final TransactionBuilder builder) {
|
||||
LOG.info("2021 phase2Initialize...");
|
||||
if (allowHighMtu()) {
|
||||
builder.requestMtu(247);
|
||||
public void onAuthenticationSuccess() {
|
||||
LOG.info("ZeppOS phase 2 initialize...");
|
||||
|
||||
final TransactionBuilder bleBuilder = new TransactionBuilder("phase 2 initialize");
|
||||
final var builder = new ZeppOsBtleTransactionBuilder(this, bleBuilder);
|
||||
builder.setDeviceState(getDevice(), GBDevice.State.INITIALIZING, getContext());
|
||||
|
||||
if (getDevicePrefs().allowHighMtu()) {
|
||||
bleBuilder.requestMtu(247);
|
||||
}
|
||||
if (GBApplication.getPrefs().syncTime()) {
|
||||
setCurrentTime(builder);
|
||||
}
|
||||
requestDeviceInfo(builder);
|
||||
|
||||
final GBDeviceEventUpdatePreferences evt = new GBDeviceEventUpdatePreferences()
|
||||
.withPreference(DeviceSettingsPreferenceConst.WIFI_HOTSPOT_STATUS, null)
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_ADDRESS, null)
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_USERNAME, null)
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_STATUS, null);
|
||||
evaluateGBDeviceEvent(evt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void phase3Initialize(final TransactionBuilder builder) {
|
||||
LOG.info("2021 phase3Initialize...");
|
||||
deviceInfoProfile.requestDeviceInfo(bleBuilder);
|
||||
|
||||
// Make sure that performInitialized is not called accidentally in here
|
||||
// (eg. by creating a new TransactionBuilder).
|
||||
@@ -956,12 +907,8 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
// initializeServices below
|
||||
mSupportedServices.clear();
|
||||
servicesService.requestServices(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public HuamiFWHelper createFWHelper(final Uri uri, final Context context) throws IOException {
|
||||
throw new UnsupportedOperationException("This function should not be used for Zepp OS devices");
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
public void addSupportedService(final short endpoint, final boolean encrypted) {
|
||||
@@ -972,7 +919,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
LOG.info("2021 initializeServices...");
|
||||
|
||||
try {
|
||||
final TransactionBuilder builder = createTransactionBuilder("initialize services");
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("initialize services");
|
||||
|
||||
// At this point we got the service list from phase 3, so we know which
|
||||
// services are supported, and whether they are encrypted or not
|
||||
@@ -986,12 +933,29 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
}
|
||||
|
||||
builder.queue(getQueue());
|
||||
builder.setDeviceState(getDevice(), GBDevice.State.INITIALIZED, getContext());
|
||||
|
||||
builder.queue(this);
|
||||
} catch (Exception e) {
|
||||
LOG.error("failed initializing device", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityNotifications(final boolean control, final boolean data) {
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("set activity notifications: " + control + " " + data);
|
||||
builder.notify(HuamiService.UUID_CHARACTERISTIC_5_ACTIVITY_CONTROL, control);
|
||||
builder.notify(HuamiService.UUID_CHARACTERISTIC_5_ACTIVITY_DATA, data);
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeActivityControl(final String name, final byte[] value) {
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder(name);
|
||||
builder.write(HuamiService.UUID_CHARACTERISTIC_5_ACTIVITY_CONTROL, value);
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AbstractZeppOsService getService(final short endpoint) {
|
||||
return mServiceMap.get(endpoint);
|
||||
@@ -1002,18 +966,12 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean force2021Protocol() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZeppOsCoordinator getCoordinator() {
|
||||
return (ZeppOsCoordinator) gbDevice.getDeviceCoordinator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setRawSensor(final boolean enable) {
|
||||
private void setRawSensor(final boolean enable) {
|
||||
LOG.info("Set raw sensor to {}", enable);
|
||||
rawSensor = enable;
|
||||
|
||||
@@ -1033,8 +991,7 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleRawSensorData(final byte[] value) {
|
||||
private void handleRawSensorData(final byte[] value) {
|
||||
// The g values seem to vary between -4100 and 4100, so we scale them
|
||||
final float scaleFactor = 4100f;
|
||||
final float gravity = -9.81f;
|
||||
@@ -1086,8 +1043,22 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
@Override
|
||||
public boolean onCharacteristicChanged(final BluetoothGatt gatt,
|
||||
final BluetoothGattCharacteristic characteristic) {
|
||||
if (super.onCharacteristicChanged(gatt, characteristic)) {
|
||||
// handled upstream
|
||||
return true;
|
||||
}
|
||||
|
||||
final UUID characteristicUUID = characteristic.getUuid();
|
||||
if (HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND.equals(characteristicUUID)) {
|
||||
if (HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ.equals(characteristicUUID)) {
|
||||
handleChunked(characteristic.getValue());
|
||||
return true;
|
||||
} else if (HuamiService.UUID_CHARACTERISTIC_5_ACTIVITY_DATA.equals(characteristicUUID)) {
|
||||
fetcher.onActivityData(characteristic.getValue());
|
||||
return true;
|
||||
} else if (HuamiService.UUID_CHARACTERISTIC_5_ACTIVITY_CONTROL.equals(characteristicUUID)) {
|
||||
fetcher.onActivityControl(characteristic.getValue());
|
||||
return true;
|
||||
} else if (HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND.equals(characteristicUUID)) {
|
||||
fileTransferService.onCharacteristicChanged(characteristic);
|
||||
return true;
|
||||
} else if (HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_RECEIVE.equals(characteristicUUID)) {
|
||||
@@ -1096,9 +1067,68 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
} else if (GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT.equals(characteristicUUID)) {
|
||||
heartRateService.handleHeartRate(characteristic.getValue());
|
||||
return true;
|
||||
} else if (HuamiService.UUID_CHARACTERISTIC_RAW_SENSOR_DATA.equals(characteristicUUID)) {
|
||||
handleRawSensorData(characteristic.getValue());
|
||||
return true;
|
||||
} else {
|
||||
LOG.warn("Unhandled characteristic changed: {}", characteristicUUID);
|
||||
logMessageContent(characteristic.getValue());
|
||||
}
|
||||
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMTU() {
|
||||
return mMTU;
|
||||
}
|
||||
|
||||
public void setMtu(final int mtu) {
|
||||
if (mtu > MIN_MTU && !getDevicePrefs().allowHighMtu()) {
|
||||
LOG.warn("High MTU is not allowed, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtu < MIN_MTU) {
|
||||
LOG.error("Device announced unreasonable low MTU of {}, ignoring", mtu);
|
||||
return;
|
||||
}
|
||||
|
||||
this.mMTU = mtu;
|
||||
if (huami2021ChunkedEncoder != null) {
|
||||
huami2021ChunkedEncoder.setMTU(mtu);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChunked(final byte[] value) {
|
||||
switch (value[0]) {
|
||||
case 0x03:
|
||||
if (huami2021ChunkedDecoder != null) {
|
||||
final boolean needsAck = huami2021ChunkedDecoder.decode(value);
|
||||
if (needsAck) {
|
||||
sendChunkedAck();
|
||||
}
|
||||
} else {
|
||||
LOG.warn("Got chunked payload, but decoder is null");
|
||||
}
|
||||
return;
|
||||
case 0x04:
|
||||
final byte handle = value[2];
|
||||
final byte count = value[4];
|
||||
LOG.info("Got chunked ack, handle={}, count={}", handle, count);
|
||||
// TODO: We should probably update the handle and count on the encoder
|
||||
return;
|
||||
default:
|
||||
LOG.warn("Unhandled chunked payload of type {}", value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunkedAck() {
|
||||
final byte handle = huami2021ChunkedDecoder.getLastHandle();
|
||||
final byte count = huami2021ChunkedDecoder.getLastCount();
|
||||
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder("send chunked ack");
|
||||
builder.write(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ, new byte[] {0x04, 0x00, handle, 0x01, count});
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1163,4 +1193,27 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
||||
private byte bool(final boolean b) {
|
||||
return (byte) (b ? 1 : 0);
|
||||
}
|
||||
|
||||
public void writeToChunked2021(final ZeppOsTransactionBuilder builder, final short type, final byte data, final boolean encrypt) {
|
||||
writeToChunked2021(builder, type, new byte[]{data}, encrypt);
|
||||
}
|
||||
|
||||
public void writeToChunked2021(final ZeppOsTransactionBuilder builder, final short type, final byte[] data, final boolean encrypt) {
|
||||
huami2021ChunkedEncoder.write(chunk -> builder.write(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_WRITE, chunk), type, data, true, encrypt);
|
||||
}
|
||||
|
||||
public void writeToChunked2021(final String taskName, final short type, final byte data, final boolean encrypt) {
|
||||
writeToChunked2021(taskName, type, new byte[]{data}, encrypt);
|
||||
}
|
||||
|
||||
public void writeToChunked2021(final String taskName, final short type, final byte[] data, final boolean encrypt) {
|
||||
final ZeppOsTransactionBuilder builder = createZeppOsTransactionBuilder(taskName);
|
||||
writeToChunked2021(builder, type, data, encrypt);
|
||||
builder.queue(this);
|
||||
}
|
||||
|
||||
public ZeppOsTransactionBuilder createZeppOsTransactionBuilder(final String taskName) {
|
||||
// FIXME this needs to be moved upstream
|
||||
return new ZeppOsBtleTransactionBuilder(this, taskName);
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2025 José Rebelo
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public interface ZeppOsTransactionBuilder {
|
||||
void setProgress(final String text, final boolean ongoing, final int percentage, final Context context);
|
||||
|
||||
void setDeviceState(final GBDevice device, final GBDevice.State deviceState, final Context context);
|
||||
|
||||
void notify(final UUID characteristic, final boolean enable);
|
||||
|
||||
void write(final UUID characteristic, final byte[] arr);
|
||||
|
||||
void queue(final ZeppOsSupport support);
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/* Copyright (C) 2025 José Rebelo
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
|
||||
/**
|
||||
* This is a simplified version of the AbstractBTLEOperation, in order to allow for simpler
|
||||
* Zepp OS btrfcomm support without a major refactor. It should not be used for new operations.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractZeppOsOperation<T extends ZeppOsSupport> {
|
||||
private final T mSupport;
|
||||
protected OperationStatus operationStatus = OperationStatus.INITIAL;
|
||||
private String name;
|
||||
|
||||
protected AbstractZeppOsOperation(T support) {
|
||||
mSupport = support;
|
||||
}
|
||||
|
||||
public final void perform() throws IOException {
|
||||
operationStatus = OperationStatus.RUNNING;
|
||||
doPerform();
|
||||
}
|
||||
|
||||
protected abstract void doPerform() throws IOException;
|
||||
|
||||
protected void operationFinished() throws IOException {
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
return mSupport.getContext();
|
||||
}
|
||||
|
||||
protected GBDevice getDevice() {
|
||||
return mSupport.getDevice();
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
String busyTask = getDevice().getBusyTask();
|
||||
if (busyTask != null) {
|
||||
return busyTask;
|
||||
}
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
protected void unsetBusy() {
|
||||
if (getDevice().isBusy()) {
|
||||
getDevice().unsetBusyTask();
|
||||
getDevice().sendDeviceUpdateIntent(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOperationRunning() {
|
||||
return operationStatus == OperationStatus.RUNNING;
|
||||
}
|
||||
|
||||
public boolean isOperationFinished() {
|
||||
return operationStatus == OperationStatus.FINISHED;
|
||||
}
|
||||
|
||||
public T getSupport() {
|
||||
return mSupport;
|
||||
}
|
||||
}
|
||||
+7
-9
@@ -22,10 +22,8 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAgpsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||
@@ -40,7 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
* 4. After successful ack from 3, update is finished. Trigger an AGPS config request from {@link ZeppOsConfigService}
|
||||
* to reload the AGPS update and expiration timestamps.
|
||||
*/
|
||||
public class ZeppOsAgpsUpdateOperation extends AbstractBTLEOperation<ZeppOsSupport>
|
||||
public class ZeppOsAgpsUpdateOperation extends AbstractZeppOsOperation<ZeppOsSupport>
|
||||
implements ZeppOsFileTransferService.UploadCallback, ZeppOsAgpsService.Callback {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsAgpsUpdateOperation.class);
|
||||
|
||||
@@ -120,9 +118,9 @@ public class ZeppOsAgpsUpdateOperation extends AbstractBTLEOperation<ZeppOsSuppo
|
||||
public void onAgpsUpdateFinishResponse(final boolean success) {
|
||||
if (success) {
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized("request agps config");
|
||||
final ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("request agps config");
|
||||
configService.requestConfig(builder, ZeppOsConfigService.ConfigGroup.AGPS);
|
||||
builder.queue(getQueue());
|
||||
builder.queue(getSupport());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to request agps config", e);
|
||||
}
|
||||
@@ -133,9 +131,9 @@ public class ZeppOsAgpsUpdateOperation extends AbstractBTLEOperation<ZeppOsSuppo
|
||||
|
||||
private void updateProgress(final int progressPercent) {
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized("send agps update progress");
|
||||
builder.add(new SetProgressAction(getContext().getString(R.string.updatefirmwareoperation_update_in_progress), true, progressPercent, getContext()));
|
||||
builder.queue(getQueue());
|
||||
final ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("send agps update progress");
|
||||
builder.setProgress(getContext().getString(R.string.updatefirmwareoperation_update_in_progress), true, progressPercent, getContext());
|
||||
builder.queue(getSupport());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to update progress notification", e);
|
||||
}
|
||||
|
||||
+12
-19
@@ -42,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressActi
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.update.UpdateFirmwareOperation2020;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.AbstractMiBandOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@@ -177,9 +178,9 @@ public class ZeppOsFirmwareUpdateOperation extends AbstractMiBandOperation<ZeppO
|
||||
break;
|
||||
case UpdateFirmwareOperation2020.COMMAND_FINALIZE_UPDATE: {
|
||||
if (fwHelper.getFirmwareType() == HuamiFirmwareType.FIRMWARE) {
|
||||
TransactionBuilder builder = performInitialized("reboot");
|
||||
getSupport().sendReboot(builder);
|
||||
builder.queue(getQueue());
|
||||
ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("reboot");
|
||||
builder.write(HuamiService.UUID_CHARACTERISTIC_FIRMWARE, new byte[]{HuamiService.COMMAND_FIRMWARE_REBOOT});
|
||||
builder.queue(getSupport());
|
||||
} else {
|
||||
GB.updateInstallNotification(getContext().getString(R.string.updatefirmwareoperation_update_complete), false, 100, getContext());
|
||||
done();
|
||||
@@ -225,24 +226,16 @@ public class ZeppOsFirmwareUpdateOperation extends AbstractMiBandOperation<ZeppO
|
||||
if (ArrayUtils.startsWith(value, new byte[]{HuamiService.RESPONSE, UpdateFirmwareOperation2020.COMMAND_FINALIZE_UPDATE, HuamiService.SUCCESS})) {
|
||||
if (fwHelper.getFirmwareType() == HuamiFirmwareType.APP) {
|
||||
// After an app is installed, request the display items from the band (new app will be at the end)
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("request display items and apps");
|
||||
getSupport().requestDisplayItems(builder);
|
||||
getSupport().requestApps(builder);
|
||||
builder.queue(getQueue());
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to request display items after app install", e);
|
||||
}
|
||||
ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("request display items and apps");
|
||||
getSupport().requestDisplayItems(builder);
|
||||
getSupport().requestApps(builder);
|
||||
builder.queue(getSupport());
|
||||
} else if (fwHelper.getFirmwareType() == HuamiFirmwareType.WATCHFACE) {
|
||||
// After a watchface is installed, request the watchfaces from the band (new watchface will be at the end)
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("request watchfaces and apps");
|
||||
getSupport().requestWatchfaces(builder);
|
||||
getSupport().requestApps(builder);
|
||||
builder.queue(getQueue());
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to request watchfaces after watchface install", e);
|
||||
}
|
||||
ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("request watchfaces and apps");
|
||||
getSupport().requestWatchfaces(builder);
|
||||
getSupport().requestApps(builder);
|
||||
builder.queue(getSupport());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -22,15 +22,13 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class ZeppOsGpxRouteUploadOperation extends AbstractBTLEOperation<ZeppOsSupport>
|
||||
public class ZeppOsGpxRouteUploadOperation extends AbstractZeppOsOperation<ZeppOsSupport>
|
||||
implements ZeppOsFileTransferService.UploadCallback {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsGpxRouteUploadOperation.class);
|
||||
|
||||
@@ -91,9 +89,9 @@ public class ZeppOsGpxRouteUploadOperation extends AbstractBTLEOperation<ZeppOsS
|
||||
|
||||
private void updateProgress(final int progressPercent) {
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized("send gpx route upload progress");
|
||||
builder.add(new SetProgressAction(getContext().getString(R.string.gpx_route_upload_in_progress), true, progressPercent, getContext()));
|
||||
builder.queue(getQueue());
|
||||
final ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("send gpx route upload progress");
|
||||
builder.setProgress(getContext().getString(R.string.gpx_route_upload_in_progress), true, progressPercent, getContext());
|
||||
builder.queue(getSupport());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to update progress notification", e);
|
||||
}
|
||||
|
||||
+5
-7
@@ -23,16 +23,14 @@ import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.audio.AudioInfo;
|
||||
|
||||
public class ZeppOsMusicUploadOperation extends AbstractBTLEOperation<ZeppOsSupport>
|
||||
public class ZeppOsMusicUploadOperation extends AbstractZeppOsOperation<ZeppOsSupport>
|
||||
implements ZeppOsFileTransferService.UploadCallback {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsMusicUploadOperation.class);
|
||||
|
||||
@@ -99,9 +97,9 @@ public class ZeppOsMusicUploadOperation extends AbstractBTLEOperation<ZeppOsSupp
|
||||
|
||||
private void updateProgress(final int progressPercent) {
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized("send music upload progress");
|
||||
builder.add(new SetProgressAction(getContext().getString(R.string.music_upload_in_progress), true, progressPercent, getContext()));
|
||||
builder.queue(getQueue());
|
||||
final ZeppOsTransactionBuilder builder = getSupport().createZeppOsTransactionBuilder("send music upload progress");
|
||||
builder.setProgress(getContext().getString(R.string.music_upload_in_progress), true, progressPercent, getContext());
|
||||
builder.queue(getSupport());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to update progress notification", e);
|
||||
}
|
||||
|
||||
+6
@@ -27,6 +27,7 @@ import java.nio.ByteOrder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
|
||||
public class ZeppOsAgpsService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsAgpsService.class);
|
||||
@@ -81,6 +82,11 @@ public class ZeppOsAgpsService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
this.mCallback = null;
|
||||
}
|
||||
|
||||
public void startUpload(final int size) {
|
||||
final ByteBuffer buf = ByteBuffer.allocate(5)
|
||||
.order(ByteOrder.LITTLE_ENDIAN)
|
||||
|
||||
+33
-11
@@ -17,25 +17,29 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class ZeppOsAlarmsService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsAlarmsService.class);
|
||||
@@ -99,27 +103,45 @@ public class ZeppOsAlarmsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestAlarms(builder);
|
||||
}
|
||||
|
||||
private void requestAlarms() {
|
||||
try {
|
||||
final TransactionBuilder builder = new TransactionBuilder("request alarms");
|
||||
requestAlarms(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to request alarms", e);
|
||||
}
|
||||
withTransactionBuilder("request alarms", this::requestAlarms);
|
||||
}
|
||||
|
||||
public void requestAlarms(final TransactionBuilder builder) {
|
||||
public void requestAlarms(final ZeppOsTransactionBuilder builder) {
|
||||
LOG.info("Requesting alarms");
|
||||
|
||||
write(builder, new byte[]{CMD_REQUEST});
|
||||
}
|
||||
|
||||
public void sendAlarm(final Alarm alarm, final TransactionBuilder builder) {
|
||||
public void onSetAlarms(final ArrayList<? extends Alarm> alarms) {
|
||||
final int maxAlarms = getCoordinator().getAlarmSlotCount(getSupport().getDevice());
|
||||
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder("set alarms");
|
||||
boolean anyAlarmEnabled = false;
|
||||
for (final Alarm alarm : alarms) {
|
||||
if (alarm.getPosition() >= maxAlarms) {
|
||||
if (alarm.getEnabled()) {
|
||||
GB.toast(getContext(), "Only " + maxAlarms + " alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
anyAlarmEnabled |= alarm.getEnabled();
|
||||
sendAlarm(alarm, builder);
|
||||
}
|
||||
builder.queue(getSupport());
|
||||
if (anyAlarmEnabled) {
|
||||
GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO);
|
||||
} else {
|
||||
GB.toast(getContext(), getContext().getString(R.string.user_feedback_all_alarms_disabled), Toast.LENGTH_SHORT, GB.INFO);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendAlarm(final Alarm alarm, final ZeppOsTransactionBuilder builder) {
|
||||
final DeviceCoordinator coordinator = getSupport().getDevice().getDeviceCoordinator();
|
||||
|
||||
final Calendar calendar = AlarmUtils.toCalendar(alarm);
|
||||
|
||||
+6
-5
@@ -28,9 +28,9 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
|
||||
public class ZeppOsAppsService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsAppsService.class);
|
||||
@@ -78,7 +78,7 @@ public class ZeppOsAppsService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestApps(builder);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ZeppOsAppsService extends AbstractZeppOsService {
|
||||
|
||||
private void handleAppsPayload(final byte[] payload) {
|
||||
if (payload[1] != CMD_INCOMING) {
|
||||
LOG.warn("Unexpected non-incoming payload ({})", String.format("0x%02x", payload[1]));
|
||||
LOG.warn("Unexpected non-incoming apps payload ({})", String.format("0x%02x", payload[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,9 +115,10 @@ public class ZeppOsAppsService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
/** @noinspection SwitchStatementWithTooFewBranches*/
|
||||
private void handleScreenshotPayload(final byte[] payload) {
|
||||
if (payload[1] != CMD_INCOMING) {
|
||||
LOG.warn("Unexpected non-incoming payload ({})", String.format("0x%02x", payload[1]));
|
||||
LOG.warn("Unexpected non-incoming screenshot payload ({})", String.format("0x%02x", payload[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -164,7 +165,7 @@ public class ZeppOsAppsService extends AbstractZeppOsService {
|
||||
// TODO broadcast something to update app manager
|
||||
}
|
||||
|
||||
public void requestApps(final TransactionBuilder builder) {
|
||||
public void requestApps(final ZeppOsTransactionBuilder builder) {
|
||||
LOG.info("Request apps");
|
||||
|
||||
final ByteBuffer buf = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
+40
-5
@@ -48,9 +48,9 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePref
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
@@ -140,6 +140,25 @@ public class ZeppOsAssistantService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
opusDecoder = null;
|
||||
if (audioTrack != null) {
|
||||
audioTrack.release();
|
||||
audioTrack = null;
|
||||
}
|
||||
if (rawVoiceOutputStream != null) {
|
||||
try {
|
||||
rawVoiceOutputStream.close();
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to close raw voice output stream", e);
|
||||
}
|
||||
rawVoiceOutputStream = null;
|
||||
}
|
||||
voiceBuffer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSendConfiguration(final String config, final Prefs prefs) {
|
||||
switch (config) {
|
||||
@@ -170,13 +189,29 @@ public class ZeppOsAssistantService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
opusDecoder = null;
|
||||
if (audioTrack != null) {
|
||||
audioTrack.release();
|
||||
audioTrack = null;
|
||||
}
|
||||
if (rawVoiceOutputStream != null) {
|
||||
try {
|
||||
rawVoiceOutputStream.close();
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to close raw voice output stream", e);
|
||||
}
|
||||
rawVoiceOutputStream = null;
|
||||
}
|
||||
voiceBuffer.clear();
|
||||
|
||||
if (ZeppOsCoordinator.experimentalFeatures(getSupport().getDevice())) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
@@ -285,13 +320,13 @@ public class ZeppOsAssistantService extends AbstractZeppOsService {
|
||||
|
||||
public void sendVoiceReply(final List<byte[]> voiceFrames) {
|
||||
try {
|
||||
final TransactionBuilder builder = getSupport().performInitialized("send voice reply");
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder("send voice reply");
|
||||
|
||||
for (final byte[] voiceFrame : voiceFrames) {
|
||||
// TODO encode
|
||||
}
|
||||
|
||||
builder.queue(getSupport().getQueue());
|
||||
builder.queue(getSupport());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to send voice reply", e);
|
||||
}
|
||||
|
||||
+3
-11
@@ -29,10 +29,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CryptoUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ECDH_B163;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@@ -122,14 +121,7 @@ public class ZeppOsAuthenticationService extends AbstractZeppOsService {
|
||||
LOG.debug("Auth Success");
|
||||
|
||||
try {
|
||||
// Authenticated, now initialize phase 2
|
||||
final TransactionBuilder builder = getSupport().createTransactionBuilder("Authenticated, now initialize phase 2");
|
||||
builder.add(new SetDeviceStateAction(getSupport().getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||
builder.setCallback(null); // remove init operation as the callback
|
||||
getSupport().phase2Initialize(builder);
|
||||
getSupport().phase3Initialize(builder);
|
||||
getSupport().setInitialized(builder);
|
||||
getSupport().performImmediately(builder);
|
||||
getSupport().onAuthenticationSuccess();
|
||||
} catch (Exception e) {
|
||||
LOG.error("failed initializing device", e);
|
||||
}
|
||||
@@ -139,7 +131,7 @@ public class ZeppOsAuthenticationService extends AbstractZeppOsService {
|
||||
LOG.warn("Got unknown auth byte {}", String.format("0x%02x", payload[0]));
|
||||
}
|
||||
|
||||
public void startAuthentication(final TransactionBuilder builder) {
|
||||
public void startAuthentication(final ZeppOsTransactionBuilder builder) {
|
||||
new Random().nextBytes(privateEC);
|
||||
|
||||
final byte[] pub = ECDH_B163.ecdh_generate_public(privateEC);
|
||||
|
||||
+3
-3
@@ -21,10 +21,10 @@ import static org.apache.commons.lang3.ArrayUtils.subarray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
|
||||
public class ZeppOsBatteryService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsBatteryService.class);
|
||||
@@ -59,11 +59,11 @@ public class ZeppOsBatteryService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestBatteryInfo(builder);
|
||||
}
|
||||
|
||||
public void requestBatteryInfo(final TransactionBuilder builder) {
|
||||
public void requestBatteryInfo(final ZeppOsTransactionBuilder builder) {
|
||||
LOG.debug("Requesting Battery Info");
|
||||
|
||||
write(builder, CMD_BATTERY_REQUEST);
|
||||
|
||||
+3
-3
@@ -26,9 +26,9 @@ import java.nio.charset.StandardCharsets;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
public class ZeppOsCalendarService extends AbstractZeppOsService {
|
||||
@@ -59,11 +59,11 @@ public class ZeppOsCalendarService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -35,9 +35,9 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificati
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
public class ZeppOsCannedMessagesService extends AbstractZeppOsService {
|
||||
@@ -99,7 +99,7 @@ public class ZeppOsCannedMessagesService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestCannedMessages(builder);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class ZeppOsCannedMessagesService extends AbstractZeppOsService {
|
||||
return;
|
||||
}
|
||||
|
||||
final TransactionBuilder builder = new TransactionBuilder("set canned messages");
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder("set canned messages");
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
LOG.debug("Deleting canned message {}", i);
|
||||
@@ -135,10 +135,10 @@ public class ZeppOsCannedMessagesService extends AbstractZeppOsService {
|
||||
buf.put(cannedMessage.getBytes(StandardCharsets.UTF_8));
|
||||
write(builder, buf.array());
|
||||
}
|
||||
builder.queue(getSupport().getQueue());
|
||||
builder.queue(getSupport());
|
||||
}
|
||||
|
||||
public void requestCannedMessages(final TransactionBuilder builder) {
|
||||
public void requestCannedMessages(final ZeppOsTransactionBuilder builder) {
|
||||
LOG.info("Requesting canned messages");
|
||||
|
||||
write(builder, new byte[]{CMD_REQUEST});
|
||||
|
||||
+32
-23
@@ -24,6 +24,8 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.LANGUAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsConfigService.ConfigArg.LANGUAGE_FOLLOW_PHONE;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
@@ -75,11 +77,11 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.DoNotDisturb;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsMenuType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiLanguageType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MapUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
@@ -133,7 +135,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
requestAllConfigs(builder);
|
||||
}
|
||||
@@ -149,24 +151,22 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
case ActivityUser.PREF_USER_GOAL_WEIGHT_KG:
|
||||
case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS:
|
||||
case ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES: {
|
||||
final TransactionBuilder builder = new TransactionBuilder("set fitness goal");
|
||||
setFitnessGoal(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("set fitness goal", this::setFitnessGoal);
|
||||
return true;
|
||||
}
|
||||
// Measurement system is global
|
||||
case SettingsActivity.PREF_MEASUREMENT_SYSTEM: {
|
||||
final TransactionBuilder builder = new TransactionBuilder("set measurement system");
|
||||
setMeasurementSystem(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("set measurement system", this::setMeasurementSystem);
|
||||
return true;
|
||||
}
|
||||
// Password needs sanity checks
|
||||
case PasswordCapabilityImpl.PREF_PASSWORD:
|
||||
case PasswordCapabilityImpl.PREF_PASSWORD_ENABLED: {
|
||||
final TransactionBuilder builder = new TransactionBuilder("set " + prefKey);
|
||||
setPassword(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("set " + prefKey, this::setPassword);
|
||||
return true;
|
||||
}
|
||||
case PREF_LANGUAGE: {
|
||||
withTransactionBuilder("set language", this::setLanguage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -179,9 +179,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
if (setConfig(prefs, prefKey, configSetter)) {
|
||||
try {
|
||||
// If the ConfigSetter was able to set the config, just write it and return
|
||||
final TransactionBuilder builder = new TransactionBuilder("send config " + prefKey);
|
||||
configSetter.write(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("send config " + prefKey, configSetter::write);
|
||||
} catch (final Exception e) {
|
||||
GB.toast("Error setting configuration", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
}
|
||||
@@ -192,7 +190,18 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setPassword(final TransactionBuilder builder) {
|
||||
private void setLanguage(final ZeppOsTransactionBuilder builder) {
|
||||
final String localeString = getDevicePrefs().getString("language", "auto");
|
||||
|
||||
LOG.info("Setting device language to {}", localeString);
|
||||
|
||||
newSetter()
|
||||
.setByte(LANGUAGE, getDevicePrefs().getLanguageId())
|
||||
.setBoolean(LANGUAGE_FOLLOW_PHONE, localeString.equals("auto"))
|
||||
.write(builder);
|
||||
}
|
||||
|
||||
private void setPassword(final ZeppOsTransactionBuilder builder) {
|
||||
final boolean passwordEnabled = HuamiCoordinator.getPasswordEnabled(getSupport().getDevice().getAddress());
|
||||
final String password = HuamiCoordinator.getPassword(getSupport().getDevice().getAddress());
|
||||
|
||||
@@ -209,7 +218,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
.write(builder);
|
||||
}
|
||||
|
||||
protected void setFitnessGoal(final TransactionBuilder builder) {
|
||||
protected void setFitnessGoal(final ZeppOsTransactionBuilder builder) {
|
||||
final int goalSteps = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal);
|
||||
final int goalCalories = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_CALORIES_BURNT, ActivityUser.defaultUserCaloriesBurntGoal);
|
||||
final int goalSleep = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION, ActivityUser.defaultUserSleepDurationGoal);
|
||||
@@ -228,7 +237,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
.write(builder);
|
||||
}
|
||||
|
||||
private void setMeasurementSystem(final TransactionBuilder builder) {
|
||||
private void setMeasurementSystem(final ZeppOsTransactionBuilder builder) {
|
||||
final String measurementSystem = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, "metric");
|
||||
LOG.info("Setting measurement system to {}", measurementSystem);
|
||||
|
||||
@@ -312,11 +321,11 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
getSupport().evaluateGBDeviceEvent(eventUpdatePreferences);
|
||||
|
||||
if (getSupport().getDevice().isInitialized()) {
|
||||
if (prefs.containsKey(PREF_LANGUAGE) && prefs.get(PREF_LANGUAGE).equals(PREF_LANGUAGE_AUTO)) {
|
||||
if (prefs.containsKey(PREF_LANGUAGE) && PREF_LANGUAGE_AUTO.equals(prefs.get(PREF_LANGUAGE))) {
|
||||
// Band is reporting automatic language, we need to send the actual language
|
||||
getSupport().onSendConfiguration(PREF_LANGUAGE);
|
||||
}
|
||||
if (prefs.containsKey(PREF_TIMEFORMAT) && prefs.get(PREF_TIMEFORMAT).equals(PREF_TIMEFORMAT_AUTO)) {
|
||||
if (prefs.containsKey(PREF_TIMEFORMAT) && PREF_TIMEFORMAT_AUTO.equals(prefs.get(PREF_TIMEFORMAT))) {
|
||||
// Band is reporting automatic time format, we need to send the actual time format
|
||||
getSupport().onSendConfiguration(PREF_TIMEFORMAT);
|
||||
}
|
||||
@@ -329,17 +338,17 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestAllConfigs(final TransactionBuilder builder) {
|
||||
public void requestAllConfigs(final ZeppOsTransactionBuilder builder) {
|
||||
for (final ConfigGroup configGroup : ConfigGroup.values()) {
|
||||
requestConfig(builder, configGroup);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestConfig(final TransactionBuilder builder, final ConfigGroup config) {
|
||||
public void requestConfig(final ZeppOsTransactionBuilder builder, final ConfigGroup config) {
|
||||
requestConfig(builder, config, true, ZeppOsConfigService.ConfigArg.getAllArgsForConfigGroup(config));
|
||||
}
|
||||
|
||||
public void requestConfig(final TransactionBuilder builder,
|
||||
public void requestConfig(final ZeppOsTransactionBuilder builder,
|
||||
final ConfigGroup config,
|
||||
final boolean includeConstraints,
|
||||
final List<ZeppOsConfigService.ConfigArg> args) {
|
||||
@@ -906,7 +915,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public void write(final TransactionBuilder builder) {
|
||||
public void write(final ZeppOsTransactionBuilder builder) {
|
||||
// Write one command per config group
|
||||
for (final ConfigGroup configGroup : arguments.keySet()) {
|
||||
ZeppOsConfigService.this.write(builder, encode(configGroup));
|
||||
|
||||
+2
-2
@@ -20,9 +20,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
|
||||
public class ZeppOsConnectionService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsConnectionService.class);
|
||||
@@ -61,7 +61,7 @@ public class ZeppOsConnectionService extends AbstractZeppOsService {
|
||||
LOG.warn("Unexpected connection payload byte {}", String.format("0x%02x", payload[0]));
|
||||
}
|
||||
|
||||
public void requestMTU(final TransactionBuilder builder) {
|
||||
public void requestMTU(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_MTU_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -26,9 +26,9 @@ import java.util.List;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
public class ZeppOsContactsService extends AbstractZeppOsService {
|
||||
@@ -41,7 +41,6 @@ public class ZeppOsContactsService extends AbstractZeppOsService {
|
||||
public static final byte CMD_SET_LIST = 0x07;
|
||||
public static final byte CMD_SET_LIST_ACK = 0x08;
|
||||
|
||||
private int version = 0;
|
||||
private int maxContacts = 0;
|
||||
|
||||
public static final String PREF_CONTACTS_SLOT_COUNT = "zepp_os_contacts_slot_count";
|
||||
@@ -59,7 +58,7 @@ public class ZeppOsContactsService extends AbstractZeppOsService {
|
||||
public void handlePayload(final byte[] payload) {
|
||||
switch (payload[0]) {
|
||||
case CMD_CAPABILITIES_RESPONSE:
|
||||
version = payload[1];
|
||||
final int version = payload[1];
|
||||
if (version != 1) {
|
||||
LOG.warn("Unsupported contacts service version {}", version);
|
||||
return;
|
||||
@@ -77,11 +76,11 @@ public class ZeppOsContactsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+8
-11
@@ -40,10 +40,10 @@ import java.util.regex.Pattern;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsMenuType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MapUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -123,7 +123,7 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestItems(builder, DISPLAY_ITEMS_MENU);
|
||||
requestItems(builder, DISPLAY_ITEMS_SHORTCUTS);
|
||||
if (getCoordinator().supportsControlCenter()) {
|
||||
@@ -131,7 +131,7 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestItems(final TransactionBuilder builder, final byte type) {
|
||||
public void requestItems(final ZeppOsTransactionBuilder builder, final byte type) {
|
||||
LOG.info("Requesting display items type={}", type);
|
||||
|
||||
write(builder, new byte[]{CMD_REQUEST, type});
|
||||
@@ -266,16 +266,13 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
||||
final List<String> allSettings,
|
||||
List<String> enabledList,
|
||||
final FlagsMap flags) {
|
||||
try {
|
||||
final TransactionBuilder builder = new TransactionBuilder("set display items type " + menuType);
|
||||
setDisplayItems(builder, menuType, allSettings, enabledList, flags);
|
||||
builder.queue(getSupport().getQueue());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to set display items", e);
|
||||
}
|
||||
withTransactionBuilder(
|
||||
"set display items type " + menuType,
|
||||
builder -> setDisplayItems(builder, menuType, allSettings, enabledList, flags)
|
||||
);
|
||||
}
|
||||
|
||||
private void setDisplayItems(final TransactionBuilder builder,
|
||||
private void setDisplayItems(final ZeppOsTransactionBuilder builder,
|
||||
final byte menuType,
|
||||
final List<String> allSettings,
|
||||
List<String> enabledList,
|
||||
|
||||
+2
-2
@@ -21,9 +21,9 @@ import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.filetransfer.ZeppOsFileTransferImpl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.filetransfer.ZeppOsFileTransferV2;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.filetransfer.ZeppOsFileTransferV3;
|
||||
@@ -77,7 +77,7 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, new byte[]{ZeppOsFileTransferImpl.CMD_CAPABILITIES_REQUEST});
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -22,10 +22,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ZeppOsFindDeviceService extends AbstractZeppOsService {
|
||||
@@ -128,7 +128,7 @@ public class ZeppOsFindDeviceService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -26,9 +26,9 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -133,7 +133,14 @@ public class ZeppOsFtpServerService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
mCallback = null;
|
||||
|
||||
final GBDeviceEventUpdatePreferences evt = new GBDeviceEventUpdatePreferences()
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_ADDRESS, null)
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_USERNAME, null)
|
||||
.withPreference(DeviceSettingsPreferenceConst.FTP_SERVER_STATUS, null);
|
||||
evaluateGBDeviceEvent(evt);
|
||||
}
|
||||
|
||||
public void setCallback(final Callback callback) {
|
||||
|
||||
+8
-14
@@ -16,7 +16,6 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.os.Handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -26,9 +25,9 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSleepState
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.SleepState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.RealtimeSamplesAggregator;
|
||||
|
||||
public class ZeppOsHeartRateService extends AbstractZeppOsService {
|
||||
@@ -111,10 +110,10 @@ public class ZeppOsHeartRateService extends AbstractZeppOsService {
|
||||
realtimeStarted = true;
|
||||
realtimeOneShot = true;
|
||||
|
||||
final TransactionBuilder builder = new TransactionBuilder("HeartRateTest");
|
||||
builder.notify(getSupport().getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT), true);
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder("HeartRateTest");
|
||||
builder.notify(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT, true);
|
||||
write(builder, new byte[]{CMD_REALTIME_SET, REALTIME_MODE_START});
|
||||
builder.queue(getSupport().getQueue());
|
||||
builder.queue(getSupport());
|
||||
|
||||
realtimeHandler.removeCallbacksAndMessages(null);
|
||||
scheduleContinue();
|
||||
@@ -133,13 +132,10 @@ public class ZeppOsHeartRateService extends AbstractZeppOsService {
|
||||
realtimeStarted = enable;
|
||||
realtimeOneShot = false;
|
||||
|
||||
final TransactionBuilder builder = new TransactionBuilder("set realtime heart rate measurement = " + enable);
|
||||
final BluetoothGattCharacteristic hrCharacteristic = getSupport().getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT);
|
||||
if (hrCharacteristic != null) {
|
||||
builder.notify(getSupport().getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT), enable);
|
||||
}
|
||||
final ZeppOsTransactionBuilder builder = createTransactionBuilder("set realtime heart rate measurement = " + enable);
|
||||
builder.notify(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT, enable);
|
||||
write(builder, new byte[]{CMD_REALTIME_SET, hrCmd});
|
||||
builder.queue(getSupport().getQueue());
|
||||
builder.queue(getSupport());
|
||||
|
||||
realtimeHandler.removeCallbacksAndMessages(null);
|
||||
if (enable) {
|
||||
@@ -178,8 +174,6 @@ public class ZeppOsHeartRateService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
private void sendContinue() {
|
||||
final TransactionBuilder builder = new TransactionBuilder("hr continue");
|
||||
write(builder, new byte[]{CMD_REALTIME_SET, REALTIME_MODE_CONTINUE});
|
||||
builder.queue(getSupport().getQueue());
|
||||
write("hr continue", new byte[]{CMD_REALTIME_SET, REALTIME_MODE_CONTINUE});
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -35,6 +35,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsWeather;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
@@ -120,6 +121,12 @@ public class ZeppOsHttpService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
urlToLocalFile.clear();
|
||||
urlDownloadCallbacks.clear();
|
||||
}
|
||||
|
||||
public void registerForDownload(final String url, final Uri uri, @Nullable final Callback callback) {
|
||||
this.urlToLocalFile.put(url, uri);
|
||||
this.urlDownloadCallbacks.put(url, callback);
|
||||
|
||||
+3
-6
@@ -32,9 +32,9 @@ import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -119,11 +119,8 @@ public class ZeppOsLogsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
sessions.clear();
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -30,9 +30,9 @@ import java.util.Objects;
|
||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.BarcodeFormat;
|
||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MapUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
@@ -116,7 +116,7 @@ public class ZeppOsLoyaltyCardService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public class ZeppOsLoyaltyCardService extends AbstractZeppOsService {
|
||||
return supportedFormats;
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,9 +34,9 @@ import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsMapsFile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ZeppOsMapsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -26,15 +26,16 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MapUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -54,15 +55,15 @@ public class ZeppOsMorningUpdatesService extends AbstractZeppOsService {
|
||||
private static final byte CMD_CATEGORIES_SET_ACK = 0x0a;
|
||||
|
||||
private static final Map<Byte, String> MORNING_UPDATES_MAP = new HashMap<Byte, String>() {{
|
||||
put((byte) 0x02, "weather");
|
||||
put((byte) 0x03, "battery");
|
||||
put((byte) 0x04, "sleep");
|
||||
put((byte) 0x06, "event");
|
||||
put((byte) 0x07, "pai");
|
||||
put((byte) 0x08, "yesterdays_activity");
|
||||
put((byte) 0x09, "zepp_coach");
|
||||
put((byte) 0x0a, "cycle_tracking");
|
||||
put((byte) 0x0b, "readiness");
|
||||
put((byte) 0x02, "weather");
|
||||
put((byte) 0x03, "battery");
|
||||
put((byte) 0x04, "sleep");
|
||||
put((byte) 0x06, "event");
|
||||
put((byte) 0x07, "pai");
|
||||
put((byte) 0x08, "yesterdays_activity");
|
||||
put((byte) 0x09, "zepp_coach");
|
||||
put((byte) 0x0a, "cycle_tracking");
|
||||
put((byte) 0x0b, "readiness");
|
||||
}};
|
||||
|
||||
public ZeppOsMorningUpdatesService(ZeppOsSupport support) {
|
||||
@@ -128,12 +129,12 @@ public class ZeppOsMorningUpdatesService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
getEnabled(builder);
|
||||
getCategories(builder);
|
||||
}
|
||||
|
||||
public void getEnabled(final TransactionBuilder builder) {
|
||||
public void getEnabled(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_ENABLED_GET);
|
||||
}
|
||||
|
||||
@@ -141,7 +142,7 @@ public class ZeppOsMorningUpdatesService extends AbstractZeppOsService {
|
||||
write("set morning updates enabled", new byte[] {CMD_ENABLED_SET, bool(enabled)});
|
||||
}
|
||||
|
||||
public void getCategories(final TransactionBuilder builder) {
|
||||
public void getCategories(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CATEGORIES_REQUEST);
|
||||
}
|
||||
|
||||
@@ -165,12 +166,12 @@ public class ZeppOsMorningUpdatesService extends AbstractZeppOsService {
|
||||
for (final String category : categoriesSorted) {
|
||||
final byte id;
|
||||
if (idMap.containsKey(category)) {
|
||||
id = idMap.get(category);
|
||||
id = Objects.requireNonNull(idMap.get(category));
|
||||
} else {
|
||||
// name doesn't match a known value, attempt to parse it as hex
|
||||
final Matcher matcher = Pattern.compile("^0[xX]([0-9a-fA-F]{1,2})$").matcher(category);
|
||||
if (matcher.find()) {
|
||||
id = (byte) Integer.parseInt(matcher.group(1), 16);
|
||||
id = (byte) Integer.parseInt(Objects.requireNonNull(matcher.group(1)), 16);
|
||||
} else {
|
||||
LOG.warn("Unknown category {}, and failed to parse as hex, not setting", category);
|
||||
return;
|
||||
|
||||
+52
-4
@@ -16,6 +16,9 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -26,6 +29,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MediaManager;
|
||||
|
||||
public class ZeppOsMusicService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsMusicService.class);
|
||||
@@ -44,6 +49,10 @@ public class ZeppOsMusicService extends AbstractZeppOsService {
|
||||
private static final byte BUTTON_VOLUME_UP = 0x05;
|
||||
private static final byte BUTTON_VOLUME_DOWN = 0x06;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private MediaManager mediaManager;
|
||||
protected boolean isMusicAppStarted = false;
|
||||
|
||||
public ZeppOsMusicService(final ZeppOsSupport support) {
|
||||
super(support, false);
|
||||
}
|
||||
@@ -103,16 +112,42 @@ public class ZeppOsMusicService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
if (mediaManager == null) {
|
||||
mediaManager = new MediaManager(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
public void onSetMusicState(final MusicStateSpec stateSpec) {
|
||||
if (mediaManager.onSetMusicState(stateSpec) && isMusicAppStarted) {
|
||||
sendMusicState(null, mediaManager.getBufferMusicStateSpec());
|
||||
}
|
||||
}
|
||||
|
||||
public void onSetMusicInfo(final MusicSpec musicSpec) {
|
||||
if (mediaManager.onSetMusicInfo(musicSpec) && isMusicAppStarted) {
|
||||
sendMusicState(mediaManager.getBufferMusicSpec(), mediaManager.getBufferMusicStateSpec());
|
||||
}
|
||||
}
|
||||
|
||||
private void onMusicAppOpen() {
|
||||
getSupport().onMusicAppOpen();
|
||||
isMusicAppStarted = true;
|
||||
sendMusicStateDelayed();
|
||||
}
|
||||
|
||||
private void onMusicAppClosed() {
|
||||
getSupport().onMusicAppClosed();
|
||||
LOG.info("Music app terminated");
|
||||
isMusicAppStarted = false;
|
||||
}
|
||||
|
||||
public void sendMusicState(final MusicSpec musicSpec,
|
||||
final MusicStateSpec musicStateSpec) {
|
||||
private void sendMusicState(final MusicSpec musicSpec,
|
||||
final MusicStateSpec musicStateSpec) {
|
||||
LOG.info("Sending music: {}, {}", musicSpec, musicStateSpec);
|
||||
|
||||
// TODO: Encode not playing state (flag 0x20, single 0x01 byte before volume)
|
||||
@@ -124,6 +159,19 @@ public class ZeppOsMusicService extends AbstractZeppOsService {
|
||||
write("send music state", cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the music state after a small delay. If we send it right as the app notifies us that it opened,
|
||||
* it won't be recognized.
|
||||
*/
|
||||
private void sendMusicStateDelayed() {
|
||||
final Looper mainLooper = Looper.getMainLooper();
|
||||
new Handler(mainLooper).postDelayed(() -> {
|
||||
mediaManager.refresh();
|
||||
sendMusicState(mediaManager.getBufferMusicSpec(), mediaManager.getBufferMusicStateSpec());
|
||||
sendVolume(mediaManager.getPhoneVolume());
|
||||
}, 100);
|
||||
}
|
||||
|
||||
public void sendVolume(final float volume) {
|
||||
LOG.info("Sending volume: {}", volume);
|
||||
|
||||
|
||||
+8
-16
@@ -42,10 +42,10 @@ import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsBitmapFormat;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
|
||||
@@ -103,11 +103,7 @@ public class ZeppOsNotificationService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, NOTIFICATION_CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
@@ -255,8 +251,6 @@ public class ZeppOsNotificationService extends AbstractZeppOsService {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
final TransactionBuilder builder = new TransactionBuilder("send notification");
|
||||
|
||||
baos.write(NOTIFICATION_CMD_SEND);
|
||||
|
||||
// ID
|
||||
@@ -285,12 +279,12 @@ public class ZeppOsNotificationService extends AbstractZeppOsService {
|
||||
|
||||
// TODO put this behind a setting?
|
||||
baos.write(callSpec.number != null ? 0x01 : 0x00); // reply from watch
|
||||
|
||||
write(builder, baos.toByteArray());
|
||||
builder.queue(getSupport().getQueue());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to send call", e);
|
||||
return;
|
||||
}
|
||||
|
||||
write("send notification", baos.toByteArray());
|
||||
}
|
||||
|
||||
public void sendNotification(final NotificationSpec notificationSpec) {
|
||||
@@ -306,8 +300,6 @@ public class ZeppOsNotificationService extends AbstractZeppOsService {
|
||||
// TODO Check real limit for notificationMaxLength / respect across all fields
|
||||
|
||||
try {
|
||||
final TransactionBuilder builder = new TransactionBuilder("send notification");
|
||||
|
||||
baos.write(NOTIFICATION_CMD_SEND);
|
||||
baos.write(BLETypeConversions.fromUint32(notificationSpec.getId()));
|
||||
if (notificationSpec.type == NotificationType.GENERIC_SMS) {
|
||||
@@ -380,12 +372,12 @@ public class ZeppOsNotificationService extends AbstractZeppOsService {
|
||||
}
|
||||
baos.write(0);
|
||||
}
|
||||
|
||||
write(builder, baos.toByteArray());
|
||||
builder.queue(getSupport().getQueue());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to send notification", e);
|
||||
return;
|
||||
}
|
||||
|
||||
write("send notification", baos.toByteArray());
|
||||
}
|
||||
|
||||
public void deleteNotification(final int id) {
|
||||
|
||||
+16
-6
@@ -16,9 +16,13 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
||||
|
||||
import android.Manifest;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresPermission;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -29,9 +33,9 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
@@ -130,7 +134,7 @@ public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
if (getCoordinator().supportsBluetoothPhoneCalls(getSupport().getDevice())) {
|
||||
requestCapabilities(builder);
|
||||
requestEnabled(builder);
|
||||
@@ -141,14 +145,15 @@ public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
return version == 1;
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
public void getPairedStatus() {
|
||||
final String bluetoothName = getBluetoothName();
|
||||
if (bluetoothName == null) {
|
||||
LOG.error("bluetoothName is null");
|
||||
LOG.error("bluetoothName for paired status check is null");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,9 +170,13 @@ public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
public void startPairing() {
|
||||
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
LOG.error("Bluetooth permission not granted");
|
||||
return;
|
||||
}
|
||||
final String bluetoothName = getBluetoothName();
|
||||
if (bluetoothName == null) {
|
||||
LOG.error("bluetoothName is null");
|
||||
LOG.error("bluetoothName for pairing is null");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -183,7 +192,7 @@ public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
write("start phone pairing", buf.array());
|
||||
}
|
||||
|
||||
public void requestEnabled(final TransactionBuilder builder) {
|
||||
public void requestEnabled(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_ENABLED_REQUEST);
|
||||
}
|
||||
|
||||
@@ -198,6 +207,7 @@ public class ZeppOsPhoneService extends AbstractZeppOsService {
|
||||
write("set phone enabled", cmd);
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
@Nullable
|
||||
public String getBluetoothName() {
|
||||
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
+8
-10
@@ -37,9 +37,9 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePref
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
@@ -107,9 +107,7 @@ public class ZeppOsRemindersService extends AbstractZeppOsService {
|
||||
case CMD_RESPONSE:
|
||||
LOG.info("Got reminders from band");
|
||||
decodeAndUpdateReminders(payload);
|
||||
final TransactionBuilder builder = getSupport().createTransactionBuilder("send reminders");
|
||||
sendReminders(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("send reminders", this::sendReminders);
|
||||
return;
|
||||
default:
|
||||
LOG.warn("Unexpected reminders payload byte {}", String.format("0x%02x", payload[0]));
|
||||
@@ -117,25 +115,25 @@ public class ZeppOsRemindersService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
requestReminders(builder);
|
||||
}
|
||||
|
||||
private void requestCapabilities(final TransactionBuilder builder) {
|
||||
private void requestCapabilities(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
private void requestReminders(final TransactionBuilder builder) {
|
||||
private void requestReminders(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_REQUEST);
|
||||
}
|
||||
|
||||
public void sendReminders(final TransactionBuilder builder) {
|
||||
public void sendReminders(final ZeppOsTransactionBuilder builder) {
|
||||
final List<? extends Reminder> reminders = DBHelper.getReminders(getSupport().getDevice());
|
||||
sendReminders(builder, reminders);
|
||||
}
|
||||
|
||||
public void sendReminders(final TransactionBuilder builder, final List<? extends Reminder> reminders) {
|
||||
public void sendReminders(final ZeppOsTransactionBuilder builder, final List<? extends Reminder> reminders) {
|
||||
LOG.info("On Set Reminders: {}", reminders.size());
|
||||
|
||||
final int reminderSlotCount = getCoordinator().getReminderSlotCount(getSupport().getDevice());
|
||||
@@ -209,7 +207,7 @@ public class ZeppOsRemindersService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendReminderToDevice(final TransactionBuilder builder, int position, final boolean update, final ZeppOsReminder reminder) {
|
||||
private void sendReminderToDevice(final ZeppOsTransactionBuilder builder, int position, final boolean update, final ZeppOsReminder reminder) {
|
||||
final DeviceCoordinator coordinator = getCoordinator();
|
||||
final int reminderSlotCount = coordinator.getReminderSlotCount(getSupport().getDevice());
|
||||
if (position + 1 > reminderSlotCount) {
|
||||
|
||||
+3
-2
@@ -22,9 +22,9 @@ import org.slf4j.LoggerFactory;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
|
||||
public class ZeppOsServicesService extends AbstractZeppOsService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsServicesService.class);
|
||||
@@ -43,6 +43,7 @@ public class ZeppOsServicesService extends AbstractZeppOsService {
|
||||
return ENDPOINT;
|
||||
}
|
||||
|
||||
/** @noinspection SwitchStatementWithTooFewBranches*/
|
||||
@Override
|
||||
public void handlePayload(final byte[] payload) {
|
||||
switch (payload[0]) {
|
||||
@@ -54,7 +55,7 @@ public class ZeppOsServicesService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestServices(final TransactionBuilder builder) {
|
||||
public void requestServices(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_GET_LIST);
|
||||
}
|
||||
|
||||
|
||||
+6
-12
@@ -32,15 +32,16 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
@@ -158,6 +159,7 @@ public class ZeppOsShortcutCardsService extends AbstractZeppOsService {
|
||||
}
|
||||
}
|
||||
|
||||
/** @noinspection SwitchStatementWithTooFewBranches*/
|
||||
@Override
|
||||
public boolean onSendConfiguration(final String config, final Prefs prefs) {
|
||||
switch (config) {
|
||||
@@ -172,16 +174,8 @@ public class ZeppOsShortcutCardsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
requestCapabilities(builder);
|
||||
requestShortcutCards(builder);
|
||||
}
|
||||
|
||||
public void requestCapabilities(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CAPABILITIES_REQUEST);
|
||||
}
|
||||
|
||||
public void requestShortcutCards(final TransactionBuilder builder) {
|
||||
write(builder, CMD_LIST_GET);
|
||||
}
|
||||
|
||||
@@ -254,9 +248,9 @@ public class ZeppOsShortcutCardsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
try {
|
||||
baos.write(appNum.getBytes(StandardCharsets.UTF_8));
|
||||
baos.write(Objects.requireNonNull(appNum).getBytes(StandardCharsets.UTF_8));
|
||||
baos.write(0);
|
||||
baos.write(cardNum.getBytes(StandardCharsets.UTF_8));
|
||||
baos.write(Objects.requireNonNull(cardNum).getBytes(StandardCharsets.UTF_8));
|
||||
baos.write(0);
|
||||
baos.write(1); // enabled
|
||||
baos.write(0); // ?
|
||||
|
||||
+5
-6
@@ -34,9 +34,9 @@ import java.time.LocalDate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ZeppOsUserInfoService extends AbstractZeppOsService {
|
||||
@@ -69,10 +69,11 @@ public class ZeppOsUserInfoService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
setUserInfo(builder);
|
||||
}
|
||||
|
||||
/** @noinspection EnhancedSwitchMigration*/
|
||||
@Override
|
||||
public boolean onSendConfiguration(final String config, final Prefs prefs) {
|
||||
switch (config) {
|
||||
@@ -82,16 +83,14 @@ public class ZeppOsUserInfoService extends AbstractZeppOsService {
|
||||
case PREF_USER_HEIGHT_CM:
|
||||
case PREF_USER_GENDER:
|
||||
case PREF_DEVICE_REGION:
|
||||
final TransactionBuilder builder = getSupport().createTransactionBuilder("set user info");
|
||||
setUserInfo(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder("set user info", this::setUserInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setUserInfo(final TransactionBuilder builder) {
|
||||
public void setUserInfo(final ZeppOsTransactionBuilder builder) {
|
||||
LOG.info("Attempting to set user info...");
|
||||
|
||||
final Prefs prefs = GBApplication.getPrefs();
|
||||
|
||||
+8
-7
@@ -31,11 +31,11 @@ import java.util.Locale;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ZeppOsVibrationPatternsService extends AbstractZeppOsService {
|
||||
@@ -68,7 +68,7 @@ public class ZeppOsVibrationPatternsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
for (final HuamiVibrationPatternNotificationType type : getCoordinator().getVibrationPatternNotificationTypes(getSupport().getDevice())) {
|
||||
// FIXME: Can we read these from the band?
|
||||
final String typeKey = type.name().toLowerCase(Locale.ROOT);
|
||||
@@ -81,9 +81,10 @@ public class ZeppOsVibrationPatternsService extends AbstractZeppOsService {
|
||||
if (config.startsWith(HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX) ||
|
||||
config.startsWith(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX) ||
|
||||
config.startsWith(HuamiConst.PREF_HUAMI_VIBRATION_TRY_PREFIX)) {
|
||||
final TransactionBuilder builder = new TransactionBuilder("send " + config);
|
||||
setVibrationPattern(builder, config);
|
||||
builder.queue(getSupport().getQueue());
|
||||
withTransactionBuilder(
|
||||
"send " + config,
|
||||
builder -> setVibrationPattern(builder, config)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -91,7 +92,7 @@ public class ZeppOsVibrationPatternsService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
|
||||
protected void setVibrationPattern(final TransactionBuilder builder, final String preferenceKey) {
|
||||
protected void setVibrationPattern(final ZeppOsTransactionBuilder builder, final String preferenceKey) {
|
||||
// The preference key has one of the 3 prefixes
|
||||
final String notificationTypeName = preferenceKey.replace(PREF_HUAMI_VIBRATION_COUNT_PREFIX, "")
|
||||
.replace(PREF_HUAMI_VIBRATION_PROFILE_PREFIX, "")
|
||||
@@ -109,7 +110,7 @@ public class ZeppOsVibrationPatternsService extends AbstractZeppOsService {
|
||||
setVibrationPattern(builder, notificationType, isTry, vibrationProfile);
|
||||
}
|
||||
|
||||
private void setVibrationPattern(final TransactionBuilder builder,
|
||||
private void setVibrationPattern(final ZeppOsTransactionBuilder builder,
|
||||
final HuamiVibrationPatternNotificationType notificationType,
|
||||
final boolean test,
|
||||
final VibrationProfile profile) {
|
||||
|
||||
+9
@@ -44,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.repository.AudioRecordingsR
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.AudioRecording;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -132,6 +133,14 @@ public class ZeppOsVoiceMemosService extends AbstractZeppOsService {
|
||||
LOG.warn("Unexpected voice memos byte {}", String.format("0x%02x", payload[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
downloadingRecordings.clear();
|
||||
downloadQueue.clear();
|
||||
downloading = false;
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
public void requestList() {
|
||||
write("get voice memos list", CMD_LIST_REQUEST);
|
||||
}
|
||||
|
||||
+5
-11
@@ -39,9 +39,9 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSett
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ZeppOsWatchfaceService extends AbstractZeppOsService {
|
||||
@@ -171,7 +171,7 @@ public class ZeppOsWatchfaceService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
requestWatchfaces(builder);
|
||||
requestCurrentWatchface(builder);
|
||||
}
|
||||
@@ -180,21 +180,15 @@ public class ZeppOsWatchfaceService extends AbstractZeppOsService {
|
||||
return watchfaces;
|
||||
}
|
||||
|
||||
public void requestWatchfaces(final TransactionBuilder builder) {
|
||||
public void requestWatchfaces(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_LIST_GET);
|
||||
}
|
||||
|
||||
public void requestCurrentWatchface() {
|
||||
try {
|
||||
final TransactionBuilder builder = new TransactionBuilder("request current watchface");
|
||||
requestCurrentWatchface(builder);
|
||||
builder.queue(getSupport().getQueue());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to request current watchface", e);
|
||||
}
|
||||
withTransactionBuilder("request current watchface", this::requestCurrentWatchface);
|
||||
}
|
||||
|
||||
public void requestCurrentWatchface(final TransactionBuilder builder) {
|
||||
public void requestCurrentWatchface(final ZeppOsTransactionBuilder builder) {
|
||||
write(builder, CMD_CURRENT_GET);
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -24,7 +24,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
|
||||
@@ -79,9 +78,7 @@ public class ZeppOsWeatherService extends AbstractZeppOsService {
|
||||
baos.write(locationName.getBytes(StandardCharsets.UTF_8));
|
||||
baos.write((byte) 0x00); // ?
|
||||
|
||||
final TransactionBuilder builder = new TransactionBuilder("set weather location");
|
||||
write(builder, baos.toByteArray());
|
||||
builder.queue(getSupport().getQueue());
|
||||
write("set weather location", baos.toByteArray());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to set weather location", e);
|
||||
}
|
||||
|
||||
+6
-2
@@ -28,9 +28,9 @@ import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -127,8 +127,12 @@ public class ZeppOsWifiService extends AbstractZeppOsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final TransactionBuilder builder) {
|
||||
public void initialize(final ZeppOsTransactionBuilder builder) {
|
||||
mCallback = null;
|
||||
|
||||
final GBDeviceEventUpdatePreferences evt = new GBDeviceEventUpdatePreferences()
|
||||
.withPreference(DeviceSettingsPreferenceConst.WIFI_HOTSPOT_STATUS, null);
|
||||
evaluateGBDeviceEvent(evt);
|
||||
}
|
||||
|
||||
public void setCallback(final Callback callback) {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.service
|
||||
/**
|
||||
* Wrapper class to keep track of ongoing file send requests and their progress.
|
||||
*/
|
||||
class FileTransferRequest {
|
||||
public class FileTransferRequest {
|
||||
private final String url;
|
||||
private final String filename;
|
||||
private final int rawLength;
|
||||
|
||||
+5
-5
@@ -19,8 +19,8 @@ import java.util.zip.Inflater;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
@@ -117,10 +117,10 @@ public abstract class ZeppOsFileTransferImpl {
|
||||
|
||||
// TODO: 3 unknown bytes for v3
|
||||
|
||||
final TransactionBuilder builder = mSupport.createTransactionBuilder("enable file transfer v3 notifications");
|
||||
builder.notify(mSupport.getCharacteristic(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND), true);
|
||||
builder.notify(mSupport.getCharacteristic(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_RECEIVE), true);
|
||||
builder.queue(mSupport.getQueue());
|
||||
final ZeppOsTransactionBuilder builder = mSupport.createZeppOsTransactionBuilder("enable file transfer v3 notifications");
|
||||
builder.notify(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND, true);
|
||||
builder.notify(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_RECEIVE, true);
|
||||
builder.queue(mSupport);
|
||||
}
|
||||
|
||||
mSupport.evaluateGBDeviceEvent(new GBDeviceEventUpdatePreferences(PREF_SUPPORTED_SERVICES, new HashSet<>(supportedServices)));
|
||||
|
||||
+5
-6
@@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsTransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
|
||||
|
||||
@@ -65,6 +66,7 @@ public class ZeppOsFileTransferV3 extends ZeppOsFileTransferImpl {
|
||||
super(fileTransferService, support);
|
||||
}
|
||||
|
||||
/** @noinspection SwitchStatementWithTooFewBranches*/
|
||||
@Override
|
||||
public void handlePayload(final byte[] payload) {
|
||||
switch (payload[0]) {
|
||||
@@ -256,15 +258,12 @@ public class ZeppOsFileTransferV3 extends ZeppOsFileTransferImpl {
|
||||
|
||||
final byte[] payload = buf.array();
|
||||
|
||||
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunk v3");
|
||||
final ZeppOsTransactionBuilder builder = mSupport.createZeppOsTransactionBuilder("send chunk v3");
|
||||
for (int i = 0; i < payload.length; i += partSize) {
|
||||
final byte[] part = ArrayUtils.subarray(payload, i, i + partSize);
|
||||
builder.write(
|
||||
mSupport.getCharacteristic(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND),
|
||||
part
|
||||
);
|
||||
builder.write(HuamiService.UUID_CHARACTERISTIC_ZEPP_OS_FILE_TRANSFER_V3_SEND, part);
|
||||
}
|
||||
builder.queue(mSupport.getQueue());
|
||||
builder.queue(mSupport);
|
||||
|
||||
request.setProgress(request.getProgress() + chunk.length);
|
||||
request.setIndex(request.getIndex() + 1);
|
||||
|
||||
+5
-1
@@ -32,7 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
|
||||
public class DevicePrefs extends Prefs {
|
||||
private GBDevice gbDevice;
|
||||
private final GBDevice gbDevice;
|
||||
|
||||
public DevicePrefs(final SharedPreferences preferences, GBDevice gbDevice) {
|
||||
super(preferences);
|
||||
@@ -115,4 +115,8 @@ public class DevicePrefs extends Prefs {
|
||||
return getInt(DeviceSettingsPreferenceConst.PREF_RESERVE_REMINDERS_CALENDAR, 9);
|
||||
}
|
||||
|
||||
public boolean allowHighMtu() {
|
||||
return getBoolean(PREF_ALLOW_HIGH_MTU, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user