mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 12:26:48 +01:00
adding FitPro bands support
This commit is contained in:
parent
b8855f16ee
commit
e00ee75ad2
@ -43,7 +43,7 @@ public class GBDaoGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Schema schema = new Schema(33, MAIN_PACKAGE + ".entities");
|
||||
Schema schema = new Schema(34, MAIN_PACKAGE + ".entities");
|
||||
|
||||
Entity userAttributes = addUserAttributes(schema);
|
||||
Entity user = addUserInfo(schema, userAttributes);
|
||||
@ -80,6 +80,7 @@ public class GBDaoGenerator {
|
||||
addSonySWR12Sample(schema, user, device);
|
||||
addBangleJSActivitySample(schema, user, device);
|
||||
addCasioGBX100Sample(schema, user, device);
|
||||
addFitProActivitySample(schema, user, device);
|
||||
|
||||
addHybridHRActivitySample(schema, user, device);
|
||||
addCalendarSyncState(schema, device);
|
||||
@ -614,4 +615,21 @@ public class GBDaoGenerator {
|
||||
batteryLevel.addIntProperty("level").notNull();
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
private static Entity addFitProActivitySample(Schema schema, Entity user, Entity device) {
|
||||
Entity activitySample = addEntity(schema, "FitProActivitySample");
|
||||
activitySample.implementsSerializable();
|
||||
addCommonActivitySampleProperties("AbstractFitProActivitySample", activitySample, user, device);
|
||||
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
|
||||
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
|
||||
addHeartRateProperties(activitySample);
|
||||
activitySample.addIntProperty("caloriesBurnt");
|
||||
activitySample.addIntProperty("distanceMeters");
|
||||
activitySample.addIntProperty("spo2Percent");
|
||||
activitySample.addIntProperty("pressureLowMmHg");
|
||||
activitySample.addIntProperty("pressureHighMmHg");
|
||||
activitySample.addIntProperty("activeTimeMinutes");
|
||||
return activitySample;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ vendor's servers.
|
||||
- Casio
|
||||
- [GB-5600B/GB-6900B/GB-X6900B](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Casio-GB-5600B%2FGB-6900B%2FGB-X6900B)
|
||||
- [GBX-100](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Casio-GBX-100)
|
||||
|
||||
- [FitPro](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/FitPro)
|
||||
- Fossil
|
||||
- [Hybrid HR](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Fossil-Hybrid-HR) [**\[!\]**](#special-pairing-procedures)
|
||||
- Q Hybrid
|
||||
@ -114,6 +116,7 @@ Please see [FEATURES.md](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/ma
|
||||
* Taavi Eomäe (iTag)
|
||||
* Erik Bloß (TLW64)
|
||||
* Yukai Li (Lefun)
|
||||
* Petr Vaněk (FitPro)
|
||||
|
||||
## Contribute
|
||||
|
||||
|
@ -46,6 +46,7 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivity {
|
||||
addPreferenceHandlerFor(PREF_USER_HEIGHT_CM);
|
||||
addPreferenceHandlerFor(PREF_USER_WEIGHT_KG);
|
||||
addPreferenceHandlerFor(PREF_USER_GENDER);
|
||||
addPreferenceHandlerFor(PREF_USER_STEPS_GOAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,6 +21,8 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_DATEFORMAT = "dateformat";
|
||||
public static final String PREF_TIMEFORMAT = "timeformat";
|
||||
public static final String PREF_WEARLOCATION = "wearlocation";
|
||||
public static final String PREF_VIBRATION_ENABLE = "vibration_enable";
|
||||
public static final String PREF_NOTIFICATION_ENABLE = "notification_enable";
|
||||
public static final String PREF_SCREEN_ORIENTATION = "screen_orientation";
|
||||
public static final String PREF_RESERVER_ALARMS_CALENDAR = "reserve_alarms_calendar";
|
||||
public static final String PREF_ALLOW_HIGH_MTU = "allow_high_mtu";
|
||||
@ -43,8 +45,25 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES = "save_raw_activity_files";
|
||||
public static final String PREF_HYBRID_HR_DANGEROUS_EXTERNAL_INTENTS = "dangerous_external_intents";
|
||||
|
||||
public static final String PREF_ACTIVATE_DISPLAY_ON_LIFT = "activate_display_on_lift_wrist";
|
||||
public static final String PREF_DISPLAY_ON_LIFT_START = "display_on_lift_start";
|
||||
public static final String PREF_DISPLAY_ON_LIFT_END = "display_on_lift_end";
|
||||
|
||||
public static final String PREF_SLEEP_TIME = "prefs_enable_sleep_time";
|
||||
public static final String PREF_SLEEP_TIME_START = "prefs_sleep_time_start";
|
||||
public static final String PREF_SLEEP_TIME_END = "prefs_sleep_time_end";
|
||||
|
||||
public static final String PREF_LIFTWRIST_NOSHED = "activate_display_on_lift_wrist_noshed";
|
||||
public static final String PREF_DISCONNECTNOTIF_NOSHED = "disconnect_notification_noshed";
|
||||
public static final String PREF_LONGSIT_START = "pref_longsit_start";
|
||||
public static final String PREF_LONGSIT_END = "pref_longsit_end";
|
||||
|
||||
public static final String PREF_AUTOHEARTRATE_SWITCH = "pref_autoheartrate_switch";
|
||||
public static final String PREF_AUTOHEARTRATE_SLEEP = "pref_autoheartrate_sleep";
|
||||
public static final String PREF_AUTOHEARTRATE_INTERVAL = "pref_autoheartrate_interval";
|
||||
public static final String PREF_AUTOHEARTRATE_START = "pref_autoheartrate_start";
|
||||
public static final String PREF_AUTOHEARTRATE_END = "pref_autoheartrate_end";
|
||||
|
||||
public static final String PREF_POWER_MODE = "power_mode";
|
||||
public static final String PREF_BUTTON_BP_CALIBRATE = "prefs_sensors_button_bp_calibration";
|
||||
public static final String PREF_ALTITUDE_CALIBRATE = "pref_sensors_altitude";
|
||||
@ -52,6 +71,9 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_LONGSIT_SWITCH = "pref_longsit_switch";
|
||||
public static final String PREF_LONGSIT_SWITCH_NOSHED = "screen_longsit_noshed";
|
||||
public static final String PREF_DO_NOT_DISTURB_NOAUTO = "do_not_disturb_no_auto";
|
||||
public static final String PREF_DO_NOT_DISTURB_NOAUTO_START = "do_not_disturb_no_auto_start";
|
||||
public static final String PREF_DO_NOT_DISTURB_NOAUTO_END = "do_not_disturb_no_auto_end";
|
||||
|
||||
public static final String PREF_FIND_PHONE_ENABLED = "prefs_find_phone";
|
||||
public static final String PREF_AUTOLIGHT = "autolight";
|
||||
public static final String PREF_AUTOREMOVE_MESSAGE = "autoremove_message";
|
||||
@ -74,4 +96,5 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_TRANSLITERATION_ENABLED = "pref_transliteration_enabled";
|
||||
|
||||
public static final String PREF_SOUNDS = "sounds";
|
||||
public static final String PREF_AUTH_KEY = "authkey";
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DISCONNECTNOTIF_NOSHED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FAKE_RING_DURATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FIND_PHONE_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DANGEROUS_EXTERNAL_INTENTS;
|
||||
@ -79,9 +81,20 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOHEARTRATE_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOHEARTRATE_SLEEP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOHEARTRATE_INTERVAL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOHEARTRATE_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOHEARTRATE_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_NOTIFICATION_ENABLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_OPERATING_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_POWER_MODE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_ORIENTATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SLEEP_TIME;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SLEEP_TIME_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SLEEP_TIME_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONYSWR12_LOW_VIBRATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONYSWR12_SMART_INTERVAL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONYSWR12_STAMINA;
|
||||
@ -90,6 +103,7 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TRANSLITERATION_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_VIBRATION_ENABLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_ACTIVATE_DISPLAY_ON_LIFT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_FELL_SLEEP_BROADCAST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_FELL_SLEEP_SELECTION;
|
||||
@ -372,6 +386,8 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat {
|
||||
addPreferenceHandlerFor(PREF_EXPOSE_HR_THIRDPARTY);
|
||||
addPreferenceHandlerFor(PREF_BT_CONNECTED_ADVERTISEMENT);
|
||||
addPreferenceHandlerFor(PREF_WEARLOCATION);
|
||||
addPreferenceHandlerFor(PREF_VIBRATION_ENABLE);
|
||||
addPreferenceHandlerFor(PREF_NOTIFICATION_ENABLE);
|
||||
addPreferenceHandlerFor(PREF_SCREEN_ORIENTATION);
|
||||
addPreferenceHandlerFor(PREF_TIMEFORMAT);
|
||||
addPreferenceHandlerFor(PREF_BUTTON_1_FUNCTION_SHORT);
|
||||
@ -391,7 +407,16 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat {
|
||||
addPreferenceHandlerFor(PREF_ALTITUDE_CALIBRATE);
|
||||
addPreferenceHandlerFor(PREF_LONGSIT_PERIOD);
|
||||
addPreferenceHandlerFor(PREF_LONGSIT_SWITCH);
|
||||
addPreferenceHandlerFor(PREF_LONGSIT_START);
|
||||
addPreferenceHandlerFor(PREF_LONGSIT_END);
|
||||
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_SWITCH);
|
||||
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_SLEEP);
|
||||
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_INTERVAL);
|
||||
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_START);
|
||||
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_END);
|
||||
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO);
|
||||
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO_START);
|
||||
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO_END);
|
||||
addPreferenceHandlerFor(PREF_FIND_PHONE_ENABLED);
|
||||
addPreferenceHandlerFor(PREF_AUTOLIGHT);
|
||||
addPreferenceHandlerFor(PREF_AUTOREMOVE_MESSAGE);
|
||||
@ -415,6 +440,81 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat {
|
||||
addPreferenceHandlerFor(PREF_SONYSWR12_LOW_VIBRATION);
|
||||
addPreferenceHandlerFor(PREF_SONYSWR12_SMART_INTERVAL);
|
||||
|
||||
String sleepTimeState = prefs.getString(PREF_SLEEP_TIME, PREF_DO_NOT_DISTURB_OFF);
|
||||
boolean sleepTimeScheduled = sleepTimeState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);
|
||||
|
||||
final Preference sleepTimeInfo = findPreference(PREF_SLEEP_TIME);
|
||||
if (sleepTimeInfo != null) {
|
||||
//sleepTimeInfo.setEnabled(!PREF_DO_NOT_DISTURB_OFF.equals(sleepTimeInfo));
|
||||
sleepTimeInfo.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||
invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GBApplication.deviceService().onSendConfiguration(PREF_SLEEP_TIME);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final Preference sleepTimeStart = findPreference(PREF_SLEEP_TIME_START);
|
||||
if (sleepTimeStart != null) {
|
||||
sleepTimeStart.setEnabled(sleepTimeScheduled);
|
||||
sleepTimeStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||
invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GBApplication.deviceService().onSendConfiguration(PREF_SLEEP_TIME_START);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final Preference sleepTimeEnd = findPreference(PREF_SLEEP_TIME_END);
|
||||
if (sleepTimeEnd != null) {
|
||||
sleepTimeEnd.setEnabled(sleepTimeScheduled);
|
||||
sleepTimeEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||
invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GBApplication.deviceService().onSendConfiguration(PREF_SLEEP_TIME_END);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final Preference sleepTime = findPreference(PREF_SLEEP_TIME);
|
||||
if (sleepTime != null) {
|
||||
sleepTime.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newVal) {
|
||||
final boolean scheduled = PREF_DO_NOT_DISTURB_SCHEDULED.equals(newVal.toString());
|
||||
Objects.requireNonNull(sleepTimeStart).setEnabled(scheduled);
|
||||
Objects.requireNonNull(sleepTimeEnd).setEnabled(scheduled);
|
||||
if (sleepTimeInfo != null) {
|
||||
//sleepTimeInfo.setEnabled(!PREF_DO_NOT_DISTURB_OFF.equals(newVal.toString()));
|
||||
}
|
||||
invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GBApplication.deviceService().onSendConfiguration(PREF_SLEEP_TIME);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
String displayOnLiftState = prefs.getString(PREF_ACTIVATE_DISPLAY_ON_LIFT, PREF_DO_NOT_DISTURB_OFF);
|
||||
boolean displayOnLiftScheduled = displayOnLiftState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);
|
||||
|
||||
|
@ -0,0 +1,250 @@
|
||||
/* Copyright (C) 2016-2020 Petr Vaněk
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.fitpro;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class FitProConstants {
|
||||
|
||||
// cd 00 2a 05 01 0c 00 0c 0000012d000000bb000018
|
||||
// | | | | | | | | |-- payload ->
|
||||
// | | | | | | | |----- payload length low
|
||||
// | | | | | | |-------- payload length high
|
||||
// | | | | | |----------- command
|
||||
// | | | | |-------------- delimiter/version
|
||||
// | | | |----------------- command group
|
||||
// | | |-------------------- full length low
|
||||
// | |----------------------- full length high
|
||||
// |-------------------------- header
|
||||
|
||||
public static final byte DATA_HEADER = (byte) 0xCD;
|
||||
public static final byte DATA_HEADER_ACK = (byte) 0xDC;
|
||||
|
||||
public static final byte[] DATA_TEMPLATE = {
|
||||
(byte) DATA_HEADER, // header
|
||||
(byte) 0x00, // delimiter or first byte of argument count?
|
||||
(byte) 0, // argument count, calculated
|
||||
(byte) 0, // command 1
|
||||
(byte) 0x1, // delimiter?
|
||||
(byte) 0, // command 2
|
||||
(byte) 0x0, // delimiter or first byte of data length?
|
||||
(byte) 0, // data length calculated
|
||||
// data payload
|
||||
};
|
||||
|
||||
public static final UUID UUID_CHARACTERISTIC_UART = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9d");
|
||||
public static final UUID UUID_CHARACTERISTIC_TX = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9d");
|
||||
public static final UUID UUID_CHARACTERISTIC_RX = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9d");
|
||||
//public static final UUID LT716_OTA = UUID.fromString("00010203-0405-0607-0809-0a0b0c0d1912"); //when in OTA mode
|
||||
|
||||
public static final byte CMD_GROUP_GENERAL = (byte) 0x12;
|
||||
public static final byte CMD_GROUP_BAND_INFO = (byte) 0x20;
|
||||
public static final byte CMD_GROUP_RECEIVE_BUTTON_DATA = 0x1c;
|
||||
public static final byte CMD_GROUP_RECEIVE_SPORTS_DATA = 0x15;
|
||||
public static final byte CMD_GROUP_HEARTRATE_SETTINGS = 0x16;
|
||||
public static final byte CMD_GROUP_REQUEST_DATA = 0x1a;
|
||||
public static final byte CMD_GROUP_BIND = 0x14;
|
||||
public static final byte CMD_GROUP_RESET = 0x1d;
|
||||
|
||||
//group general 0x12
|
||||
public static final byte CMD_FIND_BAND = (byte) 0x0b;
|
||||
public static final byte CMD_SET_DATE_TIME = (byte) 0x1;
|
||||
public static final byte CMD_SET_LANGUAGE = (byte) 0x15;
|
||||
public static final byte CMD_NOTIFICATION_MESSAGE = (byte) 0x12;
|
||||
public static final byte CMD_NOTIFICATION_CALL = (byte) 0x11;
|
||||
public static final byte CMD_WEATHER = (byte) 0x20;
|
||||
public static final byte CMD_CAMERA = (byte) 0xc;
|
||||
public static final byte CMD_HEART_RATE_MEASUREMENT = 0x18; //on/off
|
||||
public static final byte CMD_DND = (byte) 0x14;
|
||||
public static final byte CMD_INIT1 = 0xa;
|
||||
public static final byte CMD_INIT2 = 0xc;
|
||||
public static final byte CMD_INIT3 = (byte) 0xff;
|
||||
|
||||
public static final byte CMD_SET_SLEEP_TIMES = (byte) 0xF;
|
||||
public static final byte CMD_ALARM = (byte) 0x2;
|
||||
public static final byte CMD_SET_ARM = (byte) 0x6;
|
||||
public static final byte CMD_GET_HR = (byte) 0xd; //0/1
|
||||
public static final byte CMD_GET_PRESS = (byte) 0xe; //0/1
|
||||
|
||||
public static final byte CMD_NOTIFICATIONS_ENABLE = 0x7;
|
||||
public static final byte[] VALUE_SET_NOTIFICATIONS_ENABLE_ON = new byte[]{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
|
||||
public static final byte[] VALUE_SET_NOTIFICATIONS_ENABLE_OFF = new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
public static final byte CMD_SET_LONG_SIT_REMINDER = (byte) 0x5;
|
||||
public static final byte[] VALUE_SET_LONG_SIT_REMINDER_ON = new byte[]{0x0, 0x1, 0x0, (byte) 0x96};
|
||||
public static final byte[] VALUE_SET_LONG_SIT_REMINDER_OFF = new byte[]{0x0, 0x0, 0x0, (byte) 0x96, 0x4, 0x8, 0x16, 0x7f};
|
||||
|
||||
public static final byte CMD_SET_DISPLAY_ON_LIFT = (byte) 0x9;
|
||||
public static final byte CMD_SET_STEP_GOAL = (byte) 0x3;
|
||||
public static final byte CMD_SET_USER_DATA = (byte) 0x4;
|
||||
public static final byte CMD_SET_DEVICE_VIBRATIONS = (byte) 0x8;
|
||||
|
||||
//group receive sports data 0x15
|
||||
public static final byte CMD_REQUEST_DAY_STEPS_SUMMARY = 0x6;
|
||||
//request steps/hr, as per
|
||||
// https://github.com/vanous/MFitX/blob/AntiGoogle/app/src/main/java/anonymouls/dev/mgcex/app/backend/LM517CommandInterpreter.kt#L242
|
||||
public static final byte CMD_REQUEST_FETCH_DAY_STEPS_DATA = 0xd;
|
||||
public static final byte CMD_REQUEST_STEPS_DATA1 = 0x6;
|
||||
public static final byte CMD_REQUEST_STEPS_DATA0x7 = 0x7;
|
||||
public static final byte CMD_REQUEST_STEPS_DATA0x8 = 0x8;
|
||||
public static final byte CMD_REQUEST_STEPS_DATA0x10 = 0x10;
|
||||
|
||||
//also sleep data as per mfitx
|
||||
//https://github.com/vanous/MFitX/blob/AntiGoogle/app/src/main/java/anonymouls/dev/mgcex/app/backend/LM517CommandInterpreter.kt#L235
|
||||
|
||||
public static final byte RX_HEART_RATE_DATA = 0x0e;
|
||||
public static final byte RX_SPORTS_MEASUREMENT = 0x18; //0/1
|
||||
public static final byte SPORTS_RECEIVE_KEY = 0x1; //0/1
|
||||
|
||||
public static final byte RX_SLEEP_DATA = 0x3;
|
||||
public static final byte RX_STEP_DATA = 0x2;
|
||||
// https://github.com/vanous/MFitX/blob/AntiGoogle/app/src/main/java/anonymouls/dev/mgcex/app/backend/LM517CommandInterpreter.kt#L162
|
||||
|
||||
public static final byte RX_SPORTS_DAY_DATA = 0xc; //0/1
|
||||
|
||||
//group get band info 0x20
|
||||
public static final byte CMD_RX_BAND_INFO = (byte) 0x2;
|
||||
|
||||
//group request data 0x1a
|
||||
public static final byte CMD_GET_STEPS_TARGET = 0x2;
|
||||
public static final byte CMD_GET_HW_INFO = 0x10;
|
||||
public static final byte CMD_GET_AUTO_HR = 0x8;
|
||||
public static final byte CMD_GET_CONTACTS = 0xd;
|
||||
|
||||
//group 0x14
|
||||
public static final byte CMD_UNBIND = (byte) 0x0;
|
||||
|
||||
//group 0x1d
|
||||
public static final byte CMD_RESET = (byte) 0x1;
|
||||
|
||||
// group receive data
|
||||
public static final byte RX_FIND_PHONE = (byte) 0x01;
|
||||
public static final byte RX_CAMERA1 = (byte) 0x02;
|
||||
public static final byte RX_CAMERA2 = (byte) 0x03;
|
||||
public static final byte RX_CAMERA3 = (byte) 0x04;
|
||||
public static final byte RX_MEDIA_PLAY_PAUSE = (byte) 0x0b;
|
||||
public static final byte RX_MEDIA_FORW = (byte) 0x0c;
|
||||
public static final byte RX_MEDIA_BACK = (byte) 0x0a;
|
||||
|
||||
|
||||
//values
|
||||
public static final byte VALUE_ON = (byte) 0x1;
|
||||
public static final byte VALUE_OFF = (byte) 0x0;
|
||||
|
||||
public static final byte UNIT_METRIC = (byte) 0x1;
|
||||
public static final byte UNIT_IMPERIAL = (byte) 0x2;
|
||||
|
||||
public static final byte GENDER_MALE = (byte) 0x1;
|
||||
public static final byte GENDER_FEMALE = (byte) 0x0;
|
||||
|
||||
public static final byte VALUE_SET_ARM_LEFT = (byte) 0x0; //guessing
|
||||
public static final byte VALUE_SET_ARM_RIGHT = (byte) 0x1;
|
||||
|
||||
|
||||
public static final byte[] VALUE_SET_DEVICE_VIBRATIONS_ENABLE = new byte[]{0x1, 0x1, 0x1, 0x1};
|
||||
public static final byte[] VALUE_SET_DEVICE_VIBRATIONS_DISABLE = new byte[]{0, 0, 0, 0};
|
||||
|
||||
public static final byte NOTIFICATION_ICON_FACEBOOK = (byte) 0x4;
|
||||
public static final byte NOTIFICATION_ICON_TWITTER = (byte) 0x5;
|
||||
public static final byte NOTIFICATION_ICON_WHATSAPP = (byte) 0x8;
|
||||
public static final byte NOTIFICATION_ICON_LINE = (byte) 0x7;
|
||||
public static final byte NOTIFICATION_ICON_SMS = (byte) 0x1;
|
||||
public static final byte NOTIFICATION_ICON_WECHAT = (byte) 0x3;
|
||||
public static final byte NOTIFICATION_ICON_QQ = (byte) 0x2;
|
||||
public static final byte NOTIFICATION_ICON_INSTAGRAM = (byte) 0x10;
|
||||
|
||||
public static final int LANG_CHINESE = 0x0;
|
||||
public static final int LANG_PORTUGUESE = 0xc;
|
||||
public static final int LANG_GERMAN = 0x5;
|
||||
public static final int LANG_SPANISH = 0x6;
|
||||
public static final int LANG_FRENCH = 0x7;
|
||||
public static final int LANG_NETHERLANDS = 0xa;
|
||||
public static final int LANG_POLISH = 0xb;
|
||||
public static final int LANG_RUSSIAN = 0xd;
|
||||
public static final int LANG_TURKISH = 0x10;
|
||||
public static final int LANG_ENGLISH = 0x1;
|
||||
public static final int LANG_CZECH = 0x4;
|
||||
public static final int LANG_ITALIAN = 0x12;
|
||||
|
||||
//00 01 00 96 03 08 16 7f
|
||||
//^^ zeros ^^ on/off ^^ sep ^^unknown ^^minutes ^^from ^^ to ^^ unknown
|
||||
//minutes are array of minutes by 15, in 45,60, 75...→ 3,4,5...
|
||||
//the byte 4 → 96 could be experimented with to set different values..., byte 3 is probably Hi, byte 4 Low
|
||||
//public static final byte[] CMD_SET_LONG_SIT_REMINDER = new byte[]{(byte) 0x12, (byte) 0x5};
|
||||
//maybe could be usign the ON/OFF?
|
||||
//public static final byte[] VALUE_SET_LONG_SIT_REMINDER_ON = new byte[]{0x0, 0x1, 0x0, (byte) 0x96};
|
||||
//public static final byte[] VALUE_SET_LONG_SIT_REMINDER_OFF = new byte[]{0x0, 0x0, 0x0, (byte) 0x96, 0x4, 0x8, 0x16, 0x7f};
|
||||
|
||||
//Value: cd 00 0a 12 01 09 00 05 01 01 e0 05 28 ON
|
||||
//Value: cd 00 0a 12 01 09 00 05 00 01 e0 05 28 OFF
|
||||
// 00 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
//byte 8 on/off
|
||||
// 9,10,11,12 → time from/to
|
||||
//public static final byte[] CMD_SET_DISPLAY_ON_LIFT = new byte[]{(byte) 0x12, (byte) 0x9};
|
||||
//maybe could be usign the ON/OFF?
|
||||
//public static final byte VALUE_SET_DISPLAY_ON_LIFT_ON = 0x1;
|
||||
//public static final byte[] VALUE_SET_DISPLAY_ON_LIFT_OFF = new byte[]{0x0, 0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
//time
|
||||
//0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB
|
||||
//find watch
|
||||
//new byte[]{(byte) 0xcd, (byte) 0x00, (byte) 0x06,
|
||||
// (byte) 0x12, (byte) 0x01, (byte) 0x0b, (byte) 0x00, (byte) 0x01, (byte) 0x01};
|
||||
|
||||
/*init procedure:
|
||||
get pair cd 00 06 12 01 0a 00 01 02 → 18, 10
|
||||
cd 00 09 12 01 01 00 04 55 f8 36 90
|
||||
cd 00 05 1a 01 0a 00 00
|
||||
cd 00 05 1a 01 0c 00 00
|
||||
cd 00 06 12 01 15 00 01 01
|
||||
cd 00 06 12 01 ff 00 01 01
|
||||
cd 00 05 1a 01 01 00 00
|
||||
dc 00 05 1a 01 00 0c 01
|
||||
cd 00 05 1a 01 0f 00 00
|
||||
cd 00 05 1a 01 10 00 00
|
||||
dc 00 05 1a 01 00 1c 01
|
||||
something cd 00 05 20 01 02 00 00 → 32, 2
|
||||
real time step cd 00 06 15 01 06 00 01 01 → 21, 6
|
||||
*/
|
||||
|
||||
//received heartrate
|
||||
//0xcd 0x00 0x11 0x15 0x01 0x0e 0x00 0x0c 0x2a 0xf8 0x00 0x01 0x00 0x00 0x31 0x2c 0x62 0x75 0x54 0x47
|
||||
//0xcd 0x00 0x11 0x15 0x01 0x0e 0x00 0x0c 0x2b 0x04 0x00 0x01 0x00 0x01 0x43 0x94 0x62 0x5c 0x48 0x53
|
||||
//cd001115010e000c2b04000100014394625c4853
|
||||
|
||||
//find band
|
||||
// cd 00 06 12 01 0b 00 01 01
|
||||
|
||||
//set celsius/fahrenheit?
|
||||
//cd0006120121000100
|
||||
//cd0006120121000101
|
||||
|
||||
//find phone
|
||||
//0xcd 0x00 0x05 0x1c 0x01 0x01 0x00 0x00
|
||||
//camera:
|
||||
//0xcd 0x00 0x05 0x1c 0x01 0x03 0x00 0x00
|
||||
//0xcd 0x00 0x05 0x1c 0x01 0x02 0x00 0x00
|
||||
//0xcd 0x00 0x05 0x1c 0x01 0x04 0x00 0x00
|
||||
|
||||
// << 0xCD 0x00 0x05 0x1C 0x01 0x0A 0x00 0x00
|
||||
//pause 0xCD 0x00 0x05 0x1C 0x01 0x0B 0x00 0x00
|
||||
// >> 0xCD 0x00 0x05 0x1C 0x01 0x0C 0x00 0x00
|
||||
|
||||
//0xCD 0x00 0x05 0x1C 0x01 0x03 0x00 0x00
|
||||
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
/* Copyright (C) 2016-2020 Petr Vaněk
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.fitpro;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
|
||||
public class FitProDeviceCoordinator extends AbstractDeviceCoordinator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FitProDeviceCoordinator.class);
|
||||
|
||||
|
||||
@Override
|
||||
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
|
||||
Long deviceId = device.getId();
|
||||
QueryBuilder<?> qb = session.getFitProActivitySampleDao().queryBuilder();
|
||||
qb.where(FitProActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
try {
|
||||
BluetoothDevice device = candidate.getDevice();
|
||||
String name = device.getName();
|
||||
|
||||
if (name != null &&
|
||||
(name.equals("M6") ||
|
||||
name.equals("M4"))
|
||||
) {
|
||||
return DeviceType.FITPRO;
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
LOG.error("unable to check device support", ex);
|
||||
}
|
||||
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceType getDeviceType() {
|
||||
return DeviceType.FITPRO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBondingStyle() {
|
||||
// different devices seem to work differently.
|
||||
// user will unfortunately need to decide
|
||||
return BONDING_STYLE_ASK;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Class<? extends Activity> getPairingActivity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityDataFetching() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityTracking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
||||
return new FitProSampleProvider(device, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstallHandler findInstallHandler(Uri uri, Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsScreenshots() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlarmSlotCount() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSmartWakeup(GBDevice device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsHeartRateMeasurement(GBDevice device) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManufacturer() {
|
||||
return "FitPro";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAppsManagement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getAppsManagementActivity() {
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCalendarEvents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRealtimeData() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsWeather() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFindDevice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
||||
return new int[]{
|
||||
R.xml.devicesettings_liftwrist_display_no_on,
|
||||
R.xml.devicesettings_longsit_extended,
|
||||
R.xml.devicesettings_donotdisturb_no_auto,
|
||||
R.xml.devicesettings_sleep_time,
|
||||
R.xml.devicesettings_wearlocation,
|
||||
R.xml.devicesettings_autoheartrate,
|
||||
R.xml.devicesettings_vibrations_enable,
|
||||
R.xml.devicesettings_notifications_enable,
|
||||
R.xml.devicesettings_fitpro,
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2016-2020 Petr Vaněk
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.fitpro;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import de.greenrobot.dao.AbstractDao;
|
||||
import de.greenrobot.dao.Property;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
|
||||
public class FitProSampleProvider extends AbstractSampleProvider<FitProActivitySample> {
|
||||
public FitProSampleProvider(GBDevice device, DaoSession session) {
|
||||
super(device, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDao<FitProActivitySample, ?> getSampleDao() {
|
||||
return getSession().getFitProActivitySampleDao();
|
||||
}
|
||||
|
||||
|
||||
// as per FitProDeviceSupport.rawActivityKindToUniqueKind
|
||||
|
||||
@Override
|
||||
public int normalizeType(int rawType) {
|
||||
switch (rawType) {
|
||||
case 1:
|
||||
return ActivityKind.TYPE_ACTIVITY;
|
||||
case 11:
|
||||
return ActivityKind.TYPE_DEEP_SLEEP;
|
||||
case 12:
|
||||
return ActivityKind.TYPE_LIGHT_SLEEP;
|
||||
default:
|
||||
return ActivityKind.TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toRawActivityKind(int activityKind) {
|
||||
switch (activityKind) {
|
||||
case ActivityKind.TYPE_ACTIVITY:
|
||||
return 1;
|
||||
case ActivityKind.TYPE_DEEP_SLEEP:
|
||||
return 11;
|
||||
case ActivityKind.TYPE_LIGHT_SLEEP:
|
||||
return 12;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float normalizeIntensity(int rawIntensity) {
|
||||
return rawIntensity / 2000f; //samples are per 5 minutes, so this should be sufficient
|
||||
}
|
||||
|
||||
@Override
|
||||
public FitProActivitySample createActivitySample() {
|
||||
return new FitProActivitySample();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Property getRawKindSampleProperty() {
|
||||
return FitProActivitySampleDao.Properties.RawKind;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getTimestampSampleProperty() {
|
||||
return FitProActivitySampleDao.Properties.Timestamp;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getDeviceIdentifierSampleProperty() {
|
||||
return FitProActivitySampleDao.Properties.DeviceId;
|
||||
}
|
||||
}
|
@ -91,6 +91,7 @@ public enum DeviceType {
|
||||
MIJIA_LYWSD02(200, R.drawable.ic_device_pebble, R.drawable.ic_device_pebble_disabled, R.string.devicetype_mijia_lywsd02),
|
||||
LEFUN(210, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled, R.string.devicetype_lefun),
|
||||
SMAQ2OSS(220, R.drawable.ic_device_default, R.drawable.ic_device_default, R.string.devicetype_smaq2oss),
|
||||
FITPRO(230, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_fitpro),
|
||||
ITAG(250, R.drawable.ic_device_itag, R.drawable.ic_device_itag_disabled, R.string.devicetype_itag),
|
||||
NUTMINI(251, R.drawable.ic_device_itag, R.drawable.ic_device_itag_disabled, R.string.devicetype_nut_mini),
|
||||
VIBRATISSIMO(300, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo),
|
||||
|
@ -86,7 +86,7 @@ public class Weather {
|
||||
}
|
||||
|
||||
private static final Weather weather = new Weather();
|
||||
public static Weather getInstance() {return weather;}
|
||||
public static Weather getInstance() { return weather; }
|
||||
|
||||
public static byte mapToPebbleCondition(int openWeatherMapCondition) {
|
||||
/* deducted values:
|
||||
@ -880,4 +880,95 @@ public class Weather {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte mapToFitProCondition(int openWeatherMapCondition) {
|
||||
switch (openWeatherMapCondition) {
|
||||
case 100:
|
||||
return 1;
|
||||
case 104:
|
||||
return 2;
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
return 3;
|
||||
case 305:
|
||||
case 309:
|
||||
return 4;
|
||||
case 306:
|
||||
case 314:
|
||||
case 399:
|
||||
return 5;
|
||||
case 307:
|
||||
case 308:
|
||||
case 310:
|
||||
case 311:
|
||||
case 312:
|
||||
case 315:
|
||||
case 316:
|
||||
case 317:
|
||||
case 318:
|
||||
return 6;
|
||||
case 300:
|
||||
case 301:
|
||||
case 302:
|
||||
case 303:
|
||||
return 7;
|
||||
case 400:
|
||||
case 407:
|
||||
return 8;
|
||||
case 401:
|
||||
case 408:
|
||||
case 499:
|
||||
return 9;
|
||||
case 402:
|
||||
case 403:
|
||||
case 409:
|
||||
case 410:
|
||||
return 10;
|
||||
case 404:
|
||||
case 405:
|
||||
case 406:
|
||||
return 11;
|
||||
case 500:
|
||||
case 501:
|
||||
case 502:
|
||||
case 509:
|
||||
case 510:
|
||||
case 511:
|
||||
case 512:
|
||||
case 513:
|
||||
case 514:
|
||||
case 515:
|
||||
return 12;
|
||||
case 304:
|
||||
case 313:
|
||||
return 13;
|
||||
case 503:
|
||||
case 504:
|
||||
case 507:
|
||||
case 508:
|
||||
return 14;
|
||||
case 200:
|
||||
case 201:
|
||||
case 202:
|
||||
case 203:
|
||||
case 204:
|
||||
return 15;
|
||||
case 205:
|
||||
case 206:
|
||||
case 207:
|
||||
case 208:
|
||||
return 16;
|
||||
case 209:
|
||||
case 210:
|
||||
case 211:
|
||||
return 17;
|
||||
case 212:
|
||||
return 18;
|
||||
case 231:
|
||||
return 19;
|
||||
default:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.fitpro.FitProDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs.BangleJSDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.CasioGB6900DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.CasioGBX100DeviceSupport;
|
||||
@ -354,6 +355,9 @@ public class DeviceSupportFactory {
|
||||
case DOMYOS_T540:
|
||||
deviceSupport = new ServiceDeviceSupport(new DomyosT540Support(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
case FITPRO:
|
||||
deviceSupport = new ServiceDeviceSupport(new FitProDeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
}
|
||||
if (deviceSupport != null) {
|
||||
deviceSupport.setContext(gbDevice, mBtAdapter, mContext);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -80,4 +80,18 @@ public class ArrayUtils {
|
||||
public static boolean startsWith(byte[] array, byte[] values) {
|
||||
return equals(array, values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array to string representation
|
||||
*
|
||||
* @param array the array to convert
|
||||
* @return
|
||||
*/
|
||||
public static String arrayToString(byte[] array) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (byte i : array) {
|
||||
stringBuilder.append(String.format("0x%02X ", i));
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProDeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.gb6900.CasioGB6900DeviceCoordinator;
|
||||
@ -304,7 +305,7 @@ public class DeviceHelper {
|
||||
result.add(new SMAQ2OSSCoordinator());
|
||||
result.add(new UM25Coordinator());
|
||||
result.add(new DomyosT540Cooridnator());
|
||||
|
||||
result.add(new FitProDeviceCoordinator());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
10
app/src/main/res/drawable/ic_chair.xml
Normal file
10
app/src/main/res/drawable/ic_chair.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#7E7E7E">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,8V6c0,-1.65 -1.35,-3 -3,-3H7C5.35,3 4,4.35 4,6v2c-1.65,0 -3,1.35 -3,3v5c0,1.65 1.35,3 3,3v1c0,0.55 0.45,1 1,1c0.55,0 1,-0.45 1,-1v-1h12v1c0,0.55 0.45,1 1,1c0.55,0 1,-0.45 1,-1v-1c1.65,0 3,-1.35 3,-3v-5C23,9.35 21.65,8 20,8zM6,6c0,-0.55 0.45,-1 1,-1h10c0.55,0 1,0.45 1,1v2.78c-0.61,0.55 -1,1.34 -1,2.22v2H7v-2c0,-0.88 -0.39,-1.67 -1,-2.22V6zM21,16c0,0.55 -0.45,1 -1,1H4c-0.55,0 -1,-0.45 -1,-1v-5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v4h14v-4c0,-0.55 0.45,-1 1,-1s1,0.45 1,1V16z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_notifications.xml
Normal file
10
app/src/main/res/drawable/ic_notifications.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#7E7E7E"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6z" />
|
||||
</vector>
|
@ -52,6 +52,34 @@
|
||||
<item>sk</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_fitpro_language_options">
|
||||
<item>@string/automatic</item>
|
||||
<item>@string/simplified_chinese</item>
|
||||
<item>@string/english</item>
|
||||
<item>@string/turkish</item>
|
||||
<item>@string/polish</item>
|
||||
<item>@string/portuguese</item>
|
||||
<item>@string/russian</item>
|
||||
<item>@string/spanish</item>
|
||||
<item>@string/german</item>
|
||||
<item>@string/french</item>
|
||||
<item>@string/czesh</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_fitpro_language_values">
|
||||
<item>auto</item>
|
||||
<item>zh_CN</item>
|
||||
<item>en_US</item>
|
||||
<item>tr_TR</item>
|
||||
<item>pl_PL</item>
|
||||
<item>pt_BR</item>
|
||||
<item>ru_RU</item>
|
||||
<item>es_ES</item>
|
||||
<item>de_DE</item>
|
||||
<item>fr_FR</item>
|
||||
<item>cs_CZ</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="notification_mode">
|
||||
<item>@string/always</item>
|
||||
<item>@string/when_screen_off</item>
|
||||
@ -1724,4 +1752,28 @@
|
||||
<item>@string/p_menuitem_goal</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="inactivity_minutes">
|
||||
<item>45</item>
|
||||
<item>60</item>
|
||||
<item>75</item>
|
||||
<item>90</item>
|
||||
<item>105</item>
|
||||
<item>120</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="inactivity_minutes_values">
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>6</item>
|
||||
<item>7</item>
|
||||
<item>8</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="autoheartrate_interval_hours">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
|
@ -876,6 +876,7 @@
|
||||
<string name="devicetype_sonyswr12" translatable="false">Sony SWR12</string>
|
||||
<string name="devicetype_waspos">Wasp-os</string>
|
||||
<string name="devicetype_smaq2oss">SMA-Q2 OSS</string>
|
||||
<string name="devicetype_fitpro">FitPro</string>
|
||||
<string name="devicetype_domyos_t540"/>
|
||||
<string name="choose_auto_export_location">Choose export location</string>
|
||||
<string name="notification_channel_name">General</string>
|
||||
@ -1257,4 +1258,16 @@
|
||||
<string name="watchface_setting_title_power_saving">Power saving</string>
|
||||
<string name="watchface_setting_power_saving_display">Disable display updates while off wrist</string>
|
||||
<string name="watchface_setting_power_saving_hands">Disable hands movement while off wrist</string>
|
||||
<string name="prefs_sleep_time">Sleep times</string>
|
||||
<string name="prefs_sleep_time_label">Define sleep hours</string>
|
||||
<string name="prefs_sleep_time_summary">Specifies times when sleep is registered</string>
|
||||
<string name="prefs_vibration_enable">Enable vibrations</string>
|
||||
<string name="prefs_notifications_enable">Enable notifications</string>
|
||||
<string name="enable_vibrations_summary">Vibrations for calls, messages, notifications and more</string>
|
||||
<string name="enable_notifications_summary">Notifications for calls, messages and more</string>
|
||||
<string name="prefs_autoheartrate">Automatic Heart Rate</string>
|
||||
<string name="prefs_autoheartrate_summary">Periodical Heart Rate measurements during the day and also while asleep</string>
|
||||
<string name="prefs_autoheartrate_measurement">Automatic Heart Rate measurements</string>
|
||||
<string name="prefs_autoheartrate_sleep">Take measurements during sleep</string>
|
||||
<string name="prefs_autoheartrate_interval">Frequency of measurements</string>
|
||||
</resources>
|
||||
|
43
app/src/main/res/xml/devicesettings_autoheartrate.xml
Normal file
43
app/src/main/res/xml/devicesettings_autoheartrate.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_heartrate"
|
||||
android:key="screen_autoheartrate"
|
||||
android:persistent="false"
|
||||
android:summary="@string/prefs_autoheartrate_summary"
|
||||
android:title="@string/prefs_autoheartrate">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/prefs_autoheartrate_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_autoheartrate_switch"
|
||||
android:title="@string/prefs_autoheartrate_measurement" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="pref_autoheartrate_switch"
|
||||
android:key="pref_autoheartrate_sleep"
|
||||
android:title="@string/prefs_autoheartrate_sleep" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="2"
|
||||
android:dependency="pref_autoheartrate_switch"
|
||||
android:entries="@array/autoheartrate_interval_hours"
|
||||
android:entryValues="@array/autoheartrate_interval_hours"
|
||||
android:key="pref_autoheartrate_interval"
|
||||
android:summary="%s"
|
||||
android:title="@string/prefs_autoheartrate_interval" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="06:00"
|
||||
android:key="pref_autoheartrate_start"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_start" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="23:00"
|
||||
android:key="pref_autoheartrate_end"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_end" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -19,7 +19,7 @@
|
||||
android:title="@string/mi2_prefs_do_not_disturb" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="01:00"
|
||||
android:defaultValue="22:00"
|
||||
android:key="do_not_disturb_no_auto_start"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_start" />
|
||||
|
||||
|
12
app/src/main/res/xml/devicesettings_fitpro.xml
Normal file
12
app/src/main/res/xml/devicesettings_fitpro.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:entries="@array/pref_fitpro_language_options"
|
||||
android:entryValues="@array/pref_fitpro_language_values"
|
||||
android:icon="@drawable/ic_language"
|
||||
android:key="language"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_title_language" />
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_arrow_upward"
|
||||
android:key="screen_liftwrist_display"
|
||||
android:persistent="false"
|
||||
android:title="@string/mi2_prefs_activate_display_on_lift">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/mi2_prefs_activate_display_on_lift" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_off"
|
||||
android:enabled="true"
|
||||
android:entries="@array/do_not_disturb_no_auto"
|
||||
android:entryValues="@array/do_not_disturb_no_auto_values"
|
||||
android:key="activate_display_on_lift_wrist"
|
||||
android:summary="%s"
|
||||
android:title="@string/mi2_prefs_activate_display_on_lift" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="06:00"
|
||||
android:key="display_on_lift_start"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_start" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="23:00"
|
||||
android:key="display_on_lift_end"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_end" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_activity_sleep"
|
||||
android:icon="@drawable/ic_chair"
|
||||
android:key="screen_longsit"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
|
37
app/src/main/res/xml/devicesettings_longsit_extended.xml
Normal file
37
app/src/main/res/xml/devicesettings_longsit_extended.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_chair"
|
||||
android:key="screen_longsit"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/mi2_prefs_inactivity_warnings_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_longsit_switch"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="4"
|
||||
android:dependency="pref_longsit_switch"
|
||||
android:entries="@array/inactivity_minutes"
|
||||
android:entryValues="@array/inactivity_minutes_values"
|
||||
android:key="pref_longsit_period"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings_threshold" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="08:00"
|
||||
android:key="pref_longsit_start"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_start" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="16:00"
|
||||
android:key="pref_longsit_end"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_end" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_activity_sleep"
|
||||
android:icon="@drawable/ic_chair"
|
||||
android:defaultValue="false"
|
||||
android:key="screen_longsit_noshed"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings"
|
||||
|
10
app/src/main/res/xml/devicesettings_notifications_enable.xml
Normal file
10
app/src/main/res/xml/devicesettings_notifications_enable.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_notifications"
|
||||
android:key="notification_enable"
|
||||
android:summary="@string/enable_notifications_summary"
|
||||
android:title="@string/prefs_notifications_enable" />
|
||||
</androidx.preference.PreferenceScreen>
|
32
app/src/main/res/xml/devicesettings_sleep_time.xml
Normal file
32
app/src/main/res/xml/devicesettings_sleep_time.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_access_time"
|
||||
android:key="prefs_sleep_time"
|
||||
android:persistent="false"
|
||||
android:summary="@string/prefs_sleep_time_summary"
|
||||
android:title="@string/prefs_sleep_time">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/prefs_sleep_time_label" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_off"
|
||||
android:enabled="true"
|
||||
android:entries="@array/do_not_disturb_no_auto"
|
||||
android:entryValues="@array/do_not_disturb_no_auto_values"
|
||||
android:key="prefs_enable_sleep_time"
|
||||
android:summary="%s"
|
||||
android:title="@string/prefs_sleep_time" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="22:00"
|
||||
android:key="prefs_sleep_time_start"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_start" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="06:00"
|
||||
android:key="prefs_sleep_time_end"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_end" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
10
app/src/main/res/xml/devicesettings_vibrations_enable.xml
Normal file
10
app/src/main/res/xml/devicesettings_vibrations_enable.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_vibration"
|
||||
android:key="vibration_enable"
|
||||
android:summary="@string/enable_vibrations_summary"
|
||||
android:title="@string/prefs_vibration_enable" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,50 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class FitProTests extends TestBase {
|
||||
// since unit tests seem to be broken in Android Studio these are not complete
|
||||
// but but at least this provides some help for the future
|
||||
// can be used this way:
|
||||
|
||||
@Test
|
||||
public void testSleepPacket() {
|
||||
String sleepData = "cd002915010300242b1f0008000f0003001e0002002d0001003c0001004b0001005a00010069000200780002";
|
||||
|
||||
//handleSleepData(stringToByteArray(sleepData));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepPacket() {
|
||||
//note different format of data and thus different stringWith0xToByteArray method
|
||||
String stepData = "0xcd 0x00 0x31 0x15 0x01 0x02 0x00 0x2c 0x2b 0x34 0x00 0x05 0x80 0x45 0x07 0x1a 0x09 0xc8 0xbb 0x06 0x79 0x55 0x06 0x26 0x09 0xe8 0xb0 0xe4 0x71 0x15 0x05 0x9b 0x0a 0x08 0xa4 0xdc 0x7b 0x85 0x06 0x67 0x0a 0x28 0xb4 0x16 0x76 0x35 0x06 0x16 0x0a 0x48 0xac 0x57";
|
||||
|
||||
//handleStepData(stringWith0xToByteArray(stepData));
|
||||
}
|
||||
|
||||
public byte[] stringToByteArray(String s) {
|
||||
byte[] byteArray = new byte[s.length() / 2];
|
||||
String[] strBytes = new String[s.length() / 2];
|
||||
int k = 0;
|
||||
for (int i = 0; i < s.length(); i = i + 2) {
|
||||
int j = i + 2;
|
||||
strBytes[k] = s.substring(i, j);
|
||||
byteArray[k] = (byte) Integer.parseInt(strBytes[k], 16);
|
||||
k++;
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] stringWith0xToByteArray(String s) {
|
||||
String[] split = s.split(" ");
|
||||
int k = 0;
|
||||
byte[] byteArray = new byte[split.length];
|
||||
for (String ch : split) {
|
||||
byteArray[k] = (byte) Integer.parseInt(ch.split("x")[1], 16);
|
||||
k++;
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user