Merge pull request #523 from jpbarraca/Makibes-F68

HPlus: Support for Makibes F68
here
Andreas Shimokawa 2017-01-26 16:07:26 +01:00 committed by GitHub
commit 896eb19b3e
11 changed files with 232 additions and 153 deletions

View File

@ -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<Character, Byte> transliterateMap = new HashMap<Character, Byte>(){
{

View File

@ -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);
}

View File

@ -141,30 +141,46 @@ public class HPlusHealthSampleProvider extends AbstractSampleProvider<HPlusHealt
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
int stepsToday = 0;
int stepsTodayMax = 0;
int stepsTodayCount = 0;
HPlusHealthActivitySample lastSample = null;
for(HPlusHealthActivitySample sample: samples){
if(sample.getTimestamp() >= 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<HPlusHealt
userId, // User id
null, // Raw Data
ActivityKind.TYPE_UNKNOWN,
0, // Intensity
1, // Intensity
ActivitySample.NOT_MEASURED, // Steps
ActivitySample.NOT_MEASURED, // HR
ActivitySample.NOT_MEASURED, // Distance

View File

@ -0,0 +1,33 @@
package nodomain.freeyourgadget.gadgetbridge.devices.hplus;
/*
* @author João Paulo Barraca &lt;jpbarraca@gmail.com&gt;
*/
import android.support.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
/**
* Pseudo Coordinator for the Makibes F68, a sub type of the HPLUS devices
*/
public class MakibesF68Coordinator extends HPlusCoordinator {
@NonNull
@Override
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
String name = candidate.getDevice().getName();
if(name != null && name.startsWith("SPORT")){
return DeviceType.MAKIBESF68;
}
return DeviceType.UNKNOWN;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.MAKIBESF68;
}
}

View File

@ -14,6 +14,7 @@ public enum DeviceType {
VIBRATISSIMO(20),
LIVEVIEW(30),
HPLUS(40),
MAKIBESF68(50),
TEST(1000);
private final int key;

View File

@ -10,6 +10,7 @@ import java.util.EnumSet;
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.liveview.LiveviewSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
@ -98,7 +99,10 @@ public class DeviceSupportFactory {
deviceSupport = new ServiceDeviceSupport(new LiveviewSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case HPLUS:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.HPLUS), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case MAKIBESF68:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.MAKIBESF68), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
}
if (deviceSupport != null) {

View File

@ -8,7 +8,7 @@ import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public class HPlusDataRecordDaySlot extends HPlusDataRecord {
@ -47,9 +47,9 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
heartRate = data[1] & 0xFF;
if(heartRate == 255 || heartRate == 0)
heartRate = ActivityKind.TYPE_NOT_MEASURED;
heartRate = ActivitySample.NOT_MEASURED;
steps = (data[2] & 0xFF) * 256 + data[3] & 0xFF;
steps = (data[2] & 0xFF) * 256 + (data[3] & 0xFF);
//?? data[6]; atemp?? always 0
secondsInactive = data[7] & 0xFF; // ?
@ -69,16 +69,21 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
return String.format(Locale.US, "Slot: %d, Time: %s, Steps: %d, InactiveSeconds: %d, HeartRate: %d", slot, slotTime.getTime(), steps, secondsInactive, heartRate);
}
public void add(HPlusDataRecordDaySlot other){
public void accumulate(HPlusDataRecordDaySlot other){
if(other == null)
return;
steps += other.steps;
secondsInactive += other.secondsInactive;
if(heartRate == -1)
if(steps == ActivitySample.NOT_MEASURED)
steps = other.steps;
else if(other.steps != ActivitySample.NOT_MEASURED)
steps += other.steps;
if(heartRate == ActivitySample.NOT_MEASURED)
heartRate = other.heartRate;
else if(other.heartRate != -1) {
else if(other.heartRate != ActivitySample.NOT_MEASURED) {
heartRate = (heartRate + other.heartRate) / 2;
}
secondsInactive += other.secondsInactive;
}
}

View File

@ -60,8 +60,8 @@ class HPlusDataRecordRealtime extends HPlusDataRecord {
timestamp = (int) (GregorianCalendar.getInstance().getTimeInMillis() / 1000);
distance = 10 * ((data[4] & 0xFF) * 256 + (data[3] & 0xFF)); // meters
steps = (data[2] & 0xFF) * 256 + (data[1] & 0xFF);
int x = (data[6] & 0xFF) * 256 + data[5] & 0xFF;
int y = (data[8] & 0xFF) * 256 + data[7] & 0xFF;
int x = (data[6] & 0xFF) * 256 + (data[5] & 0xFF);
int y = (data[8] & 0xFF) * 256 + (data[7] & 0xFF);
battery = data[9];

View File

@ -8,7 +8,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.hplus;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -19,8 +18,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
@ -52,8 +49,6 @@ class HPlusHandlerThread extends GBDeviceIoThread {
private int DAY_SUMMARY_SYNC_PERIOD = 24 * 60 * 60;
private int DAY_SUMMARY_SYNC_RETRY_PERIOD = 30;
private int HELLO_INTERVAL = 60;
private boolean mQuit = false;
private HPlusSupport mHPlusSupport;
@ -61,7 +56,6 @@ class HPlusHandlerThread extends GBDeviceIoThread {
private int mLastSlotRequested = 0;
private Calendar mLastSleepDayReceived = GregorianCalendar.getInstance();
private Calendar mHelloTime = GregorianCalendar.getInstance();
private Calendar mGetDaySlotsTime = GregorianCalendar.getInstance();
private Calendar mGetSleepTime = GregorianCalendar.getInstance();
private Calendar mGetDaySummaryTime = GregorianCalendar.getInstance();
@ -72,7 +66,9 @@ class HPlusHandlerThread extends GBDeviceIoThread {
private final Object waitObject = new Object();
List<HPlusDataRecordDaySlot> mDaySlotSamples = new ArrayList<>();
List<HPlusDataRecordDaySlot> 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<HPlusDataRecordDaySlot>() {
Collections.sort(mDaySlotRecords, new Comparator<HPlusDataRecordDaySlot>() {
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<HPlusHealthActivitySample> 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;

View File

@ -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

View File

@ -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;
}