Merge branch 'master' into feature-calendarsync

master
Andreas Shimokawa 2017-04-19 20:19:15 +02:00
commit a28d27839f
13 changed files with 328 additions and 79 deletions

View File

@ -251,6 +251,7 @@
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service android:name=".service.NotificationCollectorMonitorService" />
<service android:name=".service.DeviceCommunicationService" />
<receiver

View File

@ -53,6 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.service.NotificationCollectorMonitorService;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
@ -146,6 +147,8 @@ public class GBApplication extends Application {
if (isRunningMarshmallowOrLater()) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//the following will ensure the notification manager is kept alive
startService(new Intent(this, NotificationCollectorMonitorService.class));
}
}

View File

@ -584,7 +584,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
startActivity(intent);
} else {
GBDevice device = DeviceHelper.getInstance().toSupportedDevice(deviceCandidate);
int bondingStyle = coordinator.getBondingStyle(deviceCandidate);
int bondingStyle = coordinator.getBondingStyle(device);
if (bondingStyle == DeviceCoordinator.BONDING_STYLE_NONE) {
LOG.info("No bonding needed, according to coordinator, so connecting right away");
connectAndFinish(device);

View File

@ -121,7 +121,7 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
}
@Override
public int getBondingStyle(GBDeviceCandidate deviceCandidate) {
public int getBondingStyle(GBDevice device) {
return BONDING_STYLE_ASK;
}
}

View File

@ -23,7 +23,6 @@ import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -225,7 +224,7 @@ public interface DeviceCoordinator {
/**
* Returns how/if the given device should be bonded before connecting to it.
* @param deviceCandidate
* @param device
*/
int getBondingStyle(GBDeviceCandidate deviceCandidate);
int getBondingStyle(GBDevice device);
}

View File

@ -80,6 +80,11 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator {
return DeviceType.UNKNOWN;
}
@Override
public int getBondingStyle(GBDevice deviceCandidate){
return BONDING_STYLE_NONE;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.HPLUS;

View File

@ -0,0 +1,73 @@
/* Copyright (C) 2015-2017 João Paulo Barraca
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.externalevents;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
/**
* Created by jpbarraca on 13/04/2017.
*/
public class BluetoothPairingRequestReceiver extends BroadcastReceiver {
private static final Logger LOG = LoggerFactory.getLogger(BluetoothConnectReceiver.class);
final DeviceCommunicationService service;
public BluetoothPairingRequestReceiver(DeviceCommunicationService service) {
this.service = service;
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
return;
}
GBDevice gbDevice = service.getGBDevice();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (gbDevice == null || device == null)
return;
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
try {
if (coordinator.getBondingStyle(gbDevice) == DeviceCoordinator.BONDING_STYLE_NONE) {
LOG.info("Aborting unwanted pairing request");
abortBroadcast();
}
} catch (Exception e) {
LOG.warn("Could not abort pairing request process");
}
}
}

View File

@ -45,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothPairingRequestReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.PebbleReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.PhoneCallReceiver;
@ -165,6 +166,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
private MusicPlaybackReceiver mMusicPlaybackReceiver = null;
private TimeChangeReceiver mTimeChangeReceiver = null;
private BluetoothConnectReceiver mBlueToothConnectReceiver = null;
private BluetoothPairingRequestReceiver mBlueToothPairingRequestReceiver = null;
private AlarmClockReceiver mAlarmClockReceiver = null;
private AlarmReceiver mAlarmReceiver = null;
@ -625,6 +627,11 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
mBlueToothConnectReceiver = new BluetoothConnectReceiver(this);
registerReceiver(mBlueToothConnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
}
if (mBlueToothPairingRequestReceiver == null) {
mBlueToothPairingRequestReceiver = new BluetoothPairingRequestReceiver(this);
registerReceiver(mBlueToothPairingRequestReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));
}
if (mAlarmReceiver == null) {
mAlarmReceiver = new AlarmReceiver();
registerReceiver(mAlarmReceiver, new IntentFilter("DAILY_ALARM"));
@ -661,6 +668,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
unregisterReceiver(mBlueToothConnectReceiver);
mBlueToothConnectReceiver = null;
}
if (mBlueToothPairingRequestReceiver != null) {
unregisterReceiver(mBlueToothPairingRequestReceiver);
mBlueToothPairingRequestReceiver = null;
}
if (mAlarmReceiver != null) {
unregisterReceiver(mAlarmReceiver);
mAlarmReceiver = null;

View File

@ -0,0 +1,79 @@
package nodomain.freeyourgadget.gadgetbridge.service;
import android.app.ActivityManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.Process;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
/**
* Original source by xinghui - see https://gist.github.com/xinghui/b2ddd8cffe55c4b62f5d8846d5545bf9
* NB: no license specified in the source code as of 2017-04-19
*/
public class NotificationCollectorMonitorService extends Service {
private static final Logger LOG = LoggerFactory.getLogger(NotificationCollectorMonitorService.class);
@Override
public void onCreate() {
super.onCreate();
ensureCollectorRunning();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
private void ensureCollectorRunning() {
ComponentName collectorComponent = new ComponentName(this, NotificationListener.class);
LOG.info("ensureCollectorRunning collectorComponent: " + collectorComponent);
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean collectorRunning = false;
List<ActivityManager.RunningServiceInfo> runningServices = manager.getRunningServices(Integer.MAX_VALUE);
if (runningServices == null) {
LOG.info("ensureCollectorRunning() runningServices is NULL");
return;
}
for (ActivityManager.RunningServiceInfo service : runningServices) {
if (service.service.equals(collectorComponent)) {
LOG.warn("ensureCollectorRunning service - pid: " + service.pid + ", currentPID: " + Process.myPid() + ", clientPackage: " + service.clientPackage + ", clientCount: " + service.clientCount
+ ", clientLabel: " + ((service.clientLabel == 0) ? "0" : "(" + getResources().getString(service.clientLabel) + ")"));
if (service.pid == Process.myPid() /*&& service.clientCount > 0 && !TextUtils.isEmpty(service.clientPackage)*/) {
collectorRunning = true;
}
}
}
if (collectorRunning) {
LOG.debug("ensureCollectorRunning: collector is running");
return;
}
LOG.debug("ensureCollectorRunning: collector not running, reviving...");
toggleNotificationListenerService();
}
private void toggleNotificationListenerService() {
LOG.debug("toggleNotificationListenerService() called");
ComponentName thisComponent = new ComponentName(this, NotificationListener.class);
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(thisComponent, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(thisComponent, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@ -101,6 +101,7 @@ public class BleNamesResolver {
mServices.put("00001804-0000-1000-8000-00805f9b34fb", "Tx Power");
mServices.put("0000fee0-0000-3512-2118-0009af100700", "(Propr: Xiaomi MiLi Service)");
mServices.put("00001530-0000-3512-2118-0009af100700", "(Propr: Xiaomi Weight Service)");
mServices.put("14701820-620a-3973-7c78-9cfff0876abd", "(Propr: HPLUS Service)");
mCharacteristics.put("00002a43-0000-1000-8000-00805f9b34fb", "Alert AlertCategory ID");
@ -185,6 +186,8 @@ public class BleNamesResolver {
mCharacteristics.put("00002a07-0000-1000-8000-00805f9b34fb", "Tx Power Level");
mCharacteristics.put("00002a45-0000-1000-8000-00805f9b34fb", "Unread Alert Status");
mCharacteristics.put("14702856-620a-3973-7c78-9cfff0876abd", "(Propr: HPLUS Control)");
mCharacteristics.put("14702853-620a-3973-7c78-9cfff0876abd", "(Propr: HPLUS Measurements)");
mValueFormats.put(Integer.valueOf(52), "32bit float");
mValueFormats.put(Integer.valueOf(50), "16bit float");
mValueFormats.put(Integer.valueOf(34), "16bit signed int");

View File

@ -102,4 +102,8 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
secondsInactive += other.secondsInactive;
}
public boolean isValid(){
return steps != 0 || secondsInactive != 0 || heartRate != -1;
}
}

View File

@ -65,6 +65,8 @@ class HPlusHandlerThread extends GBDeviceIoThread {
private int DAY_SUMMARY_SYNC_PERIOD = 24 * 60 * 60;
private int DAY_SUMMARY_SYNC_RETRY_PERIOD = 30;
private int HELLO_PERIOD = 60;
private boolean mQuit = false;
private HPlusSupport mHPlusSupport;
@ -76,6 +78,8 @@ class HPlusHandlerThread extends GBDeviceIoThread {
private Calendar mGetSleepTime = GregorianCalendar.getInstance();
private Calendar mGetDaySummaryTime = GregorianCalendar.getInstance();
private Calendar mHelloTime = GregorianCalendar.getInstance();
private boolean mSlotsInitialSync = true;
private HPlusDataRecordRealtime prevRealTimeRecord = null;
@ -88,7 +92,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
public HPlusHandlerThread(GBDevice gbDevice, Context context, HPlusSupport hplusSupport) {
super(gbDevice, context);
LOG.info("Initializing HPlus Handler Thread");
mQuit = false;
mHPlusSupport = hplusSupport;
@ -137,6 +141,10 @@ class HPlusHandlerThread extends GBDeviceIoThread {
requestDaySummaryData();
}
if(now.compareTo(mHelloTime) > 0){
sendHello();
}
now = GregorianCalendar.getInstance();
waitTime = Math.min(mGetDaySummaryTime.getTimeInMillis(), Math.min(mGetDaySlotsTime.getTimeInMillis(), mGetSleepTime.getTimeInMillis())) - now.getTimeInMillis();
}
@ -152,10 +160,14 @@ class HPlusHandlerThread extends GBDeviceIoThread {
}
public void sync() {
LOG.info("HPlus: Starting data synchronization");
mGetSleepTime.setTimeInMillis(0);
mGetDaySlotsTime.setTimeInMillis(0);
mGetDaySummaryTime.setTimeInMillis(0);
mLastSleepDayReceived.setTimeInMillis(0);
mHelloTime = GregorianCalendar.getInstance();
mHelloTime.add(Calendar.SECOND, HELLO_PERIOD);
mSlotsInitialSync = true;
mLastSlotReceived = -1;
@ -163,19 +175,41 @@ class HPlusHandlerThread extends GBDeviceIoThread {
mCurrentDaySlot = null;
mDaySlotRecords.clear();
TransactionBuilder builder = new TransactionBuilder("startSyncDayStats");
try {
if(!mHPlusSupport.isConnected())
mHPlusSupport.connect();
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DEVICE_ID});
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_VERSION});
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_CURR_DATA});
TransactionBuilder builder = new TransactionBuilder("startSyncDayStats");
builder.queue(mHPlusSupport.getQueue());
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DEVICE_ID});
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_VERSION});
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_CURR_DATA});
builder.queue(mHPlusSupport.getQueue());
}catch(Exception e){
}
synchronized (waitObject) {
waitObject.notify();
}
}
public void sendHello(){
try {
if(!mHPlusSupport.isConnected())
mHPlusSupport.connect();
TransactionBuilder builder = new TransactionBuilder("hello");
builder.write(mHPlusSupport.ctrlCharacteristic, HPlusConstants.CMD_ACTION_HELLO);
builder.queue(mHPlusSupport.getQueue());
}catch(Exception e){
}
mHelloTime = GregorianCalendar.getInstance();
mHelloTime.add(Calendar.SECOND, HELLO_PERIOD);
}
/**
* Process a message containing information regarding a day slot
* A slot summarizes 10 minutes of data
@ -190,7 +224,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
try{
record = new HPlusDataRecordDaySlot(data);
} catch(IllegalArgumentException e){
LOG.debug((e.getMessage()));
LOG.info((e.getMessage()));
return false;
}
@ -254,6 +288,11 @@ class HPlusHandlerThread extends GBDeviceIoThread {
List<HPlusHealthActivitySample> samples = new ArrayList<>();
for (HPlusDataRecordDaySlot storedRecord : mDaySlotRecords) {
//Invalid records (no data) will be ignored
if(!storedRecord.isValid())
continue;
HPlusHealthActivitySample sample = createSample(dbHandler, storedRecord.timestamp);
sample.setRawHPlusHealthData(storedRecord.getRawData());
@ -269,9 +308,9 @@ class HPlusHandlerThread extends GBDeviceIoThread {
mDaySlotRecords.clear();
} catch (GBException ex) {
LOG.debug((ex.getMessage()));
LOG.info((ex.getMessage()));
} catch (Exception ex) {
LOG.debug(ex.getMessage());
LOG.info(ex.getMessage());
}
}
@ -293,7 +332,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
try{
record = new HPlusDataRecordSleep(data);
} catch(IllegalArgumentException e){
LOG.debug((e.getMessage()));
LOG.info((e.getMessage()));
return false;
}
@ -326,7 +365,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
provider.addGBActivitySample(sample);
} catch (Exception ex) {
LOG.debug(ex.getMessage());
LOG.info(ex.getMessage());
}
mGetSleepTime = GregorianCalendar.getInstance();
@ -347,7 +386,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
try{
record = new HPlusDataRecordRealtime(data);
} catch(IllegalArgumentException e){
LOG.debug((e.getMessage()));
LOG.info((e.getMessage()));
return false;
}
@ -397,9 +436,9 @@ class HPlusHandlerThread extends GBDeviceIoThread {
//TODO: Handle Active Time. With Overlay?
} catch (GBException ex) {
LOG.debug((ex.getMessage()));
LOG.info((ex.getMessage()));
} catch (Exception ex) {
LOG.debug(ex.getMessage());
LOG.info(ex.getMessage());
}
return true;
}
@ -417,7 +456,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
try{
record = new HPlusDataRecordDaySummary(data);
} catch(IllegalArgumentException e){
LOG.debug((e.getMessage()));
LOG.info((e.getMessage()));
return false;
}
@ -437,9 +476,9 @@ class HPlusHandlerThread extends GBDeviceIoThread {
sample.setProvider(provider);
provider.addGBActivitySample(sample);
} catch (GBException ex) {
LOG.debug((ex.getMessage()));
LOG.info((ex.getMessage()));
} catch (Exception ex) {
LOG.debug(ex.getMessage());
LOG.info(ex.getMessage());
}
mGetDaySummaryTime = GregorianCalendar.getInstance();
@ -468,10 +507,16 @@ class HPlusHandlerThread extends GBDeviceIoThread {
* Issue a message requesting the next batch of sleep data
*/
private void requestNextSleepData() {
TransactionBuilder builder = new TransactionBuilder("requestSleepStats");
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_SLEEP});
builder.queue(mHPlusSupport.getQueue());
try {
if(!mHPlusSupport.isConnected())
mHPlusSupport.connect();
TransactionBuilder builder = new TransactionBuilder("requestSleepStats");
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_SLEEP});
builder.queue(mHPlusSupport.getQueue());
}catch(Exception e){
}
mGetSleepTime = GregorianCalendar.getInstance();
mGetSleepTime.add(GregorianCalendar.SECOND, SLEEP_SYNC_RETRY_PERIOD);
@ -519,19 +564,31 @@ class HPlusHandlerThread extends GBDeviceIoThread {
mLastSlotRequested = nextHour * 6 + (nextMinute / 10);
byte[] msg = new byte[]{HPlusConstants.CMD_GET_ACTIVE_DAY, hour, minute, nextHour, nextMinute};
try {
if(!mHPlusSupport.isConnected())
mHPlusSupport.connect();
TransactionBuilder builder = new TransactionBuilder("getNextDaySlot");
builder.write(mHPlusSupport.ctrlCharacteristic, msg);
builder.queue(mHPlusSupport.getQueue());
TransactionBuilder builder = new TransactionBuilder("getNextDaySlot");
builder.write(mHPlusSupport.ctrlCharacteristic, msg);
builder.queue(mHPlusSupport.getQueue());
}catch(Exception e){
}
}
/**
* Request a batch of data with the summary of the previous days
*/
public void requestDaySummaryData(){
TransactionBuilder builder = new TransactionBuilder("startSyncDaySummary");
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DAY_DATA});
builder.queue(mHPlusSupport.getQueue());
try {
if(!mHPlusSupport.isConnected())
mHPlusSupport.connect();
TransactionBuilder builder = new TransactionBuilder("startSyncDaySummary");
builder.write(mHPlusSupport.ctrlCharacteristic, new byte[]{HPlusConstants.CMD_GET_DAY_DATA});
builder.queue(mHPlusSupport.getQueue());
}catch(Exception e){
}
mGetDaySummaryTime = GregorianCalendar.getInstance();
mGetDaySummaryTime.add(Calendar.SECOND, DAY_SUMMARY_SYNC_RETRY_PERIOD);
}

View File

@ -94,8 +94,6 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
deviceType = type;
addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS);
addSupportedService(GattService.UUID_SERVICE_GENERIC_ATTRIBUTE);
addSupportedService(HPlusConstants.UUID_SERVICE_HP);
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext());
@ -106,7 +104,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void dispose() {
LOG.debug("Dispose");
LOG.info("Dispose");
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext());
broadcastManager.unregisterReceiver(mReceiver);
@ -117,7 +115,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
LOG.debug("Initializing");
LOG.info("Initializing");
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
@ -424,7 +422,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void onNotification(NotificationSpec notificationSpec) {
//TODO: Show different notifications according to source as Band supports this
//LOG.debug("OnNotification: Title: "+notificationSpec.title+" Body: "+notificationSpec.body+" Source: "+notificationSpec.sourceName+" Sender: "+notificationSpec.sender+" Subject: "+notificationSpec.subject);
//LOG.info("OnNotification: Title: "+notificationSpec.title+" Body: "+notificationSpec.body+" Source: "+notificationSpec.sourceName+" Sender: "+notificationSpec.sender+" Subject: "+notificationSpec.subject);
showText(notificationSpec.title, notificationSpec.body);
}
@ -435,40 +433,46 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void onSetTime() {
TransactionBuilder builder = new TransactionBuilder("time");
try {
TransactionBuilder builder = performInitialized("time");
setCurrentDate(builder);
setCurrentTime(builder);
setCurrentDate(builder);
setCurrentTime(builder);
builder.queue(getQueue());
builder.queue(getQueue());
}catch(IOException e){
}
}
@Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
try {
TransactionBuilder builder = performInitialized("alarm");
TransactionBuilder builder = new TransactionBuilder("alarm");
for (Alarm alarm : alarms) {
for (Alarm alarm : alarms) {
if (!alarm.isEnabled())
continue;
if (!alarm.isEnabled())
continue;
if (alarm.isSmartWakeup()) //Not available
continue;
if (alarm.isSmartWakeup()) //Not available
continue;
Calendar t = alarm.getAlarmCal();
setAlarm(builder, t);
builder.queue(getQueue());
Calendar t = alarm.getAlarmCal();
setAlarm(builder, t);
GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO);
return; //Only first alarm
}
setAlarm(builder, null);
builder.queue(getQueue());
GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO);
GB.toast(getContext(), getContext().getString(R.string.user_feedback_all_alarms_disabled), Toast.LENGTH_SHORT, GB.INFO);
}catch(Exception e){}
return; //Only first alarm
}
setAlarm(builder, null);
builder.queue(getQueue());
GB.toast(getContext(), getContext().getString(R.string.user_feedback_all_alarms_disabled), Toast.LENGTH_SHORT, GB.INFO);
}
@ -485,7 +489,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
LOG.debug("Canned Messages: " + cannedMessagesSpec);
LOG.info("Canned Messages: " + cannedMessagesSpec);
}
@Override
@ -541,39 +545,47 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void onReboot() {
getQueue().clear();
try {
getQueue().clear();
TransactionBuilder builder = new TransactionBuilder("Shutdown");
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SHUTDOWN, HPlusConstants.ARG_SHUTDOWN_EN});
builder.queue(getQueue());
TransactionBuilder builder = performInitialized("Shutdown");
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SHUTDOWN, HPlusConstants.ARG_SHUTDOWN_EN});
builder.queue(getQueue());
}catch(Exception e){
}
}
@Override
public void onHeartRateTest() {
getQueue().clear();
try{
TransactionBuilder builder = performInitialized("HeartRateTest");
TransactionBuilder builder = new TransactionBuilder("HeartRateTest");
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SET_HEARTRATE_STATE, HPlusConstants.ARG_HEARTRATE_MEASURE_ON}); //Set Real Time... ?
builder.queue(getQueue());
}catch(Exception e){
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SET_HEARTRATE_STATE, HPlusConstants.ARG_HEARTRATE_MEASURE_ON}); //Set Real Time... ?
builder.queue(getQueue());
}
}
@Override
public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
getQueue().clear();
try {
TransactionBuilder builder = performInitialized("realTimeHeartMeasurement");
byte state;
TransactionBuilder builder = new TransactionBuilder("realTimeHeartMeasurement");
byte state;
if (enable)
state = HPlusConstants.ARG_HEARTRATE_ALLDAY_ON;
else
state = HPlusConstants.ARG_HEARTRATE_ALLDAY_OFF;
if (enable)
state = HPlusConstants.ARG_HEARTRATE_ALLDAY_ON;
else
state = HPlusConstants.ARG_HEARTRATE_ALLDAY_OFF;
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SET_ALLDAY_HRM, state});
builder.queue(getQueue());
builder.write(ctrlCharacteristic, new byte[]{HPlusConstants.CMD_SET_ALLDAY_HRM, state});
builder.queue(getQueue());
}catch(Exception e){
}
}
@Override
@ -632,13 +644,13 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
@Override
public void onSendConfiguration(String config) {
LOG.debug("Send Configuration: " + config);
LOG.info("Send Configuration: " + config);
}
@Override
public void onTestNewFunction() {
LOG.debug("Test New Function");
LOG.info("Test New Function");
}
@Override
@ -706,7 +718,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
private void showText(String title, String body) {
LOG.debug("Show Notification: " + title + " --> " + body);
try {
TransactionBuilder builder = performInitialized("notification");
@ -844,7 +856,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
return syncHelper.processIncomingDaySlotData(data);
default:
LOG.debug("Unhandled characteristic changed: " + characteristicUUID);
LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + data[0]);
return true;
}
}
@ -858,7 +870,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
String DEVINFO_STEP = getContext().getString(R.string.chart_steps) + ": ";
String DEVINFO_DISTANCE = getContext().getString(R.string.distance) + ": ";
String DEVINFO_CALORY = getContext().getString(R.string.calories) + ": ";
String DEVINFO_HEART = "HR: ";
String DEVINFO_HEART = getContext().getString(R.string.charts_legend_heartrate);
String info = "";
if (record.steps > 0) {
@ -878,7 +890,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
getDevice().addDeviceInfo(new GenericItem("", info));
}
} catch (IllegalArgumentException e) {
LOG.debug((e.getMessage()));
LOG.info((e.getMessage()));
}
}