mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-25 11:26:47 +01:00
Adding support for battery events using GBDeviceEvent.
- show notification on low battery (closes #40) - Miband specific: add date of last charge and number of charges
This commit is contained in:
parent
121baa19ec
commit
c3e395818f
@ -15,6 +15,7 @@ public abstract class GBDeviceEvent {
|
|||||||
SLEEP_MONITOR_RES,
|
SLEEP_MONITOR_RES,
|
||||||
SCREENSHOT,
|
SCREENSHOT,
|
||||||
DISMISS_NOTIFICATION,
|
DISMISS_NOTIFICATION,
|
||||||
|
BATTERY_INFO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
public class GBDeviceEventBatteryInfo extends GBDeviceEvent {
|
||||||
|
public GregorianCalendar lastChargeTime;
|
||||||
|
public BatteryState state = BatteryState.UNKNOWN;
|
||||||
|
//TODO: I think the string should be deprecated in favor of the Enum above
|
||||||
|
public String status;
|
||||||
|
public short level = 50;
|
||||||
|
public int numCharges = -1;
|
||||||
|
|
||||||
|
public GBDeviceEventBatteryInfo() {
|
||||||
|
eventClass = EventClass.BATTERY_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BatteryState {
|
||||||
|
UNKNOWN,
|
||||||
|
CHARGE_FULL,
|
||||||
|
CHARGE_MEDIUM,
|
||||||
|
CHARGE_LOW,
|
||||||
|
CHARGING,
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,8 @@ public class GBDevice implements Parcelable {
|
|||||||
private String mHardwareVersion = null;
|
private String mHardwareVersion = null;
|
||||||
private State mState = State.NOT_CONNECTED;
|
private State mState = State.NOT_CONNECTED;
|
||||||
private short mBatteryLevel = BATTERY_UNKNOWN;
|
private short mBatteryLevel = BATTERY_UNKNOWN;
|
||||||
private String mBatteryState;
|
//TODO: get rid of String mBatteryStatus in favor of Enum mBatteryState
|
||||||
|
private String mBatteryStatus;
|
||||||
private short mRssi = RSSI_UNKNOWN;
|
private short mRssi = RSSI_UNKNOWN;
|
||||||
private String mBusyTask;
|
private String mBusyTask;
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ public class GBDevice implements Parcelable {
|
|||||||
mHardwareVersion = in.readString();
|
mHardwareVersion = in.readString();
|
||||||
mState = State.values()[in.readInt()];
|
mState = State.values()[in.readInt()];
|
||||||
mBatteryLevel = (short) in.readInt();
|
mBatteryLevel = (short) in.readInt();
|
||||||
mBatteryState = in.readString();
|
mBatteryStatus = in.readString();
|
||||||
mRssi = (short) in.readInt();
|
mRssi = (short) in.readInt();
|
||||||
mBusyTask = in.readString();
|
mBusyTask = in.readString();
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ public class GBDevice implements Parcelable {
|
|||||||
dest.writeString(mHardwareVersion);
|
dest.writeString(mHardwareVersion);
|
||||||
dest.writeInt(mState.ordinal());
|
dest.writeInt(mState.ordinal());
|
||||||
dest.writeInt(mBatteryLevel);
|
dest.writeInt(mBatteryLevel);
|
||||||
dest.writeString(mBatteryState);
|
dest.writeString(mBatteryStatus);
|
||||||
dest.writeInt(mRssi);
|
dest.writeInt(mRssi);
|
||||||
dest.writeString(mBusyTask);
|
dest.writeString(mBusyTask);
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@ public class GBDevice implements Parcelable {
|
|||||||
|
|
||||||
private void unsetDynamicState() {
|
private void unsetDynamicState() {
|
||||||
setBatteryLevel(BATTERY_UNKNOWN);
|
setBatteryLevel(BATTERY_UNKNOWN);
|
||||||
setBatteryState(null);
|
setBatteryStatus(null);
|
||||||
setFirmwareVersion(null);
|
setFirmwareVersion(null);
|
||||||
setRssi(RSSI_UNKNOWN);
|
setRssi(RSSI_UNKNOWN);
|
||||||
if (mBusyTask != null) {
|
if (mBusyTask != null) {
|
||||||
@ -284,12 +285,12 @@ public class GBDevice implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* Returns a string representation of the battery state.
|
* Returns a string representation of the battery state.
|
||||||
*/
|
*/
|
||||||
public String getBatteryState() {
|
public String getBatteryStatus() {
|
||||||
return mBatteryState != null ? mBatteryState : GBApplication.getContext().getString(R.string._unknown_);
|
return mBatteryStatus != null ? mBatteryStatus : GBApplication.getContext().getString(R.string._unknown_);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBatteryState(String batteryState) {
|
public void setBatteryStatus(String batteryStatus) {
|
||||||
mBatteryState = batteryState;
|
mBatteryStatus = batteryStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,17 +15,18 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.AppManagerActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.AppManagerActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsHost;
|
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsHost;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
|
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
|
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.AbstractChartFragment;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
||||||
@ -111,6 +112,9 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
|||||||
case DISMISS_NOTIFICATION:
|
case DISMISS_NOTIFICATION:
|
||||||
handleGBDeviceEvent((GBDeviceEventDismissNotification) deviceEvent);
|
handleGBDeviceEvent((GBDeviceEventDismissNotification) deviceEvent);
|
||||||
break;
|
break;
|
||||||
|
case BATTERY_INFO:
|
||||||
|
handleGBDeviceEvent((GBDeviceEventBatteryInfo) deviceEvent);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -219,4 +223,23 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
|||||||
notificationListenerIntent.putExtra("id", deviceEvent.notificationID);
|
notificationListenerIntent.putExtra("id", deviceEvent.notificationID);
|
||||||
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationListenerIntent);
|
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationListenerIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handleGBDeviceEvent(GBDeviceEventBatteryInfo deviceEvent) {
|
||||||
|
Context context = getContext();
|
||||||
|
LOG.info("Got BATTERY_INFO device event");
|
||||||
|
gbDevice.setBatteryLevel(deviceEvent.level);
|
||||||
|
gbDevice.setBatteryStatus(deviceEvent.status);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: maybe switch to a device-dependent threshold
|
||||||
|
if (deviceEvent.level < 10) {
|
||||||
|
GB.updateBatteryNotification(deviceEvent.level,
|
||||||
|
context.getString(R.string.notif_battery_low_bigtext_last_charge_time, DateFormat.getDateTimeInstance().format(deviceEvent.lastChargeTime.getTime()).toString()) +
|
||||||
|
context.getString(R.string.notif_battery_low_bigtext_number_of_charges, deviceEvent.numCharges)
|
||||||
|
, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
gbDevice.sendDeviceUpdateIntent(context);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.miband;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.miband;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
@ -31,4 +34,27 @@ public class BatteryInfo extends AbstractInfo {
|
|||||||
}
|
}
|
||||||
return GBApplication.getContext().getString(R.string._unknown_);
|
return GBApplication.getContext().getString(R.string._unknown_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GregorianCalendar getLastChargeTime() {
|
||||||
|
GregorianCalendar lastCharge = new GregorianCalendar();
|
||||||
|
|
||||||
|
if (mData.length >= 10) {
|
||||||
|
lastCharge.set(Calendar.YEAR, (2000 + mData[1]));
|
||||||
|
lastCharge.set(Calendar.MONTH, mData[2]);
|
||||||
|
lastCharge.set(Calendar.DATE, mData[3]);
|
||||||
|
lastCharge.set(Calendar.HOUR_OF_DAY, mData[4]);
|
||||||
|
lastCharge.set(Calendar.MINUTE, mData[5]);
|
||||||
|
lastCharge.set(Calendar.SECOND, mData[6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumCharges() {
|
||||||
|
if (mData.length >= 10) {
|
||||||
|
return ((0xff & mData[7]) | ((0xff & mData[8]) << 8));
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import java.util.GregorianCalendar;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
|
||||||
@ -66,6 +67,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
private DeviceInfo mDeviceInfo;
|
private DeviceInfo mDeviceInfo;
|
||||||
|
|
||||||
GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
|
GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
|
||||||
|
GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo();
|
||||||
|
|
||||||
public MiBandSupport() {
|
public MiBandSupport() {
|
||||||
addSupportedService(MiBandService.UUID_SERVICE_MIBAND_SERVICE);
|
addSupportedService(MiBandService.UUID_SERVICE_MIBAND_SERVICE);
|
||||||
@ -261,6 +263,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of device initialization process. Do not call manually.
|
* Part of device initialization process. Do not call manually.
|
||||||
*
|
*
|
||||||
@ -276,7 +279,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
transaction.write(characteristic, new byte[]{
|
transaction.write(characteristic, new byte[]{
|
||||||
MiBandService.COMMAND_SET_FITNESS_GOAL,
|
MiBandService.COMMAND_SET_FITNESS_GOAL,
|
||||||
0,
|
0,
|
||||||
(byte) (fitnessGoal & 0xff),
|
(byte) (fitnessGoal & 0xff),
|
||||||
(byte) ((fitnessGoal >>> 8) & 0xff)
|
(byte) ((fitnessGoal >>> 8) & 0xff)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -637,6 +640,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method that may be used to log incoming messages when we don't know how to deal with them yet.
|
* Utility method that may be used to log incoming messages when we don't know how to deal with them yet.
|
||||||
|
*
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
private void logMessageContent(byte[] value) {
|
private void logMessageContent(byte[] value) {
|
||||||
@ -651,13 +655,13 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
* characteristic,
|
* characteristic,
|
||||||
* These messages appear to be always 1 byte long, with values that are listed in MiBandService.
|
* These messages appear to be always 1 byte long, with values that are listed in MiBandService.
|
||||||
* It is not excluded that there are further values which are still unknown.
|
* It is not excluded that there are further values which are still unknown.
|
||||||
*
|
* <p/>
|
||||||
* Upon receiving known values that request further action by GB, the appropriate method is called.
|
* Upon receiving known values that request further action by GB, the appropriate method is called.
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
private void handleNotificationNotif(byte[] value) {
|
private void handleNotificationNotif(byte[] value) {
|
||||||
if(value.length != 1) {
|
if (value.length != 1) {
|
||||||
LOG.error("Notifications should be 1 byte long.");
|
LOG.error("Notifications should be 1 byte long.");
|
||||||
LOG.info("RECEIVED DATA WITH LENGTH: " + value.length);
|
LOG.info("RECEIVED DATA WITH LENGTH: " + value.length);
|
||||||
for (byte b : value) {
|
for (byte b : value) {
|
||||||
@ -732,9 +736,10 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
private void handleBatteryInfo(byte[] value, int status) {
|
private void handleBatteryInfo(byte[] value, int status) {
|
||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
BatteryInfo info = new BatteryInfo(value);
|
BatteryInfo info = new BatteryInfo(value);
|
||||||
getDevice().setBatteryLevel((short) info.getLevelInPercent());
|
batteryCmd.level = ((short) info.getLevelInPercent());
|
||||||
getDevice().setBatteryState(info.getStatus());
|
batteryCmd.lastChargeTime = info.getLastChargeTime();
|
||||||
getDevice().sendDeviceUpdateIntent(getContext());
|
batteryCmd.numCharges = info.getNumCharges();
|
||||||
|
handleGBDeviceEvent(batteryCmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.externalevents.TimeChangeReceiver;
|
|||||||
public class GB {
|
public class GB {
|
||||||
public static final int NOTIFICATION_ID = 1;
|
public static final int NOTIFICATION_ID = 1;
|
||||||
public static final int NOTIFICATION_ID_INSTALL = 2;
|
public static final int NOTIFICATION_ID_INSTALL = 2;
|
||||||
|
public static final int NOTIFICATION_ID_LOW_BATTERY = 3;
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(GB.class);
|
private static final Logger LOG = LoggerFactory.getLogger(GB.class);
|
||||||
public static final int INFO = 1;
|
public static final int INFO = 1;
|
||||||
@ -298,4 +299,29 @@ public class GB {
|
|||||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
nm.notify(NOTIFICATION_ID_INSTALL, notification);
|
nm.notify(NOTIFICATION_ID_INSTALL, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Notification createBatteryNotification(int level, String text, Context context) {
|
||||||
|
Intent notificationIntent = new Intent(context, ControlCenter.class);
|
||||||
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
|
||||||
|
notificationIntent, 0);
|
||||||
|
|
||||||
|
NotificationCompat.Builder nb = new NotificationCompat.Builder(context)
|
||||||
|
.setContentTitle(context.getString(R.string.notif_battery_low_title))
|
||||||
|
.setContentText(context.getString(R.string.notif_battery_low_percent, level))
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setStyle(new NotificationCompat.BigTextStyle().bigText(text))
|
||||||
|
.setOngoing(false);
|
||||||
|
|
||||||
|
return nb.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateBatteryNotification(int level, String text, Context context) {
|
||||||
|
Notification notification = createBatteryNotification(level, text, context);
|
||||||
|
|
||||||
|
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
nm.notify(NOTIFICATION_ID_LOW_BATTERY, notification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,4 +166,8 @@
|
|||||||
<string name="pbw_install_handler_unable_to_install">Unable to install the given file: $1%s</string>
|
<string name="pbw_install_handler_unable_to_install">Unable to install the given file: $1%s</string>
|
||||||
<string name="pbw_install_handler_hw_revision_mismatch">Unable to install the given firmware: it doesn\'t match your Pebble\'s hardware revision.</string>
|
<string name="pbw_install_handler_hw_revision_mismatch">Unable to install the given firmware: it doesn\'t match your Pebble\'s hardware revision.</string>
|
||||||
<string name="installer_activity_wait_while_determining_status">Please wait while determining the installation status...</string>
|
<string name="installer_activity_wait_while_determining_status">Please wait while determining the installation status...</string>
|
||||||
|
<string name="notif_battery_low_title">Gadget battery Low!</string>
|
||||||
|
<string name="notif_battery_low_percent">Battery left: %s%%</string>
|
||||||
|
<string name="notif_battery_low_bigtext_last_charge_time">Last charge: %s \n</string>
|
||||||
|
<string name="notif_battery_low_bigtext_number_of_charges">Number of charges: %s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user