diff --git a/app/build.gradle b/app/build.gradle index b719e8799..df1437734 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "androidx.appcompat:appcompat:1.0.2" - implementation "androidx.preference:preference:1.0.0" + implementation "androidx.preference:preference:1.1.0-alpha05" implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.recyclerview:recyclerview:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0" diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java index e62dd0596..3cec793b3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java @@ -671,6 +671,7 @@ public static String packageNameToPebbleMsgSender(String packageName) { switch (deviceType) { case MIBAND: deviceSharedPrefsEdit.putBoolean("low_latency_fw_update", prefs.getBoolean("mi_low_latency_fw_update", true)); + deviceSharedPrefsEdit.putInt("device_time_offset_hours", prefs.getInt("mi_device_time_offset_hours", 0)); break; case AMAZFITCOR: displayItems = prefs.getStringSet("cor_display_items", null); @@ -709,6 +710,7 @@ public static String packageNameToPebbleMsgSender(String packageName) { editor.remove("disconnect_notification_start"); editor.remove("disconnect_notification_end"); editor.remove("mi_low_latency_fw_update"); + editor.remove("mi_device_time_offset_hours"); editor.remove("mi2_do_not_disturb"); editor.remove("mi2_do_not_disturb_start"); editor.remove("mi2_do_not_disturb_end"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java index a9f2a4b77..7e09a3648 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java @@ -1,9 +1,12 @@ package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings; import android.os.Bundle; +import android.text.InputType; +import android.widget.EditText; import androidx.annotation.NonNull; import androidx.fragment.app.DialogFragment; +import androidx.preference.EditTextPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; @@ -269,6 +272,16 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat { addPreferenceHandlerFor(PREF_SWIPE_UNLOCK); addPreferenceHandlerFor(PREF_MI2_DATEFORMAT); addPreferenceHandlerFor(HuamiConst.PREF_DISPLAY_ITEMS); + + EditTextPreference pref = findPreference(MiBandConst.PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS); + if (pref != null) { + pref.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() { + @Override + public void onBindEditText(@NonNull EditText editText) { + editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); + } + }); + } } static DeviceSpecificSettingsFragment newInstance(String settingsFileSuffix, @NonNull int[] supportedSettings) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java index 79e02d16e..0fc7133a2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java @@ -39,7 +39,7 @@ public final class MiBandConst { public static final String PREF_MIBAND_BUTTON_ACTION_DELAY = "mi_button_press_count_match_delay"; public static final String PREF_MIBAND_BUTTON_PRESS_BROADCAST = "mi_button_press_broadcast"; public static final String PREF_MIBAND_USE_HR_FOR_SLEEP_DETECTION = "mi_hr_sleep_detection"; - public static final String PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS = "mi_device_time_offset_hours"; + public static final String PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS = "device_time_offset_hours"; public static final String PREF_MI2_DATEFORMAT = "mi2_dateformat"; public static final String PREF_MI2_GOAL_NOTIFICATION = "mi2_goal_notification"; public static final String PREF_MI2_DISPLAY_ITEM_CLOCK = "clock"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java index 803eff9d8..fd8154294 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java @@ -22,6 +22,7 @@ import android.app.Activity; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanFilter; import android.content.Context; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Build; import android.os.ParcelUuid; @@ -236,8 +237,8 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator { return location; } - public static int getDeviceTimeOffsetHours() throws IllegalArgumentException { - Prefs prefs = GBApplication.getPrefs(); + public static int getDeviceTimeOffsetHours(String deviceAddress) throws IllegalArgumentException { + Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress)); return prefs.getInt(MiBandConst.PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS, 0); } @@ -260,7 +261,8 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator { @Override public int[] getSupportedDeviceSpecificSettings(GBDevice device) { return new int[]{ - R.xml.devicesettings_lowlatency_fwupdate + R.xml.devicesettings_lowlatency_fwupdate, + R.xml.devicesettings_fake_timeoffset }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandDateConverter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandDateConverter.java index 9b9802ccc..3283c6531 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandDateConverter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandDateConverter.java @@ -34,9 +34,9 @@ public class MiBandDateConverter { * @param value * @return */ - public static GregorianCalendar rawBytesToCalendar(byte[] value) { + public static GregorianCalendar rawBytesToCalendar(byte[] value, String deviceAddress) { if (value.length == 6) { - return rawBytesToCalendar(value, 0); + return rawBytesToCalendar(value, 0, deviceAddress); } return createCalendar(); } @@ -47,7 +47,7 @@ public class MiBandDateConverter { * @param value * @return */ - public static GregorianCalendar rawBytesToCalendar(byte[] value, int offset) { + public static GregorianCalendar rawBytesToCalendar(byte[] value, int offset, String deviceAddress) { if (value.length - offset >= 6) { GregorianCalendar timestamp = new GregorianCalendar( value[offset] + 2000, @@ -57,7 +57,7 @@ public class MiBandDateConverter { value[offset + 4], value[offset + 5]); - int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(); + int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(deviceAddress); if(offsetInHours != 0) timestamp.add(Calendar.HOUR_OF_DAY,-offsetInHours); @@ -73,7 +73,7 @@ public class MiBandDateConverter { * @param timestamp * @return */ - public static byte[] calendarToRawBytes(Calendar timestamp) { + public static byte[] calendarToRawBytes(Calendar timestamp, String deviceAddress) { // The mi-band device currently records sleep // only if it happens after 10pm and before 7am. @@ -82,7 +82,7 @@ public class MiBandDateConverter { // If you usually sleep, say, from 6am to 2pm, set the // shift to -8, so at 6am the device thinks it's still 10pm // of the day before. - int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(); + int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(deviceAddress); if(offsetInHours != 0) timestamp.add(Calendar.HOUR_OF_DAY,offsetInHours); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BLETypeConversions.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BLETypeConversions.java index fdc77d61f..4c8bb8d77 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BLETypeConversions.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BLETypeConversions.java @@ -40,22 +40,7 @@ public class BLETypeConversions { * @return * @see GattCharacteristic#UUID_CHARACTERISTIC_CURRENT_TIME */ - public static byte[] calendarToRawBytes(Calendar timestamp, boolean honorDeviceTimeOffset) { - - // The mi-band device currently records sleep - // only if it happens after 10pm and before 7am. - // The offset is used to trick the device to record sleep - // in non-standard hours. - // If you usually sleep, say, from 6am to 2pm, set the - // shift to -8, so at 6am the device thinks it's still 10pm - // of the day before. - if (honorDeviceTimeOffset) { - int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(); - if (offsetInHours != 0) { - timestamp.add(Calendar.HOUR_OF_DAY, offsetInHours); - } - } - + public static byte[] calendarToRawBytes(Calendar timestamp) { // MiBand2: // year,year,month,dayofmonth,hour,minute,second,dayofweek,0,0,tz @@ -78,25 +63,9 @@ public class BLETypeConversions { /** * Similar to calendarToRawBytes, but only up to (and including) the MINUTES. * @param timestamp - * @param honorDeviceTimeOffset * @return */ - public static byte[] shortCalendarToRawBytes(Calendar timestamp, boolean honorDeviceTimeOffset) { - - // The mi-band device currently records sleep - // only if it happens after 10pm and before 7am. - // The offset is used to trick the device to record sleep - // in non-standard hours. - // If you usually sleep, say, from 6am to 2pm, set the - // shift to -8, so at 6am the device thinks it's still 10pm - // of the day before. - if (honorDeviceTimeOffset) { - int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(); - if (offsetInHours != 0) { - timestamp.add(Calendar.HOUR_OF_DAY, offsetInHours); - } - } - + public static byte[] shortCalendarToRawBytes(Calendar timestamp) { // MiBand2: // year,year,month,dayofmonth,hour,minute @@ -136,7 +105,7 @@ public class BLETypeConversions { * @param value * @return */ - public static GregorianCalendar rawBytesToCalendar(byte[] value, boolean honorDeviceTimeOffset) { + public static GregorianCalendar rawBytesToCalendar(byte[] value) { if (value.length >= 7) { int year = toUint16(value[0], value[1]); GregorianCalendar timestamp = new GregorianCalendar( @@ -153,14 +122,6 @@ public class BLETypeConversions { timeZone.setRawOffset(value[7] * 15 * 60 * 1000); timestamp.setTimeZone(timeZone); } - - if (honorDeviceTimeOffset) { - int offsetInHours = MiBandCoordinator.getDeviceTimeOffsetHours(); - if (offsetInHours != 0) { - timestamp.add(Calendar.HOUR_OF_DAY,-offsetInHours); - } - } - return timestamp; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiBatteryInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiBatteryInfo.java index 9bd15396d..21a8f0e42 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiBatteryInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiBatteryInfo.java @@ -95,7 +95,7 @@ public class HuamiBatteryInfo extends AbstractInfo { if (mData.length >= 18) { lastCharge = BLETypeConversions.rawBytesToCalendar(new byte[]{ mData[10], mData[11], mData[12], mData[13], mData[14], mData[15], mData[16], mData[17] - }, true); + }); } return lastCharge; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index e7b548a27..26505a914 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -237,9 +237,9 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { public byte[] getTimeBytes(Calendar calendar, TimeUnit precision) { byte[] bytes; if (precision == TimeUnit.MINUTES) { - bytes = BLETypeConversions.shortCalendarToRawBytes(calendar, true); + bytes = BLETypeConversions.shortCalendarToRawBytes(calendar); } else if (precision == TimeUnit.SECONDS) { - bytes = BLETypeConversions.calendarToRawBytes(calendar, true); + bytes = BLETypeConversions.calendarToRawBytes(calendar); } else { throw new IllegalArgumentException("Unsupported precision, only MINUTES and SECONDS are supported till now"); } @@ -251,7 +251,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { } public Calendar fromTimeBytes(byte[] bytes) { - GregorianCalendar timestamp = BLETypeConversions.rawBytesToCalendar(bytes, true); + GregorianCalendar timestamp = BLETypeConversions.rawBytesToCalendar(bytes); return timestamp; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/BatteryInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/BatteryInfo.java index 20ed2ed9a..66910462e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/BatteryInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/BatteryInfo.java @@ -59,13 +59,14 @@ public class BatteryInfo extends AbstractInfo { return BatteryState.UNKNOWN; } - public GregorianCalendar getLastChargeTime() { + public GregorianCalendar getLastChargeTime(String deviceAddress) { GregorianCalendar lastCharge = MiBandDateConverter.createCalendar(); if (mData.length >= 10) { lastCharge = MiBandDateConverter.rawBytesToCalendar(new byte[]{ - mData[1], mData[2], mData[3], mData[4], mData[5], mData[6] - }); + mData[1], mData[2], mData[3], mData[4], mData[5], mData[6]}, + deviceAddress + ); } return lastCharge; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java index 17d5c59c1..72dcffb8d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java @@ -625,7 +625,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { Calendar now = GregorianCalendar.getInstance(); Date date = now.getTime(); LOG.info("Sending current time to Mi Band: " + DateTimeUtils.formatDate(date) + " (" + date.toGMTString() + ")"); - byte[] nowBytes = MiBandDateConverter.calendarToRawBytes(now); + byte[] nowBytes = MiBandDateConverter.calendarToRawBytes(now, gbDevice.getAddress()); byte[] time = new byte[]{ nowBytes[0], nowBytes[1], @@ -943,7 +943,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { public void logDate(byte[] value, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { - GregorianCalendar calendar = MiBandDateConverter.rawBytesToCalendar(value); + GregorianCalendar calendar = MiBandDateConverter.rawBytesToCalendar(value, gbDevice.getAddress()); LOG.info("Got Mi Band Date: " + DateTimeUtils.formatDateTime(calendar.getTime())); } else { logMessageContent(value); @@ -1134,7 +1134,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { * @param characteristic */ private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) { - byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(AlarmUtils.toCalendar(alarm)); + byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(AlarmUtils.toCalendar(alarm), gbDevice.getAddress()); byte[] alarmMessage = new byte[]{ MiBandService.COMMAND_SET_TIMER, @@ -1172,7 +1172,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { BatteryInfo info = new BatteryInfo(value); batteryCmd.level = ((short) info.getLevelInPercent()); batteryCmd.state = info.getState(); - batteryCmd.lastChargeTime = info.getLastChargeTime(); + batteryCmd.lastChargeTime = info.getLastChargeTime(gbDevice.getAddress()); batteryCmd.numCharges = info.getNumCharges(); handleGBDeviceEvent(batteryCmd); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/FetchActivityOperation.java index 391d129a3..0c275a476 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/FetchActivityOperation.java @@ -254,7 +254,7 @@ public class FetchActivityOperation extends AbstractMiBand1Operation { // byte 0 is the data type: 1 means that each minute is represented by a triplet of bytes int dataType = value[0]; // byte 1 to 6 represent a timestamp - GregorianCalendar timestamp = MiBandDateConverter.rawBytesToCalendar(value, 1); + GregorianCalendar timestamp = MiBandDateConverter.rawBytesToCalendar(value, 1, getDevice().getAddress()); // counter of all data held by the band int totalDataToRead = (value[7] & 0xff) | ((value[8] & 0xff) << 8); @@ -405,7 +405,7 @@ public class FetchActivityOperation extends AbstractMiBand1Operation { * @param bytesTransferred */ private void sendAckDataTransfer(Calendar time, int bytesTransferred) { - byte[] ackTime = MiBandDateConverter.calendarToRawBytes(time); + byte[] ackTime = MiBandDateConverter.calendarToRawBytes(time, getDevice().getAddress()); Prefs prefs = GBApplication.getPrefs(); byte[] ackChecksum = new byte[]{ diff --git a/app/src/main/res/xml/devicesettings_fake_timeoffset.xml b/app/src/main/res/xml/devicesettings_fake_timeoffset.xml new file mode 100644 index 000000000..319f146f8 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_fake_timeoffset.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/miband_preferences.xml b/app/src/main/res/xml/miband_preferences.xml index 7eac6d9fa..453ad30af 100644 --- a/app/src/main/res/xml/miband_preferences.xml +++ b/app/src/main/res/xml/miband_preferences.xml @@ -106,13 +106,6 @@ android:summary="%s" android:title="@string/prefs_title_heartrate_measurement_interval" /> - - diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/BLETypeConversionsTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/BLETypeConversionsTest.java index 70c39e352..d6e92b700 100644 --- a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/BLETypeConversionsTest.java +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/BLETypeConversionsTest.java @@ -17,8 +17,8 @@ public class BLETypeConversionsTest extends TestBase { byte[] received = new byte[] { (byte) 0xe1, 0x07, 0x0a, 0x1c, 0x17, 0x1c, 0x00, 0x04 }; - GregorianCalendar calRequested = BLETypeConversions.rawBytesToCalendar(requested, false); - GregorianCalendar calReceived = BLETypeConversions.rawBytesToCalendar(received, false); + GregorianCalendar calRequested = BLETypeConversions.rawBytesToCalendar(requested); + GregorianCalendar calReceived = BLETypeConversions.rawBytesToCalendar(received); assertTrue(calRequested.getTime().equals(calReceived.getTime())); } @@ -31,8 +31,8 @@ public class BLETypeConversionsTest extends TestBase { byte[] received = new byte[] { (byte) 0xe1,0x07,0x0a,0x09,0x10,0x23,0x00,0x04 }; - GregorianCalendar calRequested = BLETypeConversions.rawBytesToCalendar(requested, false); - GregorianCalendar calReceived = BLETypeConversions.rawBytesToCalendar(received, false); + GregorianCalendar calRequested = BLETypeConversions.rawBytesToCalendar(requested); + GregorianCalendar calReceived = BLETypeConversions.rawBytesToCalendar(received); assertTrue(calRequested.getTime().equals(calReceived.getTime())); }