From b3e1cbf55eeb73baefcfc69c5d64b5b068622393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Paulo=20Barraca?= Date: Mon, 23 Jan 2017 00:08:36 +0000 Subject: [PATCH] HPlus: Support of Makibes F68 and small fixes to HPlus devices --- .../devices/hplus/HPlusConstants.java | 6 +- .../devices/hplus/HPlusCoordinator.java | 8 +- .../hplus/HPlusHealthSampleProvider.java | 36 +++-- .../devices/hplus/MakibesF68Coordinator.java | 33 +++++ .../gadgetbridge/model/DeviceType.java | 1 + .../service/DeviceSupportFactory.java | 6 +- .../devices/hplus/HPlusDataRecordDaySlot.java | 21 +-- .../hplus/HPlusDataRecordRealtime.java | 4 +- .../devices/hplus/HPlusHandlerThread.java | 135 ++++++++---------- .../service/devices/hplus/HPlusSupport.java | 132 +++++++++++------ .../gadgetbridge/util/DeviceHelper.java | 3 + 11 files changed, 232 insertions(+), 153 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/MakibesF68Coordinator.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusConstants.java index 01e619bf..73515ee7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusConstants.java @@ -15,8 +15,8 @@ public final class HPlusConstants { public static final UUID UUID_SERVICE_HP = UUID.fromString("14701820-620a-3973-7c78-9cfff0876abd"); - public static final byte ARG_COUNTRY_CN = 1; - public static final byte ARG_COUNTRY_OTHER = 2; + public static final byte ARG_LANGUAGE_CN = 1; + public static final byte ARG_LANGUAGE_EN = 2; public static final byte ARG_TIMEMODE_24H = 0; public static final byte ARG_TIMEMODE_12H = 1; @@ -111,7 +111,7 @@ public final class HPlusConstants { public static final String PREF_HPLUS_ALERT_TIME = "hplus_alert_time"; public static final String PREF_HPLUS_SIT_START_TIME = "hplus_sit_start_time"; public static final String PREF_HPLUS_SIT_END_TIME = "hplus_sit_end_time"; - public static final String PREF_HPLUS_COUNTRY = "hplus_country"; + public static final String PREF_HPLUS_LANGUAGE = "hplus_language"; public static final Map transliterateMap = new HashMap(){ { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java index 8a596d4c..8495e664 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java @@ -38,8 +38,8 @@ import java.util.Collection; import java.util.Collections; public class HPlusCoordinator extends AbstractDeviceCoordinator { - private static final Logger LOG = LoggerFactory.getLogger(HPlusCoordinator.class); - private static Prefs prefs = GBApplication.getPrefs(); + protected static final Logger LOG = LoggerFactory.getLogger(HPlusCoordinator.class); + protected static Prefs prefs = GBApplication.getPrefs(); @NonNull @Override @@ -144,8 +144,8 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator { return activityUser.getStepsGoal(); } - public static byte getCountry(String address) { - return (byte) prefs.getInt(HPlusConstants.PREF_HPLUS_COUNTRY + "_" + address, 10); + public static byte getLanguage(String address) { + return (byte) prefs.getInt(HPlusConstants.PREF_HPLUS_LANGUAGE + "_" + address, HPlusConstants.ARG_LANGUAGE_EN); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusHealthSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusHealthSampleProvider.java index 9a7fa8c1..23f4090e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusHealthSampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusHealthSampleProvider.java @@ -141,30 +141,46 @@ public class HPlusHealthSampleProvider extends AbstractSampleProvider= today.getTimeInMillis() / 1000){ - //Only consider these for the current day as a single message is enough for steps - //HR and Overlays will still benefit from the full set of samples + + /**Strategy is: + * Calculate max steps from realtime messages + * Calculate sum of steps from day 10 minute slot summaries + */ + if(sample.getRawKind() == HPlusDataRecord.TYPE_REALTIME) { - int aux = sample.getSteps(); - sample.setSteps(sample.getSteps() - stepsToday); - stepsToday = aux; - }else - sample.setSteps(ActivitySample.NOT_MEASURED); + stepsTodayMax = Math.max(stepsTodayMax, sample.getSteps()); + }else if(sample.getRawKind() == HPlusDataRecord.TYPE_DAY_SLOT) { + stepsTodayCount += sample.getSteps(); + } + + sample.setSteps(ActivitySample.NOT_MEASURED); + lastSample = sample; }else{ if (sample.getRawKind() != HPlusDataRecord.TYPE_DAY_SUMMARY) { - sample.setSteps(ActivityKind.TYPE_NOT_MEASURED); + sample.setSteps(ActivitySample.NOT_MEASURED); } } } + if(lastSample != null) + lastSample.setSteps(Math.max(stepsTodayCount, stepsTodayMax)); + for (HPlusHealthActivityOverlay overlay : overlayRecords) { //Create fake events to improve activity counters if there are no events around the overlay //timestamp boundaries + //Insert one before, one at the beginning, one at the end, and one 1s after. + insertVirtualItem(samples, Math.max(overlay.getTimestampFrom() - 1, timestamp_from), overlay.getDeviceId(), overlay.getUserId()); insertVirtualItem(samples, Math.max(overlay.getTimestampFrom(), timestamp_from), overlay.getDeviceId(), overlay.getUserId()); insertVirtualItem(samples, Math.min(overlay.getTimestampTo() - 1, timestamp_to - 1), overlay.getDeviceId(), overlay.getUserId()); + insertVirtualItem(samples, Math.min(overlay.getTimestampTo(), timestamp_to), overlay.getDeviceId(), overlay.getUserId()); + for (HPlusHealthActivitySample sample : samples) { if (sample.getTimestamp() >= overlay.getTimestampFrom() && sample.getTimestamp() < overlay.getTimestampTo()) { @@ -191,7 +207,7 @@ public class HPlusHealthSampleProvider extends AbstractSampleProvider mDaySlotSamples = new ArrayList<>(); + List mDaySlotRecords = new ArrayList<>(); + + private HPlusDataRecordDaySlot mCurrentDaySlot = null; public HPlusHandlerThread(GBDevice gbDevice, Context context, HPlusSupport hplusSupport) { super(gbDevice, context); @@ -113,10 +109,6 @@ class HPlusHandlerThread extends GBDeviceIoThread { Calendar now = GregorianCalendar.getInstance(); - if (now.compareTo(mHelloTime) > 0) { - sendHello(); - } - if (now.compareTo(mGetDaySlotsTime) > 0) { requestNextDaySlots(); } @@ -130,7 +122,7 @@ class HPlusHandlerThread extends GBDeviceIoThread { } now = GregorianCalendar.getInstance(); - waitTime = Math.min(mGetDaySummaryTime.getTimeInMillis(), Math.min(Math.min(mGetDaySlotsTime.getTimeInMillis(), mGetSleepTime.getTimeInMillis()), mHelloTime.getTimeInMillis())) - now.getTimeInMillis(); + waitTime = Math.min(mGetDaySummaryTime.getTimeInMillis(), Math.min(mGetDaySlotsTime.getTimeInMillis(), mGetSleepTime.getTimeInMillis())) - now.getTimeInMillis(); } } @@ -152,54 +144,22 @@ class HPlusHandlerThread extends GBDeviceIoThread { mSlotsInitialSync = true; mLastSlotReceived = -1; mLastSlotRequested = 0; + mCurrentDaySlot = null; + mDaySlotRecords.clear(); TransactionBuilder builder = new TransactionBuilder("startSyncDayStats"); builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DEVICE_ID}); - builder.wait(400); builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_VERSION}); - builder.wait(400); - - builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_SLEEP}); - builder.wait(400); - builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DAY_DATA}); - builder.wait(400); - builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_ACTIVE_DAY}); - builder.wait(400); builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_CURR_DATA}); builder.queue(mHPlusSupport.getQueue()); - scheduleHello(); synchronized (waitObject) { waitObject.notify(); } } - /** - * Send an Hello/Null Packet to keep connection - */ - private void sendHello() { - TransactionBuilder builder = new TransactionBuilder("hello"); - - builder.write(mHPlusSupport.ctrlCharacteristic, HPlusConstants.CMD_ACTION_HELLO); - builder.queue(mHPlusSupport.getQueue()); - - scheduleHello(); - - synchronized (waitObject) { - waitObject.notify(); - } - } - - /** - * Schedule an Hello Packet in the future - */ - public void scheduleHello(){ - mHelloTime = GregorianCalendar.getInstance(); - mHelloTime.add(Calendar.SECOND, HELLO_INTERVAL); - } - /** * Process a message containing information regarding a day slot * A slot summarizes 10 minutes of data @@ -218,32 +178,56 @@ class HPlusHandlerThread extends GBDeviceIoThread { return false; } - //Ignore real time messages as they are still not understood - if(!mSlotsInitialSync){ - mGetDaySlotsTime.set(Calendar.SECOND, CURRENT_DAY_SYNC_PERIOD); - return true; - } - Calendar now = GregorianCalendar.getInstance(); int nowSlot = now.get(Calendar.HOUR_OF_DAY) * 6 + (now.get(Calendar.MINUTE) / 10); - - //If the slot is in the future, actually it is from the previous day - //Subtract a day of seconds - if(record.slot >= nowSlot){ - record.timestamp -= 3600 * 24; + if(record.slot == nowSlot){ + if(mCurrentDaySlot != null && mCurrentDaySlot != record){ + mCurrentDaySlot.accumulate(record); + mDaySlotRecords.add(mCurrentDaySlot); + mCurrentDaySlot = null; + }else{ + //Store it to a temp variable as this is an intermediate value + mCurrentDaySlot = record; + if(!mSlotsInitialSync) + return true; + } } - //Ignore out of order messages - if(record.slot == mLastSlotReceived + 1) { - mLastSlotReceived = record.slot; + if(mSlotsInitialSync) { + + //If the slot is in the future, actually it is from the previous day + //Subtract a day of seconds + if(record.slot > nowSlot){ + record.timestamp -= 3600 * 24; + } + + if (record.slot == mLastSlotReceived + 1) { + mLastSlotReceived = record.slot; + } + + //Ignore the current slot as it is incomplete + if(record.slot != nowSlot) + mDaySlotRecords.add(record); + + //Still fetching ring buffer. Request the next slots + if (record.slot == mLastSlotRequested) { + mGetDaySlotsTime.clear(); + synchronized (waitObject) { + waitObject.notify(); + } + } + + //Keep buffering + if(record.slot != 143) + return true; + } else { + mGetDaySlotsTime = GregorianCalendar.getInstance(); + mGetDaySlotsTime.add(Calendar.DAY_OF_MONTH, 1); } - if(record.slot < 143){ - mDaySlotSamples.add(record); - }else { - + if(mDaySlotRecords.size() > 0) { //Sort the samples - Collections.sort(mDaySlotSamples, new Comparator() { + Collections.sort(mDaySlotRecords, new Comparator() { public int compare(HPlusDataRecordDaySlot one, HPlusDataRecordDaySlot other) { return one.timestamp - other.timestamp; } @@ -253,20 +237,20 @@ class HPlusHandlerThread extends GBDeviceIoThread { HPlusHealthSampleProvider provider = new HPlusHealthSampleProvider(getDevice(), dbHandler.getDaoSession()); List samples = new ArrayList<>(); - for(HPlusDataRecordDaySlot storedRecord : mDaySlotSamples) { + for (HPlusDataRecordDaySlot storedRecord : mDaySlotRecords) { HPlusHealthActivitySample sample = createSample(dbHandler, storedRecord.timestamp); - sample.setRawHPlusHealthData(record.getRawData()); - sample.setSteps(record.steps); - sample.setHeartRate(record.heartRate); - sample.setRawKind(record.type); + sample.setRawHPlusHealthData(storedRecord.getRawData()); + sample.setSteps(storedRecord.steps); + sample.setHeartRate(storedRecord.heartRate); + sample.setRawKind(storedRecord.type); sample.setProvider(provider); samples.add(sample); } provider.getSampleDao().insertOrReplaceInTx(samples); - mDaySlotSamples.clear(); + mDaySlotRecords.clear(); } catch (GBException ex) { LOG.debug((ex.getMessage())); @@ -274,13 +258,6 @@ class HPlusHandlerThread extends GBDeviceIoThread { LOG.debug(ex.getMessage()); } } - //Still fetching ring buffer. Request the next slots - if (record.slot == mLastSlotRequested) { - mGetDaySlotsTime.clear(); - synchronized (waitObject) { - waitObject.notify(); - } - } return true; } @@ -357,6 +334,7 @@ class HPlusHandlerThread extends GBDeviceIoThread { LOG.debug((e.getMessage())); return false; } + //Skip duplicated messages as the device seems to send the same record multiple times //This can be used to detect the user is moving (not sleeping) if(prevRealTimeRecord != null && record.same(prevRealTimeRecord)) @@ -490,7 +468,6 @@ class HPlusHandlerThread extends GBDeviceIoThread { * Messages will be provided every 10 minutes after they are available */ private void requestNextDaySlots() { - Calendar now = GregorianCalendar.getInstance(); int currentSlot = now.get(Calendar.HOUR_OF_DAY) * 6 + now.get(Calendar.MINUTE) / 10; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java index c410537c..4bf02c55 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java @@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; @@ -54,6 +55,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { public BluetoothGattCharacteristic measureCharacteristic = null; private HPlusHandlerThread syncHelper; + private DeviceType deviceType = DeviceType.UNKNOWN; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -65,8 +67,11 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { } }; - public HPlusSupport() { + public HPlusSupport(DeviceType type) { super(LOG); + + deviceType = type; + addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS); addSupportedService(GattService.UUID_SERVICE_GENERIC_ATTRIBUTE); addSupportedService(HPlusConstants.UUID_SERVICE_HP); @@ -75,7 +80,6 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { IntentFilter intentFilter = new IntentFilter(); broadcastManager.registerReceiver(mReceiver, intentFilter); - } @Override @@ -107,7 +111,9 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { sendUserInfo(builder); //Sync preferences setSIT(builder); //Sync SIT Interval setCurrentDate(builder); // Sync Current Date + setDayOfWeek(builder); setCurrentTime(builder); // Sync Current Time + setLanguage(builder); requestDeviceInfo(builder); @@ -133,51 +139,69 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { } private HPlusSupport syncPreferences(TransactionBuilder transaction) { - byte gender = HPlusCoordinator.getUserGender(getDevice().getAddress()); - byte age = HPlusCoordinator.getUserAge(getDevice().getAddress()); - byte bodyHeight = HPlusCoordinator.getUserHeight(getDevice().getAddress()); - byte bodyWeight = HPlusCoordinator.getUserWeight(getDevice().getAddress()); - int goal = HPlusCoordinator.getGoal(getDevice().getAddress()); - byte displayTime = HPlusCoordinator.getScreenTime(getDevice().getAddress()); - byte country = HPlusCoordinator.getCountry(getDevice().getAddress()); - byte social = HPlusCoordinator.getSocial(getDevice().getAddress()); // ?? - byte allDayHeart = HPlusCoordinator.getAllDayHR(getDevice().getAddress()); - byte wrist = HPlusCoordinator.getUserWrist(getDevice().getAddress()); - byte alertTimeHour = 0; - byte alertTimeMinute = 0; - if (HPlusCoordinator.getSWAlertTime(getDevice().getAddress())) { - int t = HPlusCoordinator.getAlertTime(getDevice().getAddress()); + if(deviceType == DeviceType.HPLUS) { + byte gender = HPlusCoordinator.getUserGender(getDevice().getAddress()); + byte age = HPlusCoordinator.getUserAge(getDevice().getAddress()); + byte bodyHeight = HPlusCoordinator.getUserHeight(getDevice().getAddress()); + byte bodyWeight = HPlusCoordinator.getUserWeight(getDevice().getAddress()); + int goal = HPlusCoordinator.getGoal(getDevice().getAddress()); + byte displayTime = HPlusCoordinator.getScreenTime(getDevice().getAddress()); + byte country = HPlusCoordinator.getLanguage(getDevice().getAddress()); + byte social = HPlusCoordinator.getSocial(getDevice().getAddress()); // ?? + byte allDayHeart = HPlusCoordinator.getAllDayHR(getDevice().getAddress()); + byte wrist = HPlusCoordinator.getUserWrist(getDevice().getAddress()); + byte alertTimeHour = 0; + byte alertTimeMinute = 0; - alertTimeHour = (byte) ((t / 256) & 0xff); - alertTimeMinute = (byte) (t % 256); + if (HPlusCoordinator.getSWAlertTime(getDevice().getAddress())) { + int t = HPlusCoordinator.getAlertTime(getDevice().getAddress()); + + alertTimeHour = (byte) ((t / 256) & 0xff); + alertTimeMinute = (byte) (t % 256); + } + + byte unit = HPlusCoordinator.getUnit(getDevice().getAddress()); + byte timemode = HPlusCoordinator.getTimeMode((getDevice().getAddress())); + + transaction.write(ctrlCharacteristic, new byte[]{ + HPlusConstants.CMD_SET_PREFS, + gender, + age, + bodyHeight, + bodyWeight, + 0, + 0, + (byte) ((goal / 256) & 0xff), + (byte) (goal % 256), + displayTime, + country, + 0, + social, + allDayHeart, + wrist, + 0, + alertTimeHour, + alertTimeMinute, + unit, + timemode + }); + + }else if(deviceType == DeviceType.MAKIBESF68){ + //Makibes doesn't support setting everything at once. + + setGender(transaction); + setAge(transaction); + setWeight(transaction); + setHeight(transaction); + setGoal(transaction); + setLanguage(transaction); + setScreenTime(transaction); + //setAlarm(transaction, t); + setUnit(transaction); + setTimeMode(transaction); } - byte unit = HPlusCoordinator.getUnit(getDevice().getAddress()); - byte timemode = HPlusCoordinator.getTimeMode((getDevice().getAddress())); - - transaction.write(ctrlCharacteristic, new byte[]{ - HPlusConstants.CMD_SET_PREFS, - gender, - age, - bodyHeight, - bodyWeight, - 0, - 0, - (byte) ((goal / 256) & 0xff), - (byte) (goal % 256), - displayTime, - country, - 0, - social, - allDayHeart, - wrist, - 0, - alertTimeHour, - alertTimeMinute, - unit, - timemode - }); setAllDayHeart(transaction); @@ -185,7 +209,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { } private HPlusSupport setLanguage(TransactionBuilder transaction) { - byte value = HPlusCoordinator.getCountry(getDevice().getAddress()); + byte value = HPlusCoordinator.getLanguage(getDevice().getAddress()); transaction.write(ctrlCharacteristic, new byte[]{ HPlusConstants.CMD_SET_LANGUAGE, value @@ -248,13 +272,20 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { transaction.write(ctrlCharacteristic, new byte[]{ HPlusConstants.CMD_SET_WEEK, - (byte) c.get(Calendar.DAY_OF_WEEK) + (byte) (c.get(Calendar.DAY_OF_WEEK) - 1) }); return this; } private HPlusSupport setSIT(TransactionBuilder transaction) { + + //Makibes F68 doesn't like this command. + //Just ignore. + if(deviceType == DeviceType.MAKIBESF68){ + return this; + } + int startTime = HPlusCoordinator.getSITStartTime(getDevice().getAddress()); int endTime = HPlusCoordinator.getSITEndTime(getDevice().getAddress()); @@ -646,8 +677,17 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { } - private void showIncomingCall(String name, String number) { + private void showIncomingCall(String name, String rawNumber) { try { + StringBuilder number = new StringBuilder(); + + //Clean up number as the device only accepts digits + for(char c : rawNumber.toCharArray()){ + if(Character.isDigit(c)){ + number.append(c); + } + } + TransactionBuilder builder = performInitialized("incomingCall"); //Enable call notifications diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java index 0fbd5451..9e2ebb41 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -23,6 +23,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.hplus.MakibesF68Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; @@ -172,6 +173,8 @@ public class DeviceHelper { result.add(new VibratissimoCoordinator()); result.add(new LiveviewCoordinator()); result.add(new HPlusCoordinator()); + result.add(new MakibesF68Coordinator()); + return result; }