diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
index 5afc7f185..1c3e4a87a 100644
--- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
+++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
@@ -56,7 +56,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
- final Schema schema = new Schema(101, MAIN_PACKAGE + ".entities");
+ final Schema schema = new Schema(102, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@@ -193,6 +193,7 @@ public class GBDaoGenerator {
addGenericHeartRateSample(schema, user, device);
addGenericSpo2Sample(schema, user, device);
addGenericStressSample(schema, user, device);
+ addGenericHrvSummarySample(schema, user, device);
addGenericHrvValueSample(schema, user, device);
addGenericTemperatureSample(schema, user, device);
@@ -1773,6 +1774,19 @@ public class GBDaoGenerator {
return heartRateSample;
}
+ private static Entity addGenericHrvSummarySample(Schema schema, Entity user, Entity device) {
+ Entity hrvSummarySample = addEntity(schema, "GenericHrvSummarySample");
+ addCommonTimeSampleProperties("AbstractHrvSummarySample", hrvSummarySample, user, device);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_WEEKLY_AVERAGE).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_LAST_NIGHT_AVERAGE).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_LAST_NIGHT_5MIN_HIGH).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_BASELINE_LOW_UPPER).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_BASELINE_BALANCED_LOWER).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_BASELINE_BALANCED_UPPER).codeBeforeGetter(OVERRIDE);
+ hrvSummarySample.addIntProperty(SAMPLE_HRV_STATUS_NUM).codeBeforeGetter(OVERRIDE);
+ return hrvSummarySample;
+ }
+
private static Entity addGenericHrvValueSample(Schema schema, Entity user, Entity device) {
Entity hrvValueSample = addEntity(schema, "GenericHrvValueSample");
addCommonTimeSampleProperties("AbstractHrvValueSample", hrvValueSample, user, device);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/GenericHrvSummarySampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/GenericHrvSummarySampleProvider.java
new file mode 100644
index 000000000..adbf8c61d
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/GenericHrvSummarySampleProvider.java
@@ -0,0 +1,56 @@
+/* Copyright (C) 2025 Thomas Kuehne
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+
+package nodomain.freeyourgadget.gadgetbridge.devices;
+
+import androidx.annotation.NonNull;
+
+import de.greenrobot.dao.AbstractDao;
+import de.greenrobot.dao.Property;
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericHrvSummarySample;
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericHrvSummarySampleDao;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class GenericHrvSummarySampleProvider extends AbstractTimeSampleProvider {
+ public GenericHrvSummarySampleProvider(final GBDevice device, final DaoSession session) {
+ super(device, session);
+ }
+
+ @NonNull
+ @Override
+ public AbstractDao getSampleDao() {
+ return getSession().getGenericHrvSummarySampleDao();
+ }
+
+ @NonNull
+ @Override
+ protected Property getTimestampSampleProperty() {
+ return GenericHrvSummarySampleDao.Properties.Timestamp;
+ }
+
+ @NonNull
+ @Override
+ protected Property getDeviceIdentifierSampleProperty() {
+ return GenericHrvSummarySampleDao.Properties.DeviceId;
+ }
+
+ @Override
+ public GenericHrvSummarySample createSample() {
+ return new GenericHrvSummarySample();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanConstants.java
index 7083d1d76..42d9da02d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanConstants.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanConstants.java
@@ -36,4 +36,6 @@ public class UltrahumanConstants {
public static final byte OPERATION_PING = 0x59;
public static final byte OPERATION_ACTIVATE_AIRPLANE_MODE = 0x70;
public static final byte OPERATION_RESET = (byte) 0x98;
+ public static final byte OPERATION_DISABLE_POWERSAVE = (byte) 0xD1;
+ public static final byte OPERATION_ENABLE_POWERSAVE = (byte) 0xD2;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCardAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCardAction.java
index cb1e15968..3fadbfd22 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCardAction.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCardAction.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCardAction;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@@ -58,6 +59,7 @@ public class UltrahumanDeviceCardAction implements DeviceCardAction {
.setIcon(Icon)
.setPositiveButton(android.R.string.yes, (dialog, whichButton) -> {
final Intent intent = new Intent(Action);
+ intent.setPackage(BuildConfig.APPLICATION_ID);
intent.putExtra(GBDevice.EXTRA_DEVICE, device);
context.sendBroadcast(intent);
})
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCoordinator.java
index 5a2fbfe4c..4c0f1b60b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/ultrahuman/UltrahumanDeviceCoordinator.java
@@ -32,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCardAction;
import nodomain.freeyourgadget.gadgetbridge.devices.GenericHeartRateSampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.devices.GenericHrvSummarySampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.GenericHrvValueSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.GenericSpo2SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.GenericStressSampleProvider;
@@ -51,6 +52,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.UltrahumanDeviceStateSample
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.HeartRateSample;
+import nodomain.freeyourgadget.gadgetbridge.model.HrvSummarySample;
import nodomain.freeyourgadget.gadgetbridge.model.HrvValueSample;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
@@ -71,7 +73,7 @@ public class UltrahumanDeviceCoordinator extends AbstractBLEDeviceCoordinator {
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
final Long deviceId = device.getId();
- final Map, Property> daoMap = new HashMap, Property>() {{
+ final Map, Property> daoMap = new HashMap<>() {{
put(session.getGenericHeartRateSampleDao(), GenericHeartRateSampleDao.Properties.DeviceId);
put(session.getGenericHrvValueSampleDao(), GenericHrvValueSampleDao.Properties.DeviceId);
put(session.getGenericSpo2SampleDao(), GenericSpo2SampleDao.Properties.DeviceId);
@@ -114,6 +116,11 @@ public class UltrahumanDeviceCoordinator extends AbstractBLEDeviceCoordinator {
return "Ultrahuman Healthcare Pvt Ltd";
}
+ @Override
+ public TimeSampleProvider extends HrvSummarySample> getHrvSummarySampleProvider(GBDevice device, DaoSession session) {
+ return new GenericHrvSummarySampleProvider(device, session);
+ }
+
@Override
public TimeSampleProvider extends HrvValueSample> getHrvValueSampleProvider(GBDevice device, DaoSession session) {
return new GenericHrvValueSampleProvider(device, session);
@@ -147,7 +154,8 @@ public class UltrahumanDeviceCoordinator extends AbstractBLEDeviceCoordinator {
@Override
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[]{
- R.xml.devicesettings_time_sync
+ R.xml.devicesettings_time_sync,
+ R.xml.devicesettings_power_saving
};
}
@@ -183,8 +191,7 @@ public class UltrahumanDeviceCoordinator extends AbstractBLEDeviceCoordinator {
@Override
public boolean supportsHrvMeasurement(final GBDevice device) {
- // TODO - needs getHrvSummarySampleProvider in addition to the implemented getHrvValueSampleProvider
- return false;
+ return true;
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/ultrahuman/UltrahumanDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/ultrahuman/UltrahumanDeviceSupport.java
index 0ab006692..724c0cd7e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/ultrahuman/UltrahumanDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/ultrahuman/UltrahumanDeviceSupport.java
@@ -30,6 +30,7 @@ import androidx.core.content.ContextCompat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Locale;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@@ -57,7 +58,6 @@ import nodomain.freeyourgadget.gadgetbridge.entities.UltrahumanActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.UltrahumanDeviceStateSample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
-import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
@@ -71,30 +71,30 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(UltrahumanDeviceSupport.class);
- private BroadcastReceiver CommandReceiver;
+ private final UltrahumanBroadcastReceiver CommandReceiver;
private int FetchTo;
private int FetchFrom;
private int FetchCurrent;
- public UltrahumanDeviceSupport(DeviceType type) {
+ public UltrahumanDeviceSupport() {
super(LOG);
addSupportedService(UltrahumanConstants.UUID_SERVICE_COMMAND);
addSupportedService(UltrahumanConstants.UUID_SERVICE_STATE);
addSupportedService(GattService.UUID_SERVICE_DEVICE_INFORMATION);
+ CommandReceiver = new UltrahumanBroadcastReceiver();
+
DeviceInfoProfile deviceProfile = new DeviceInfoProfile<>(this);
- deviceProfile.addListener(new UltrahumanIntentListener());
+ deviceProfile.addListener(CommandReceiver);
addSupportedProfile(deviceProfile);
}
@Override
public void dispose() {
- BroadcastReceiver receiver = CommandReceiver;
- CommandReceiver = null;
-
- if (receiver != null) {
- getContext().unregisterReceiver(receiver);
+ if (CommandReceiver.Registered) {
+ CommandReceiver.Registered = false;
+ getContext().unregisterReceiver(CommandReceiver);
}
super.dispose();
@@ -115,11 +115,11 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
- if (CommandReceiver == null) {
- CommandReceiver = new UltrahumanBroadcastReceiver();
+ if (!CommandReceiver.Registered) {
IntentFilter filter = new IntentFilter();
filter.addAction(UltrahumanConstants.ACTION_AIRPLANE_MODE);
ContextCompat.registerReceiver(getContext(), CommandReceiver, filter, ContextCompat.RECEIVER_EXPORTED);
+ CommandReceiver.Registered = true;
}
// trying to read non-existing characteristics sometimes causes odd BLE failures
@@ -148,6 +148,9 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
builder.add(new UltrahumanSetTimeAction(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND)));
}
+ boolean powerSave = getDevicePrefs().getBoolean(DeviceSettingsPreferenceConst.PREF_POWER_SAVING, true);
+ builder.write(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND), new byte[]{powerSave ? UltrahumanConstants.OPERATION_ENABLE_POWERSAVE : UltrahumanConstants.OPERATION_DISABLE_POWERSAVE});
+
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
return builder;
@@ -162,12 +165,15 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
getDevice().setBusyTask(task);
getDevice().sendDeviceUpdateIntent(getContext());
- FetchFrom = -1;
+ // fetch deltas while the device is connected
+ FetchFrom = (FetchCurrent > 0 && FetchCurrent < Short.MAX_VALUE - 1000) ? FetchCurrent : -1;
FetchTo = -1;
FetchCurrent = -1;
TransactionBuilder builder = new TransactionBuilder("onFetchRecordedData");
- builder.write(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND), new byte[]{UltrahumanConstants.OPERATION_GET_FIRST_RECORDING_NR});
+ if (FetchFrom <= 0) {
+ builder.write(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND), new byte[]{UltrahumanConstants.OPERATION_GET_FIRST_RECORDING_NR});
+ }
builder.write(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND), new byte[]{UltrahumanConstants.OPERATION_GET_LAST_RECORDING_NR});
if (isConnected()) {
@@ -209,19 +215,20 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
return false;
}
- byte op = raw[0];
- byte success = raw[1];
- byte result = raw[2];
+ final byte op = raw[0];
+ final byte success = raw[1];
+ final byte result = raw[2];
// ignore checksums for now - algorithm is unknown
//byte chk1 = raw[raw.length-1];
//byte chk2 = raw[raw.length-2];
+ final String info = String.format(Locale.US, "received BLE command response op=%02x, success=%02x, result=%02x : %s", op, success, result, StringUtils.bytesToHex(raw));
if (success == 0x00) {
- LOG.debug("received BLE command response op={}, success={}, result={} : {}", op, success, result, StringUtils.bytesToHex(raw));
+ LOG.debug(info);
} else if ((0xFF & success) == 0xFF) {
- LOG.warn("received BLE command response op={}, success={}, result={} : {}", op, success, result, StringUtils.bytesToHex(raw));
+ LOG.warn(info);
} else {
- LOG.info("received BLE command response op={}, success={}, result={} : {}", op, success, result, StringUtils.bytesToHex(raw));
+ LOG.info(info);
}
Context context = getContext();
@@ -230,13 +237,12 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
case UltrahumanConstants.OPERATION_GET_RECORDINGS:
return decodeRecordings(raw);
case UltrahumanConstants.OPERATION_PING:
- if (raw[1] != 0x00) {
- String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[1], raw[0]);
- GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
+ if (success == 0x00) {
+ return true;
}
- return true;
+ break;
case UltrahumanConstants.OPERATION_ACTIVATE_AIRPLANE_MODE:
- switch (raw[2]) {
+ switch (result) {
case 0x01:
GB.toast(context, context.getString(R.string.ultrahuman_airplane_mode_activated), Toast.LENGTH_LONG, GB.INFO);
return true;
@@ -247,54 +253,66 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
GB.toast(context, context.getString(R.string.ultrahuman_airplane_mode_too_full), Toast.LENGTH_LONG, GB.ERROR);
return true;
}
- LOG.warn("set airplane mode - unknown error: {} ", StringUtils.bytesToHex(raw));
- GB.toast(context, context.getString(R.string.ultrahuman_airplane_mode_unknown), Toast.LENGTH_LONG, GB.ERROR);
+
+ String airplaneMessage = getContext().getString(R.string.ultrahuman_airplane_mode_unknown, result);
+ GB.toast(context, airplaneMessage, Toast.LENGTH_LONG, GB.ERROR);
return false;
case UltrahumanConstants.OPERATION_GET_FIRST_RECORDING_NR:
- if (raw[1] == 0x00 || raw[2] == 0x01) {
+ if (success == 0x00 && result == 0x01) {
FetchFrom = BLETypeConversions.toUint16(raw, 3);
if (FetchTo != -1) {
fetchRecordingActually();
}
return true;
- } else {
- String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[1], raw[0]);
- GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
- fetchRecordedDataFinished();
}
- return false;
+ fetchRecordedDataFinished();
+ break;
case UltrahumanConstants.OPERATION_GET_LAST_RECORDING_NR:
- if (raw[1] == 0x00 && raw[2] == 0x01) {
+ if (success == 0x00 && result == 0x01) {
FetchTo = BLETypeConversions.toUint16(raw, 3);
if (FetchFrom != -1) {
fetchRecordingActually();
}
return true;
- } else {
- String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[1], raw[0]);
- GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
- fetchRecordedDataFinished();
}
- return false;
+ fetchRecordedDataFinished();
+ break;
+ case UltrahumanConstants.OPERATION_DISABLE_POWERSAVE:
+ case UltrahumanConstants.OPERATION_ENABLE_POWERSAVE:
case UltrahumanConstants.OPERATION_SETTIME:
- if (raw[1] != 0x00 || raw[2] != 0x01) {
- String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[1], raw[0]);
- GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
+ if (success == 0x00 && result == 0x01) {
+ return true;
}
- return true;
+ break;
+
default:
- LOG.error("unhandled BLE command response: {} ", StringUtils.bytesToHex(raw));
+ String message = getContext().getString(R.string.ultrahuman_unhandled_operation_response, StringUtils.bytesToHex(raw));
+ GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
return false;
}
+
+ String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, op, success, result);
+ GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
+ return false;
}
LOG.error("unhandled characteristics {} - {} ", characteristicUUID, StringUtils.bytesToHex(raw));
return false;
}
+ @Override
+ public void onSendConfiguration(String config) {
+ if (DeviceSettingsPreferenceConst.PREF_TIME_SYNC.equals(config)) {
+ onSetTime();
+ } else if (DeviceSettingsPreferenceConst.PREF_POWER_SAVING.equals(config)) {
+ onSetPowerSaveMode();
+ } else {
+ super.onSendConfiguration(config);
+ }
+ }
@Override
public boolean useAutoConnect() {
@@ -310,7 +328,7 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
if ((raw[1] & 0xFF) == 0xEE) {
LOG.warn("no historic data recorded");
} else {
- String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[1], raw[0]);
+ String message = getContext().getString(R.string.ultrahuman_unhandled_error_response, raw[0], raw[1], raw[2]);
GB.toast(getContext(), message, Toast.LENGTH_LONG, GB.ERROR);
}
fetchRecordedDataFinished();
@@ -439,7 +457,7 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
batteryState = BatteryState.BATTERY_NORMAL;
break;
case 0x03:
- batteryState = BatteryState.BATTERY_CHARGING;
+ batteryState = (batteryLevel > 99) ? BatteryState.BATTERY_CHARGING_FULL : BatteryState.BATTERY_CHARGING;
break;
default:
LOG.warn("DeviceState contains unhandled device state {}: {}", raw[5], StringUtils.bytesToHex(raw));
@@ -488,8 +506,8 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
GB.signalActivityDataFinish(getDevice());
}
- public void activateAirplaneMode() {
- sendCommand("ActivateAirplaneMode", new byte[]{UltrahumanConstants.OPERATION_ACTIVATE_AIRPLANE_MODE});
+ private void activateAirplaneMode() {
+ sendCommand("activateAirplaneMode", new byte[]{UltrahumanConstants.OPERATION_ACTIVATE_AIRPLANE_MODE});
}
@Override
@@ -499,11 +517,10 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
- @Override
- public void onSetTime() {
- TransactionBuilder builder = new TransactionBuilder("onSetTime");
- UltrahumanSetTimeAction action = new UltrahumanSetTimeAction(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND));
- builder.add(action);
+ private void onSetPowerSaveMode() {
+ boolean powerSave = getDevicePrefs().getBoolean(DeviceSettingsPreferenceConst.PREF_POWER_SAVING, true);
+ TransactionBuilder builder = new TransactionBuilder("onSetPowerSaveMode");
+ builder.write(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND), new byte[]{powerSave ? UltrahumanConstants.OPERATION_ENABLE_POWERSAVE : UltrahumanConstants.OPERATION_DISABLE_POWERSAVE});
if (isConnected()) {
builder.queue(getQueue());
@@ -512,6 +529,22 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
+ @Override
+ public void onSetTime() {
+ boolean timeSync = getDevicePrefs().getBoolean(DeviceSettingsPreferenceConst.PREF_TIME_SYNC, true);
+ if (timeSync) {
+ TransactionBuilder builder = new TransactionBuilder("onSetTime");
+ UltrahumanSetTimeAction action = new UltrahumanSetTimeAction(getCharacteristic(UltrahumanConstants.UUID_CHARACTERISTIC_COMMAND));
+ builder.add(action);
+
+ if (isConnected()) {
+ builder.queue(getQueue());
+ } else {
+ GB.toast(getContext(), R.string.devicestatus_disconnected, Toast.LENGTH_LONG, GB.ERROR);
+ }
+ }
+ }
+
private void sendCommand(String taskName, byte[] contents) {
LOG.debug("sendCommand {} : {}", taskName, StringUtils.bytesToHex(contents));
TransactionBuilder builder = new TransactionBuilder(taskName);
@@ -524,9 +557,16 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
- private class UltrahumanBroadcastReceiver extends BroadcastReceiver {
+ private class UltrahumanBroadcastReceiver extends BroadcastReceiver implements IntentListener {
+ boolean Registered;
+
@Override
public void onReceive(Context context, Intent intent) {
+ notify(intent);
+ }
+
+ @Override
+ public void notify(Intent intent) {
final GBDevice device = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (device != null && !device.equals(getDevice())) {
// this intent is for another device
@@ -536,15 +576,7 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
String action = intent.getAction();
if (UltrahumanConstants.ACTION_AIRPLANE_MODE.equals(action)) {
activateAirplaneMode();
- }
- }
- }
-
- private class UltrahumanIntentListener implements IntentListener {
- @Override
- public void notify(Intent intent) {
- String action = intent.getAction();
- if (DeviceInfoProfile.ACTION_DEVICE_INFO.equals(action)) {
+ } else if (DeviceInfoProfile.ACTION_DEVICE_INFO.equals(action)) {
handleDeviceInfo(intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO));
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 18dc30aee..b3c11c411 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1189,7 +1189,7 @@
Persian
Scandinavian
Serbian
- Ukranian
+ Ukrainian
Armenian
Italian
French
@@ -3875,10 +3875,11 @@
airplane mode activated
ring is charging - airplane mode NOT activated
ring is fully charged - airplane mode NOT activated
- unknown error - airplane mode NOT activated
+ unknown error %#02x - airplane mode NOT activated
Activate airplane mode?
airplane mode
- received unhandled response code 0x%x for operation 0x%x
+ unhandled response %2$#02x %3$#02x for operation %1$#02x
+ unhandled operation response %s
Automatic stress test
Enable or disable automatic stress test
No initial data - calibrate first