mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-06-05 21:49:48 +02:00
Ultrahuman optimizations
- fetch only new records instead of all records while the device is connected - added PREF_POWER_SAVING support (disables / enables SpO2 sensing) - added HRV visualization - unified and secured Intent handling - added BATTERY_CHARGING_FULL support - honour PREF_TIME_SYNC in onSetTime - various clean-ups
This commit is contained in:
@@ -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);
|
||||
|
@@ -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 <https://www.gnu.org/licenses/>. */
|
||||
|
||||
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<GenericHrvSummarySample> {
|
||||
public GenericHrvSummarySampleProvider(final GBDevice device, final DaoSession session) {
|
||||
super(device, session);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AbstractDao<GenericHrvSummarySample, ?> 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();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
})
|
||||
|
@@ -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<AbstractDao<?, ?>, Property> daoMap = new HashMap<AbstractDao<?, ?>, Property>() {{
|
||||
final Map<AbstractDao<?, ?>, 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
|
||||
|
@@ -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<UltrahumanDeviceSupport> 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");
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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,8 +517,22 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
} else {
|
||||
GB.toast(getContext(), R.string.devicestatus_disconnected, Toast.LENGTH_LONG, GB.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -511,6 +543,7 @@ public class UltrahumanDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
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));
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
@@ -1189,7 +1189,7 @@
|
||||
<string name="persian">Persian</string>
|
||||
<string name="scandinavian">Scandinavian</string>
|
||||
<string name="serbian">Serbian</string>
|
||||
<string name="ukranian">Ukranian</string>
|
||||
<string name="ukranian">Ukrainian</string>
|
||||
<string name="armenian">Armenian</string>
|
||||
<string name="italian">Italian</string>
|
||||
<string name="french">French</string>
|
||||
@@ -3875,10 +3875,11 @@
|
||||
<string name="ultrahuman_airplane_mode_activated">airplane mode activated</string>
|
||||
<string name="ultrahuman_airplane_mode_on_charger">ring is charging - airplane mode NOT activated</string>
|
||||
<string name="ultrahuman_airplane_mode_too_full">ring is fully charged - airplane mode NOT activated</string>
|
||||
<string name="ultrahuman_airplane_mode_unknown">unknown error - airplane mode NOT activated</string>
|
||||
<string name="ultrahuman_airplane_mode_unknown">unknown error %#02x - airplane mode NOT activated</string>
|
||||
<string name="ultrahuman_airplane_mode_question">Activate airplane mode?</string>
|
||||
<string name="ultrahuman_airplane_mode_title">airplane mode</string>
|
||||
<string name="ultrahuman_unhandled_error_response">received unhandled response code 0x%x for operation 0x%x</string>
|
||||
<string name="ultrahuman_unhandled_error_response">unhandled response %2$#02x %3$#02x for operation %1$#02x</string>
|
||||
<string name="ultrahuman_unhandled_operation_response">unhandled operation response %s</string>
|
||||
<string name="huawei_stress_test_enable">Automatic stress test</string>
|
||||
<string name="huawei_stress_test_enable_summary">Enable or disable automatic stress test</string>
|
||||
<string name="huawei_stress_no_calibration_data">No initial data - calibrate first</string>
|
||||
|
Reference in New Issue
Block a user