mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 21:06:50 +01:00
Support for vibration profiles, configurable for notifications
Configurable for sms, k9, incoming calls, pebble messages, generic notifications. Color is unfortunately not configurable so far, see #37 Closes #29 Currently provided profiles are - staccato - short - medium - long - waterdrop - ring - alarm clock
This commit is contained in:
parent
f105bbbde3
commit
c7b4f295a1
@ -0,0 +1,30 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.btle;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBDevice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A special action that checks for an abort-condition, and if met, the currently
|
||||||
|
* executing transaction will be aborted by returning false.
|
||||||
|
*/
|
||||||
|
public abstract class AbortTransactionAction extends PlainAction {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbortTransactionAction.class);
|
||||||
|
|
||||||
|
public AbortTransactionAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean run(BluetoothGatt gatt) {
|
||||||
|
if (shouldAbort()) {
|
||||||
|
LOG.info("Aborting transaction because abort criteria met.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean shouldAbort();
|
||||||
|
}
|
@ -12,7 +12,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBDevice;
|
|||||||
* sequence (transaction). It will abort the entire initialization sequence
|
* sequence (transaction). It will abort the entire initialization sequence
|
||||||
* by returning false, when the device is already initialized.
|
* by returning false, when the device is already initialized.
|
||||||
*/
|
*/
|
||||||
public class CheckInitializedAction extends PlainAction {
|
public class CheckInitializedAction extends AbortTransactionAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
|
||||||
|
|
||||||
private final GBDevice device;
|
private final GBDevice device;
|
||||||
@ -22,11 +22,11 @@ public class CheckInitializedAction extends PlainAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
protected boolean shouldAbort() {
|
||||||
boolean continueWithOtherInitActions = !device.isInitialized();
|
boolean abort = device.isInitialized();
|
||||||
if (!continueWithOtherInitActions) {
|
if (abort) {
|
||||||
LOG.info("Aborting device initialization, because already initialized: " + device);
|
LOG.info("Aborting device initialization, because already initialized: " + device);
|
||||||
}
|
}
|
||||||
return continueWithOtherInitActions;
|
return abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import android.content.SharedPreferences;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
public final class MiBandConst {
|
public final class MiBandConst {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MiBandConst.class);
|
private static final Logger LOG = LoggerFactory.getLogger(MiBandConst.class);
|
||||||
|
|
||||||
@ -13,9 +15,11 @@ public final class MiBandConst {
|
|||||||
public static final String PREF_USER_GENDER = "mi_user_gender";
|
public static final String PREF_USER_GENDER = "mi_user_gender";
|
||||||
public static final String PREF_USER_HEIGHT_CM = "mi_user_height_cm";
|
public static final String PREF_USER_HEIGHT_CM = "mi_user_height_cm";
|
||||||
public static final String PREF_USER_WEIGHT_KG = "mi_user_weight_kg";
|
public static final String PREF_USER_WEIGHT_KG = "mi_user_weight_kg";
|
||||||
|
public static final String PREF_MIBAND_WEARSIDE = "mi_wearside";
|
||||||
public static final String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_
|
public static final String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_
|
||||||
|
|
||||||
public static final String ORIGIN_SMS = "sms";
|
public static final String ORIGIN_SMS = "sms";
|
||||||
|
public static final String ORIGIN_INCOMING_CALL = "incoming_call";
|
||||||
public static final String ORIGIN_K9MAIL = "k9mail";
|
public static final String ORIGIN_K9MAIL = "k9mail";
|
||||||
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
|
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
|
||||||
public static final String ORIGIN_GENERIC = "generic";
|
public static final String ORIGIN_GENERIC = "generic";
|
||||||
@ -32,10 +36,16 @@ public final class MiBandConst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getNotificationPrefStringValue(String pref, String origin, SharedPreferences prefs, String defaultValue) {
|
||||||
|
String key = getNotificationPrefKey(pref, origin);
|
||||||
|
return prefs.getString(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
public static final String getNotificationPrefKey(String pref, String origin) {
|
public static final String getNotificationPrefKey(String pref, String origin) {
|
||||||
return new StringBuilder(pref).append('_').append(origin).toString();
|
return new StringBuilder(pref).append('_').append(origin).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String VIBRATION_PROFILE = "mi_vibration_profile";
|
||||||
public static final String VIBRATION_COUNT = "mi_vibration_count";
|
public static final String VIBRATION_COUNT = "mi_vibration_count";
|
||||||
public static final String VIBRATION_DURATION = "mi_vibration_duration";
|
public static final String VIBRATION_DURATION = "mi_vibration_duration";
|
||||||
public static final String VIBRATION_PAUSE = "mi_vibration_pause";
|
public static final String VIBRATION_PAUSE = "mi_vibration_pause";
|
||||||
@ -45,7 +55,8 @@ public final class MiBandConst {
|
|||||||
public static final String FLASH_COLOUR = "mi_flash_colour";
|
public static final String FLASH_COLOUR = "mi_flash_colour";
|
||||||
public static final String FLASH_ORIGINAL_COLOUR = "mi_flash_original_colour";
|
public static final String FLASH_ORIGINAL_COLOUR = "mi_flash_original_colour";
|
||||||
|
|
||||||
public static final int DEFAULT_VALUE_VIBRATION_COUNT = 6;
|
public static final String DEFAULT_VALUE_VIBRATION_PROFILE = "short";
|
||||||
|
public static final int DEFAULT_VALUE_VIBRATION_COUNT = 3;
|
||||||
public static final int DEFAULT_VALUE_VIBRATION_DURATION = 500; // ms
|
public static final int DEFAULT_VALUE_VIBRATION_DURATION = 500; // ms
|
||||||
public static final int DEFAULT_VALUE_VIBRATION_PAUSE = 500; // ms
|
public static final int DEFAULT_VALUE_VIBRATION_PAUSE = 500; // ms
|
||||||
public static final int DEFAULT_VALUE_FLASH_COUNT = 10; // ms
|
public static final int DEFAULT_VALUE_FLASH_COUNT = 10; // ms
|
||||||
|
@ -10,16 +10,19 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
|
||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_GENERIC;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_GENERIC;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_INCOMING_CALL;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_K9MAIL;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_K9MAIL;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_PEBBLEMSG;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_PEBBLEMSG;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_SMS;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_SMS;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ADDRESS;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ADDRESS;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_WEARSIDE;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_ALIAS;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_ALIAS;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_GENDER;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_GENDER;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_HEIGHT_CM;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_HEIGHT_CM;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_WEIGHT_KG;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_WEIGHT_KG;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_YEAR_OF_BIRTH;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_USER_YEAR_OF_BIRTH;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PROFILE;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.getNotificationPrefKey;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.getNotificationPrefKey;
|
||||||
|
|
||||||
public class MiBandPreferencesActivity extends AbstractSettingsActivity {
|
public class MiBandPreferencesActivity extends AbstractSettingsActivity {
|
||||||
@ -51,10 +54,17 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity {
|
|||||||
PREF_USER_GENDER,
|
PREF_USER_GENDER,
|
||||||
PREF_USER_HEIGHT_CM,
|
PREF_USER_HEIGHT_CM,
|
||||||
PREF_USER_WEIGHT_KG,
|
PREF_USER_WEIGHT_KG,
|
||||||
|
PREF_MIBAND_WEARSIDE,
|
||||||
PREF_MIBAND_ADDRESS,
|
PREF_MIBAND_ADDRESS,
|
||||||
|
getNotificationPrefKey(VIBRATION_PROFILE, ORIGIN_SMS),
|
||||||
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_SMS),
|
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_SMS),
|
||||||
|
getNotificationPrefKey(VIBRATION_PROFILE, ORIGIN_INCOMING_CALL),
|
||||||
|
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_INCOMING_CALL),
|
||||||
|
getNotificationPrefKey(VIBRATION_PROFILE, ORIGIN_K9MAIL),
|
||||||
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_K9MAIL),
|
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_K9MAIL),
|
||||||
|
getNotificationPrefKey(VIBRATION_PROFILE, ORIGIN_PEBBLEMSG),
|
||||||
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_PEBBLEMSG),
|
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_PEBBLEMSG),
|
||||||
|
getNotificationPrefKey(VIBRATION_PROFILE, ORIGIN_GENERIC),
|
||||||
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_GENERIC),
|
getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_GENERIC),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,14 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.GBCommand;
|
import nodomain.freeyourgadget.gadgetbridge.GBCommand;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBDevice.State;
|
import nodomain.freeyourgadget.gadgetbridge.GBDevice.State;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.btle.AbortTransactionAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.btle.AbstractBTLEDeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.btle.AbstractBTLEDeviceSupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.btle.BtLEAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.btle.SetDeviceBusyAction;
|
import nodomain.freeyourgadget.gadgetbridge.btle.SetDeviceBusyAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
|
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
|
||||||
|
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_PROFILE;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COLOUR;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COLOUR;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COUNT;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COUNT;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_DURATION;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_DURATION;
|
||||||
@ -44,7 +47,9 @@ import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_SMS
|
|||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_DURATION;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_DURATION;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PAUSE;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PAUSE;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PROFILE;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.getNotificationPrefIntValue;
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.getNotificationPrefIntValue;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.getNotificationPrefStringValue;
|
||||||
|
|
||||||
public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
||||||
|
|
||||||
@ -63,6 +68,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
private GregorianCalendar activityDataTimestampProgress = null;
|
private GregorianCalendar activityDataTimestampProgress = null;
|
||||||
//same as above, but remains untouched for the ack message
|
//same as above, but remains untouched for the ack message
|
||||||
private GregorianCalendar activityDataTimestampToAck = null;
|
private GregorianCalendar activityDataTimestampToAck = null;
|
||||||
|
private volatile boolean telephoneRinging;
|
||||||
|
|
||||||
|
|
||||||
public MiBandSupport() {
|
public MiBandSupport() {
|
||||||
@ -135,6 +141,42 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
builder.write(characteristic, getDefaultNotification()).queue(getQueue());
|
builder.write(characteristic, getDefaultNotification()).queue(getQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a custom notification to the Mi Band.
|
||||||
|
* @param vibrationProfile specifies how and how often the Band shall vibrate.
|
||||||
|
* @param flashTimes
|
||||||
|
* @param flashColour
|
||||||
|
* @param originalColour
|
||||||
|
* @param flashDuration
|
||||||
|
* @param extraAction an extra action to be executed after every vibration and flash sequence. Allows to abort the repetition, for example.
|
||||||
|
* @param builder
|
||||||
|
*/
|
||||||
|
private void sendCustomNotification(VibrationProfile vibrationProfile, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) {
|
||||||
|
BluetoothGattCharacteristic controlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
|
||||||
|
for (byte i = 0; i < vibrationProfile.getRepeat(); i++) {
|
||||||
|
int[] onOffSequence = vibrationProfile.getOnOffSequence();
|
||||||
|
for (int j = 0; j < onOffSequence.length; j++) {
|
||||||
|
int on = onOffSequence[j];
|
||||||
|
on = Math.min(500, on); // longer than 500ms is not possible
|
||||||
|
builder.write(controlPoint, startVibrate);
|
||||||
|
builder.wait(on);
|
||||||
|
builder.write(controlPoint, stopVibrate);
|
||||||
|
|
||||||
|
if (++j < onOffSequence.length) {
|
||||||
|
int off = Math.max(onOffSequence[j], 25); // wait at least 25ms
|
||||||
|
builder.wait(off);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extraAction != null) {
|
||||||
|
builder.add(extraAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.info("Sending notification to MiBand: " + controlPoint);
|
||||||
|
builder.queue(getQueue());
|
||||||
|
}
|
||||||
|
|
||||||
private void sendCustomNotification(int vibrateDuration, int vibrateTimes, int pause, int flashTimes, int flashColour, int originalColour, long flashDuration, TransactionBuilder builder) {
|
private void sendCustomNotification(int vibrateDuration, int vibrateTimes, int pause, int flashTimes, int flashColour, int originalColour, long flashDuration, TransactionBuilder builder) {
|
||||||
BluetoothGattCharacteristic controlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
|
BluetoothGattCharacteristic controlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
|
||||||
int vDuration = Math.min(500, vibrateDuration); // longer than 500ms is not possible
|
int vDuration = Math.min(500, vibrateDuration); // longer than 500ms is not possible
|
||||||
@ -221,20 +263,22 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private void performPreferredNotification(String task, String notificationOrigin) {
|
private void performPreferredNotification(String task, String notificationOrigin, BtLEAction extraAction) {
|
||||||
try {
|
try {
|
||||||
TransactionBuilder builder = performInitialized(task);
|
TransactionBuilder builder = performInitialized(task);
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
int vibrateDuration = getPreferredVibrateDuration(notificationOrigin, prefs);
|
int vibrateDuration = getPreferredVibrateDuration(notificationOrigin, prefs);
|
||||||
int vibrateTimes = getPreferredVibrateCount(notificationOrigin, prefs);
|
|
||||||
int vibratePause = getPreferredVibratePause(notificationOrigin, prefs);
|
int vibratePause = getPreferredVibratePause(notificationOrigin, prefs);
|
||||||
|
int vibrateTimes = getPreferredVibrateCount(notificationOrigin, prefs);
|
||||||
|
VibrationProfile profile = getPreferredVibrateProfile(notificationOrigin, prefs, vibrateTimes);
|
||||||
|
|
||||||
int flashTimes = getPreferredFlashCount(notificationOrigin, prefs);
|
int flashTimes = getPreferredFlashCount(notificationOrigin, prefs);
|
||||||
int flashColour = getPreferredFlashColour(notificationOrigin, prefs);
|
int flashColour = getPreferredFlashColour(notificationOrigin, prefs);
|
||||||
int originalColour = getPreferredOriginalColour(notificationOrigin, prefs);
|
int originalColour = getPreferredOriginalColour(notificationOrigin, prefs);
|
||||||
int flashDuration = getPreferredFlashDuration(notificationOrigin, prefs);
|
int flashDuration = getPreferredFlashDuration(notificationOrigin, prefs);
|
||||||
|
|
||||||
sendCustomNotification(vibrateDuration, vibrateTimes, vibratePause, flashTimes, flashColour, originalColour, flashDuration, builder);
|
sendCustomNotification(profile, flashTimes, flashColour, originalColour, flashDuration, extraAction, builder);
|
||||||
|
// sendCustomNotification(vibrateDuration, vibrateTimes, vibratePause, flashTimes, flashColour, originalColour, flashDuration, builder);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOG.error("Unable to send notification to MI device", ex);
|
LOG.error("Unable to send notification to MI device", ex);
|
||||||
}
|
}
|
||||||
@ -268,20 +312,24 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
return getNotificationPrefIntValue(VIBRATION_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_DURATION);
|
return getNotificationPrefIntValue(VIBRATION_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VibrationProfile getPreferredVibrateProfile(String notificationOrigin, SharedPreferences prefs, int repeat) {
|
||||||
|
String profileId = getNotificationPrefStringValue(VIBRATION_PROFILE, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_PROFILE);
|
||||||
|
return VibrationProfile.getProfile(profileId, (byte) repeat);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSMS(String from, String body) {
|
public void onSMS(String from, String body) {
|
||||||
// performCustomNotification("sms received", 500, 3, 2000, 0, 0, 0, 0);
|
performPreferredNotification("sms received", ORIGIN_SMS, null);
|
||||||
performPreferredNotification("sms received", ORIGIN_SMS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEmail(String from, String subject, String body) {
|
public void onEmail(String from, String subject, String body) {
|
||||||
performPreferredNotification("email received", ORIGIN_K9MAIL);
|
performPreferredNotification("email received", ORIGIN_K9MAIL, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGenericNotification(String title, String details) {
|
public void onGenericNotification(String title, String details) {
|
||||||
performPreferredNotification("generic notification received", ORIGIN_GENERIC);
|
performPreferredNotification("generic notification received", ORIGIN_GENERIC, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -328,10 +376,24 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
@Override
|
@Override
|
||||||
public void onSetCallState(String number, String name, GBCommand command) {
|
public void onSetCallState(String number, String name, GBCommand command) {
|
||||||
if (GBCommand.CALL_INCOMING.equals(command)) {
|
if (GBCommand.CALL_INCOMING.equals(command)) {
|
||||||
performDefaultNotification("incoming call");
|
telephoneRinging = true;
|
||||||
|
AbortTransactionAction abortAction = new AbortTransactionAction() {
|
||||||
|
@Override
|
||||||
|
protected boolean shouldAbort() {
|
||||||
|
return !isTelephoneRinging();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
performPreferredNotification("incoming call", MiBandConst.ORIGIN_INCOMING_CALL, abortAction);
|
||||||
|
} else if (GBCommand.CALL_START.equals(command) || GBCommand.CALL_END.equals(command)) {
|
||||||
|
telephoneRinging = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isTelephoneRinging() {
|
||||||
|
// don't synchronize, this is not really important
|
||||||
|
return telephoneRinging;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetMusicInfo(String artist, String album, String track) {
|
public void onSetMusicInfo(String artist, String album, String track) {
|
||||||
// not supported
|
// not supported
|
||||||
@ -556,8 +618,12 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||||||
unsetBusy();
|
unsetBusy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (byte b : value) {
|
if (value != null) {
|
||||||
LOG.info("handleControlPoint GOT DATA:" + String.format("0x%8x", b));
|
for (byte b : value) {
|
||||||
|
LOG.info("handleControlPoint GOT DATA:" + String.format("0x%8x", b));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.warn("handleControlPoint GOT null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.miband;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
|
public class VibrationProfile {
|
||||||
|
public static final Context CONTEXT = GBApplication.getContext();
|
||||||
|
public static final String ID_STACCATO = CONTEXT.getString(R.string.p_staccato);
|
||||||
|
public static final String ID_SHORT = CONTEXT.getString(R.string.p_short);
|
||||||
|
public static final String ID_MEDIUM = CONTEXT.getString(R.string.p_medium);
|
||||||
|
public static final String ID_LONG = CONTEXT.getString(R.string.p_long);
|
||||||
|
public static final String ID_WATERDROP = CONTEXT.getString(R.string.p_waterdrop);
|
||||||
|
public static final String ID_RING = CONTEXT.getString(R.string.p_ring);
|
||||||
|
public static final String ID_ALARM_CLOCK = CONTEXT.getString(R.string.p_alarm_clock);
|
||||||
|
|
||||||
|
public static VibrationProfile getProfile(String id, byte repeat) {
|
||||||
|
if (ID_STACCATO.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[]{100, 0}, repeat);
|
||||||
|
}
|
||||||
|
if (ID_SHORT.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[] {200, 200}, repeat);
|
||||||
|
}
|
||||||
|
if (ID_LONG.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[] {500, 1000}, repeat);
|
||||||
|
}
|
||||||
|
if (ID_WATERDROP.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[] {100, 1500}, repeat);
|
||||||
|
}
|
||||||
|
if (ID_RING.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[]{300, 200, 600, 2000}, repeat);
|
||||||
|
}
|
||||||
|
if (ID_ALARM_CLOCK.equals(id)) {
|
||||||
|
return new VibrationProfile(id, new int[] {30, 35, 30, 35, 30, 35, 30, 800}, repeat);
|
||||||
|
}
|
||||||
|
// medium
|
||||||
|
return new VibrationProfile(id, new int[] {300, 600}, repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private int[] onOffSequence;
|
||||||
|
private byte repeat; // 1-10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new profile instance.
|
||||||
|
* @param id the ID, used as preference key.
|
||||||
|
* @param onOffSequence a sequence of alternating on and off durations, in milliseconds
|
||||||
|
* @param repeat how ofoften the sequence shall be repeated
|
||||||
|
*/
|
||||||
|
public VibrationProfile(String id, int[] onOffSequence, byte repeat) {
|
||||||
|
this.id = id;
|
||||||
|
this.repeat = repeat;
|
||||||
|
this.onOffSequence = onOffSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getOnOffSequence() {
|
||||||
|
return onOffSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getRepeat() {
|
||||||
|
return repeat;
|
||||||
|
}
|
||||||
|
}
|
@ -21,4 +21,33 @@
|
|||||||
<item>female</item>
|
<item>female</item>
|
||||||
<item>other</item>
|
<item>other</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="wearside">
|
||||||
|
<item>@string/left</item>
|
||||||
|
<item>@string/right</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="wearside_values">
|
||||||
|
<item>left</item>
|
||||||
|
<item>right</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="vibration_profile">
|
||||||
|
<item>@string/vibration_profile_staccato</item>
|
||||||
|
<item>@string/vibration_profile_short</item>
|
||||||
|
<item>@string/vibration_profile_medium</item>
|
||||||
|
<item>@string/vibration_profile_long</item>
|
||||||
|
<item>@string/vibration_profile_waterdrop</item>
|
||||||
|
<item>@string/vibration_profile_ring</item>
|
||||||
|
<item>@string/vibration_profile_alarm_clock</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="vibration_profile_values">
|
||||||
|
<!-- Note: corresponds with IDs in VibrationProfile -->
|
||||||
|
<item>@string/p_staccato</item>
|
||||||
|
<item>@string/p_short</item>
|
||||||
|
<item>@string/p_medium</item>
|
||||||
|
<item>@string/p_long</item>
|
||||||
|
<item>@string/p_waterdrop</item>
|
||||||
|
<item>@string/p_ring</item>
|
||||||
|
<item>@string/p_alarm_clock</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -28,7 +28,9 @@
|
|||||||
<string name="pref_summary_datetime_syctimeonconnect">Sync time to device when connecting and when time or timezone changes on Android</string>
|
<string name="pref_summary_datetime_syctimeonconnect">Sync time to device when connecting and when time or timezone changes on Android</string>
|
||||||
|
|
||||||
<string name="pref_header_notifications">Notifications</string>
|
<string name="pref_header_notifications">Notifications</string>
|
||||||
|
<string name="pref_title_notifications_repetitions">Repetitions</string>
|
||||||
<string name="pref_title_notifications_sms">SMS</string>
|
<string name="pref_title_notifications_sms">SMS</string>
|
||||||
|
<string name="pref_title_notifications_incoming_call">Incoming Calls</string>
|
||||||
<string name="pref_title_notifications_k9mail">K9-Mail</string>
|
<string name="pref_title_notifications_k9mail">K9-Mail</string>
|
||||||
<string name="pref_title_notifications_pebblemsg">Pebble Messages</string>
|
<string name="pref_title_notifications_pebblemsg">Pebble Messages</string>
|
||||||
<string name="pref_summary_notifications_pebblemsg">Support for applications which send Notifications to the Pebble via Intent. Can be used for Conversations.</string>
|
<string name="pref_summary_notifications_pebblemsg">Support for applications which send Notifications to the Pebble via Intent. Can be used for Conversations.</string>
|
||||||
@ -91,6 +93,8 @@
|
|||||||
<string name="male">male</string>
|
<string name="male">male</string>
|
||||||
<string name="female">female</string>
|
<string name="female">female</string>
|
||||||
<string name="other">other</string>
|
<string name="other">other</string>
|
||||||
|
<string name="left">left</string>
|
||||||
|
<string name="right">right</string>
|
||||||
<string name="miband_pairing_using_dummy_userdata">No valid user data given, using dummy user data for now.</string>
|
<string name="miband_pairing_using_dummy_userdata">No valid user data given, using dummy user data for now.</string>
|
||||||
<string name="miband_pairing_tap_hint">When your Mi Band vibrates and blinks, tap it a few times in a row.</string>
|
<string name="miband_pairing_tap_hint">When your Mi Band vibrates and blinks, tap it a few times in a row.</string>
|
||||||
<string name="appinstaller_install">Install</string>
|
<string name="appinstaller_install">Install</string>
|
||||||
@ -112,5 +116,22 @@
|
|||||||
<string name="controlcenter_fetch_activity_data">Fetch Activity Data</string>
|
<string name="controlcenter_fetch_activity_data">Fetch Activity Data</string>
|
||||||
<string name="controlcenter_disconnect">Disconnect</string>
|
<string name="controlcenter_disconnect">Disconnect</string>
|
||||||
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
|
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
|
||||||
|
<string name="miband_prefs_wearside">Wearing left or right?</string>
|
||||||
|
<string name="pref_screen_vibration_profile">Vibration Profile</string>
|
||||||
|
|
||||||
|
<string name="vibration_profile_staccato">Staccato</string>
|
||||||
|
<string name="vibration_profile_short">Short</string>
|
||||||
|
<string name="vibration_profile_medium">Medium</string>
|
||||||
|
<string name="vibration_profile_long">Long</string>
|
||||||
|
<string name="vibration_profile_waterdrop">Waterdrop</string>
|
||||||
|
<string name="vibration_profile_ring">Ring</string>
|
||||||
|
<string name="vibration_profile_alarm_clock">Alarm Clock</string>
|
||||||
|
<string name="miband_prefs_vibration">Vibration</string>
|
||||||
|
<string name="pref_screen_notification_profile_sms">SMS Notification</string>
|
||||||
|
<string name="pref_header_vibration_settings">Vibration Settings</string>
|
||||||
|
<string name="pref_screen_notification_profile_generic">Generic Notification</string>
|
||||||
|
<string name="pref_screen_notification_profile_pebblemsg">Pebble Notification</string>
|
||||||
|
<string name="pref_screen_notification_profile_k9mail">K9 Mail Notification</string>
|
||||||
|
<string name="pref_screen_notification_profile_incoming_call">Incoming Call Notification</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
12
app/src/main/res/values/values.xml
Normal file
12
app/src/main/res/values/values.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Note: these are not translated! They are used as preference keys -->
|
||||||
|
<item name="p_staccato" type="string">staccato</item>
|
||||||
|
<item name="p_short" type="string">short</item>
|
||||||
|
<item name="p_medium" type="string">medium</item>
|
||||||
|
<item name="p_long" type="string">long</item>
|
||||||
|
<item name="p_waterdrop" type="string">waterdrop</item>
|
||||||
|
<item name="p_ring" type="string">ring</item>
|
||||||
|
<item name="p_alarm_clock" type="string">alarm_clock</item>
|
||||||
|
|
||||||
|
</resources>
|
@ -34,35 +34,118 @@
|
|||||||
android:maxLength="3"
|
android:maxLength="3"
|
||||||
android:title="@string/miband_prefs_weight_kg" />
|
android:title="@string/miband_prefs_weight_kg" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="left"
|
||||||
|
android:entries="@array/wearside"
|
||||||
|
android:entryValues="@array/wearside_values"
|
||||||
|
android:key="mi_wearside"
|
||||||
|
android:title="@string/miband_prefs_wearside" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="pref_category_miband_notification"
|
android:key="pref_category_miband_notification"
|
||||||
android:title="@string/pref_header_vibration_count">
|
android:title="@string/pref_header_vibration_settings">
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue="3"
|
<PreferenceScreen
|
||||||
android:inputType="number"
|
android:key="vibration_profile_key"
|
||||||
android:key="mi_vibration_count_sms"
|
android:title="@string/pref_screen_notification_profile_sms"
|
||||||
android:maxLength="1"
|
android:persistent="false">
|
||||||
android:title="@string/pref_title_notifications_sms" />
|
|
||||||
<EditTextPreference
|
<ListPreference
|
||||||
android:defaultValue="3"
|
android:defaultValue="@string/p_staccato"
|
||||||
android:inputType="number"
|
android:entries="@array/vibration_profile"
|
||||||
android:key="mi_vibration_count_k9mail"
|
android:entryValues="@array/vibration_profile_values"
|
||||||
android:maxLength="1"
|
android:key="mi_vibration_profile_sms"
|
||||||
android:title="@string/pref_title_notifications_k9mail" />
|
android:title="@string/miband_prefs_vibration" />
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue="3"
|
<EditTextPreference
|
||||||
android:inputType="number"
|
android:defaultValue="3"
|
||||||
android:key="mi_vibration_count_pebblemsg"
|
android:inputType="number"
|
||||||
android:maxLength="1"
|
android:key="mi_vibration_count_sms"
|
||||||
android:title="@string/pref_title_notifications_pebblemsg" />
|
android:maxLength="1"
|
||||||
<EditTextPreference
|
android:title="@string/pref_title_notifications_repetitions" />
|
||||||
android:defaultValue="3"
|
</PreferenceScreen>
|
||||||
android:inputType="number"
|
|
||||||
android:key="mi_vibration_count_generic"
|
<PreferenceScreen
|
||||||
android:maxLength="1"
|
android:key="vibration_profile_key"
|
||||||
android:title="@string/pref_title_notifications_generic" />
|
android:title="@string/pref_screen_notification_profile_incoming_call"
|
||||||
|
android:persistent="false">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="@string/p_ring"
|
||||||
|
android:entries="@array/vibration_profile"
|
||||||
|
android:entryValues="@array/vibration_profile_values"
|
||||||
|
android:key="mi_vibration_profile_incoming_call"
|
||||||
|
android:title="@string/miband_prefs_vibration" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="60"
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="mi_vibration_count_incoming_call"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:title="@string/pref_title_notifications_repetitions" />
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:key="vibration_profile_key"
|
||||||
|
android:title="@string/pref_screen_notification_profile_k9mail"
|
||||||
|
android:persistent="false">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="@string/p_medium"
|
||||||
|
android:entries="@array/vibration_profile"
|
||||||
|
android:entryValues="@array/vibration_profile_values"
|
||||||
|
android:key="mi_vibration_profile_k9mail"
|
||||||
|
android:title="@string/miband_prefs_vibration" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="2"
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="mi_vibration_count_k9mail"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:title="@string/pref_title_notifications_repetitions" />
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:key="vibration_profile_key"
|
||||||
|
android:title="@string/pref_screen_notification_profile_pebblemsg"
|
||||||
|
android:persistent="false">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="@string/p_short"
|
||||||
|
android:entries="@array/vibration_profile"
|
||||||
|
android:entryValues="@array/vibration_profile_values"
|
||||||
|
android:key="mi_vibration_profile_pebblemsg"
|
||||||
|
android:title="@string/miband_prefs_vibration" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="mi_vibration_count_pebblemsg"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:title="@string/pref_title_notifications_repetitions" />
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:key="vibration_profile_key"
|
||||||
|
android:title="@string/pref_screen_notification_profile_generic"
|
||||||
|
android:persistent="false">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="@string/p_waterdrop"
|
||||||
|
android:entries="@array/vibration_profile"
|
||||||
|
android:entryValues="@array/vibration_profile_values"
|
||||||
|
android:key="mi_vibration_profile_generic"
|
||||||
|
android:title="@string/miband_prefs_vibration" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="3"
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="mi_vibration_count_generic"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:title="@string/pref_title_notifications_repetitions" />
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
@ -58,9 +58,11 @@
|
|||||||
android:title="@string/preferences_category_device_specific_settings">
|
android:title="@string/preferences_category_device_specific_settings">
|
||||||
<Preference
|
<Preference
|
||||||
android:key="pref_key_miband"
|
android:key="pref_key_miband"
|
||||||
|
android:icon="@drawable/ic_device_miband"
|
||||||
android:title="@string/preferences_miband_settings" />
|
android:title="@string/preferences_miband_settings" />
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:key="pref_key_pebble"
|
android:key="pref_key_pebble"
|
||||||
|
android:icon="@drawable/ic_device_pebble"
|
||||||
android:title="@string/pref_title_pebble_settings" >
|
android:title="@string/pref_title_pebble_settings" >
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="pref_key_development"
|
android:key="pref_key_development"
|
||||||
|
Loading…
Reference in New Issue
Block a user