1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-08-24 00:00:47 +02:00

Mi Band 5: Add notification vibration patterns

This commit is contained in:
José Rebelo 2022-05-14 14:20:28 +01:00 committed by Gitea
parent 5f73dd79e6
commit b220fef74e
18 changed files with 658 additions and 16 deletions

View File

@ -20,6 +20,8 @@ import android.os.Parcelable;
import androidx.preference.Preference;
import java.util.Set;
/**
* A device-specific preference handler, that allows for concrete implementations to customize the preferences in
* the {@link DeviceSpecificSettingsFragment}.
@ -39,4 +41,9 @@ public interface DeviceSpecificSettingsCustomizer extends Parcelable {
* @param handler the {@link DeviceSpecificSettingsHandler}
*/
void customizeSettings(final DeviceSpecificSettingsHandler handler);
/**
* Keys of preferences which should print its values as a summary below the preference name.
*/
Set<String> getPreferenceKeysWithSummary();
}

View File

@ -43,7 +43,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -806,7 +808,8 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
}
}
private void setInputTypeFor(final String preferenceKey, final int editTypeFlags) {
@Override
public void setInputTypeFor(final String preferenceKey, final int editTypeFlags) {
EditTextPreference textPreference = findPreference(preferenceKey);
if (textPreference != null) {
textPreference.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
@ -818,6 +821,19 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
}
}
/**
* Keys of preferences which should print its values as a summary below the preference name.
*/
protected Set<String> getPreferenceKeysWithSummary() {
final Set<String> keysWithSummary = new HashSet<>();
if (deviceSpecificSettingsCustomizer != null) {
keysWithSummary.addAll(deviceSpecificSettingsCustomizer.getPreferenceKeysWithSummary());
}
return keysWithSummary;
}
/**
* Reload the preferences in the current screen. This is needed when the user enters or exists a PreferenceScreen,
* otherwise the settings won't be reloaded by the {@link SharedPreferencesChangeHandler}, as the preferences return
@ -849,7 +865,7 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
LOG.debug("Preference changed: {}", key);
if(key == null){
if (key == null){
LOG.warn("Preference null, ignoring");
return;
}
@ -879,6 +895,11 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
LOG.warn("Unknown preference class {}, ignoring", preference.getClass());
}
if (getPreferenceKeysWithSummary().contains(key)) {
final String summary = prefs.getString(key, preference.getSummary() != null ? preference.getSummary().toString() : "");
preference.setSummary(summary);
}
if (deviceSpecificSettingsCustomizer != null) {
deviceSpecificSettingsCustomizer.onPreferenceChange(preference, DeviceSpecificSettingsFragment.this);
}

View File

@ -53,4 +53,12 @@ public interface DeviceSpecificSettingsHandler {
* @param extraListener the extra listener.
*/
void addPreferenceHandlerFor(final String preferenceKey, Preference.OnPreferenceChangeListener extraListener);
/**
* Sets the input type flags for an EditText preference.
*
* @param preferenceKey the preference key.
* @param editTypeFlags the edit type {@link android.text.InputType} flags.
*/
void setInputTypeFor(final String preferenceKey, final int editTypeFlags);
}

View File

@ -86,6 +86,39 @@ public class HuamiConst {
public static final String PREF_DEVICE_ACTION_START_NON_WEAR_SELECTION = "events_forwarding_startnonwear_action_selection";
public static final String PREF_DEVICE_ACTION_START_NON_WEAR_BROADCAST = "prefs_events_forwarding_startnonwear_broadcast";
/**
* The suffixes match the enum {@link nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType}.
*/
// profile
public static final String PREF_HUAMI_VIBRATION_PROFILE_PREFIX = "huami_vibration_profile_";
public static final String PREF_HUAMI_VIBRATION_PROFILE_APP_ALERTS = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "app_alerts";
public static final String PREF_HUAMI_VIBRATION_PROFILE_INCOMING_CALL = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "incoming_call";
public static final String PREF_HUAMI_VIBRATION_PROFILE_INCOMING_SMS = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "incoming_sms";
public static final String PREF_HUAMI_VIBRATION_PROFILE_GOAL_NOTIFICATION = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "goal_notification";
public static final String PREF_HUAMI_VIBRATION_PROFILE_ALARM = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "alarm";
public static final String PREF_HUAMI_VIBRATION_PROFILE_IDLE_ALERTS = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "idle_alerts";
public static final String PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "event_reminder";
public static final String PREF_HUAMI_VIBRATION_PROFILE_FIND_BAND = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "find_band";
// count
public static final String PREF_HUAMI_VIBRATION_COUNT_PREFIX = "huami_vibration_count_";
public static final String PREF_HUAMI_VIBRATION_COUNT_APP_ALERTS = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "app_alerts";
public static final String PREF_HUAMI_VIBRATION_COUNT_INCOMING_CALL = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "incoming_call";
public static final String PREF_HUAMI_VIBRATION_COUNT_INCOMING_SMS = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "incoming_sms";
public static final String PREF_HUAMI_VIBRATION_COUNT_GOAL_NOTIFICATION = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "goal_notification";
public static final String PREF_HUAMI_VIBRATION_COUNT_ALARM = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "alarm";
public static final String PREF_HUAMI_VIBRATION_COUNT_IDLE_ALERTS = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "idle_alerts";
public static final String PREF_HUAMI_VIBRATION_COUNT_EVENT_REMINDER = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "event_reminder";
public static final String PREF_HUAMI_VIBRATION_COUNT_FIND_BAND = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "find_band";
// try
public static final String PREF_HUAMI_VIBRATION_TRY_PREFIX = "huami_vibration_try_";
public static final String PREF_HUAMI_VIBRATION_TRY_APP_ALERTS = PREF_HUAMI_VIBRATION_TRY_PREFIX + "app_alerts";
public static final String PREF_HUAMI_VIBRATION_TRY_INCOMING_CALL = PREF_HUAMI_VIBRATION_TRY_PREFIX + "incoming_call";
public static final String PREF_HUAMI_VIBRATION_TRY_INCOMING_SMS = PREF_HUAMI_VIBRATION_TRY_PREFIX + "incoming_sms";
public static final String PREF_HUAMI_VIBRATION_TRY_GOAL_NOTIFICATION = PREF_HUAMI_VIBRATION_TRY_PREFIX + "goal_notification";
public static final String PREF_HUAMI_VIBRATION_TRY_ALARM = PREF_HUAMI_VIBRATION_TRY_PREFIX + "alarm";
public static final String PREF_HUAMI_VIBRATION_TRY_IDLE_ALERTS = PREF_HUAMI_VIBRATION_TRY_PREFIX + "idle_alerts";
public static final String PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER = PREF_HUAMI_VIBRATION_TRY_PREFIX + "event_reminder";
public static final String PREF_HUAMI_VIBRATION_TRY_FIND_BAND = PREF_HUAMI_VIBRATION_TRY_PREFIX + "find_band";
public static int toActivityKind(int rawType) {
switch (rawType) {

View File

@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.DateTimeDisplay;
@ -51,11 +52,13 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2SampleProvider
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPairingActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public abstract class HuamiCoordinator extends AbstractDeviceCoordinator {
@ -270,6 +273,17 @@ public abstract class HuamiCoordinator extends AbstractDeviceCoordinator {
return prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_BT_CONNECTED_ADVERTISEMENT, false);
}
public static VibrationProfile getVibrationProfile(String deviceAddress, HuamiVibrationPatternNotificationType notificationType) {
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
final String vibrationProfileId = prefs.getString(
HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + notificationType.name().toLowerCase(Locale.ROOT),
VibrationProfile.ID_MEDIUM
);
final int vibrationProfileCount = prefs.getInt(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + notificationType.name().toLowerCase(Locale.ROOT), 2);
return VibrationProfile.getProfile(vibrationProfileId, (short) vibrationProfileCount);
}
protected static Date getTimePreference(String key, String defaultValue, String deviceAddress) {
Prefs prefs;
@ -353,4 +367,9 @@ public abstract class HuamiCoordinator extends AbstractDeviceCoordinator {
public int getReminderSlotCount() {
return 22; // At least, Mi Fit still allows more
}
@Override
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
return new HuamiSettingsCustomizer(device);
}
}

View File

@ -0,0 +1,104 @@
/* Copyright (C) 2022 José Rebelo
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.devices.huami;
import android.os.Parcel;
import android.text.InputType;
import android.widget.Toast;
import androidx.preference.Preference;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType;
public class HuamiSettingsCustomizer implements DeviceSpecificSettingsCustomizer {
final GBDevice device;
public HuamiSettingsCustomizer(final GBDevice device) {
this.device = device;
}
@Override
public void onPreferenceChange(final Preference preference, final DeviceSpecificSettingsHandler handler) {
// Nothing to do here
}
@Override
public void customizeSettings(final DeviceSpecificSettingsHandler handler) {
for (HuamiVibrationPatternNotificationType notificationType : HuamiVibrationPatternNotificationType.values()) {
final String typeKey = notificationType.name().toLowerCase(Locale.ROOT);
handler.addPreferenceHandlerFor(HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + typeKey);
handler.addPreferenceHandlerFor(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey);
handler.setInputTypeFor(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey, InputType.TYPE_CLASS_NUMBER);
final String tryPrefKey = HuamiConst.PREF_HUAMI_VIBRATION_TRY_PREFIX + typeKey;
final Preference tryPref = handler.findPreference(tryPrefKey);
if (tryPref != null) {
tryPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
GBApplication.deviceService().onSendConfiguration(tryPrefKey);
return true;
}
});
}
}
}
@Override
public Set<String> getPreferenceKeysWithSummary() {
final Set<String> keysWithSummary = new HashSet<>();
for (HuamiVibrationPatternNotificationType notificationType : HuamiVibrationPatternNotificationType.values()) {
final String typeKey = notificationType.name().toLowerCase(Locale.ROOT);
keysWithSummary.add(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey);
}
return keysWithSummary;
}
public static final Creator<HuamiSettingsCustomizer> CREATOR = new Creator<HuamiSettingsCustomizer>() {
@Override
public HuamiSettingsCustomizer createFromParcel(final Parcel in) {
final GBDevice device = in.readParcelable(HuamiSettingsCustomizer.class.getClassLoader());
return new HuamiSettingsCustomizer(device);
}
@Override
public HuamiSettingsCustomizer[] newArray(final int size) {
return new HuamiSettingsCustomizer[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeParcelable(device, 0);
}
}

View File

@ -99,6 +99,7 @@ public class MiBand5Coordinator extends HuamiCoordinator {
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[]{
R.xml.devicesettings_miband5,
R.xml.devicesettings_miband5_vibration,
R.xml.devicesettings_wearlocation,
R.xml.devicesettings_custom_emoji_font,
R.xml.devicesettings_timeformat,

View File

@ -79,6 +79,10 @@ public class VibrationProfile {
* @param repeat how often the sequence shall be repeated
*/
public VibrationProfile(String id, int[] onOffSequence, short repeat) {
if (onOffSequence.length % 2 != 0) {
throw new IllegalArgumentException("Each on duration must have a subsequent off duration");
}
this.id = id;
this.repeat = repeat;
this.onOffSequence = onOffSequence;

View File

@ -47,8 +47,10 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
@ -185,6 +187,11 @@ public class SonyHeadphonesSettingsCustomizer implements DeviceSpecificSettingsC
}
}
@Override
public Set<String> getPreferenceKeysWithSummary() {
return Collections.emptySet();
}
public static final Creator<SonyHeadphonesSettingsCustomizer> CREATOR = new Creator<SonyHeadphonesSettingsCustomizer>() {
@Override
public SonyHeadphonesSettingsCustomizer createFromParcel(final Parcel in) {

View File

@ -197,6 +197,33 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_START_NON_WEAR_SELECTION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_WOKE_UP_BROADCAST;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_WOKE_UP_SELECTION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_ALARM;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_APP_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_EVENT_REMINDER;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_FIND_BAND;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_GOAL_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_IDLE_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_INCOMING_CALL;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_INCOMING_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_ALARM;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_APP_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_FIND_BAND;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_GOAL_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_IDLE_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_INCOMING_CALL;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_INCOMING_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_ALARM;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_APP_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_FIND_BAND;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_GOAL_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_IDLE_ALERTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_INCOMING_CALL;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_INCOMING_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_PREFIX;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.DISPLAY_ITEM_BIT_CLOCK;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.ENDPOINT_DISPLAY_ITEMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_COUNT;
@ -2465,6 +2492,32 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
case PREF_USER_GENDER:
setUserInfo(builder);
break;
case PREF_HUAMI_VIBRATION_PROFILE_APP_ALERTS:
case PREF_HUAMI_VIBRATION_PROFILE_INCOMING_CALL:
case PREF_HUAMI_VIBRATION_PROFILE_INCOMING_SMS:
case PREF_HUAMI_VIBRATION_PROFILE_GOAL_NOTIFICATION:
case PREF_HUAMI_VIBRATION_PROFILE_ALARM:
case PREF_HUAMI_VIBRATION_PROFILE_IDLE_ALERTS:
case PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER:
case PREF_HUAMI_VIBRATION_PROFILE_FIND_BAND:
case PREF_HUAMI_VIBRATION_COUNT_APP_ALERTS:
case PREF_HUAMI_VIBRATION_COUNT_INCOMING_CALL:
case PREF_HUAMI_VIBRATION_COUNT_INCOMING_SMS:
case PREF_HUAMI_VIBRATION_COUNT_GOAL_NOTIFICATION:
case PREF_HUAMI_VIBRATION_COUNT_ALARM:
case PREF_HUAMI_VIBRATION_COUNT_IDLE_ALERTS:
case PREF_HUAMI_VIBRATION_COUNT_EVENT_REMINDER:
case PREF_HUAMI_VIBRATION_COUNT_FIND_BAND:
case PREF_HUAMI_VIBRATION_TRY_APP_ALERTS:
case PREF_HUAMI_VIBRATION_TRY_INCOMING_CALL:
case PREF_HUAMI_VIBRATION_TRY_INCOMING_SMS:
case PREF_HUAMI_VIBRATION_TRY_GOAL_NOTIFICATION:
case PREF_HUAMI_VIBRATION_TRY_ALARM:
case PREF_HUAMI_VIBRATION_TRY_IDLE_ALERTS:
case PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER:
case PREF_HUAMI_VIBRATION_TRY_FIND_BAND:
setVibrationPattern(builder, config);
break;
}
builder.queue(getQueue());
} catch (IOException e) {
@ -2480,16 +2533,82 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
@Override
public void onTestNewFunction() {
//requestMTU(23);
/*
try {
boolean test = false;
TransactionBuilder builder = performInitialized("test pattern");
byte[] testpattern = new byte[] {0x20,0x00, (byte) 0x4b,0x64,0x00, (byte) 0x8d,0x01,0x73,0x00,0x38,0x01,0x64,0x00,0x64,0x00,0x64,0x00,0x67,0x00,0x64,0x00,0x37,0x01,0x7c,0x00,0x64,0x00,0x64,0x00,0x67,0x00,0x64,0x00,0x67,0x00,0x64,0x00,0x37,0x01,0x64,0x00,0x64,0x00,0x64,0x00, (byte) 0xe5,0x02};
//byte[] testpattern = new byte[] {0x20,0x00, (byte) 0x00, 0,0,0,0};
writeToChunked(builder,2, testpattern);
final TransactionBuilder builder = performInitialized("test pattern");
final VibrationProfile profile = VibrationProfile.getProfile(VibrationProfile.ID_SHORT, (short) 2);
setVibrationPattern(builder, HuamiVibrationPatternNotificationType.APP_ALERTS, true, profile);
builder.queue(getQueue());
} catch (Exception ignored) {}
*/
} catch (final Exception e) {
LOG.error("onTestNewFunction failed", e);
}
}
private void setVibrationPattern(final TransactionBuilder builder, final String preferenceKey) {
// The preference key has one of the 3 prefixes
final String notificationTypeName = preferenceKey.replace(PREF_HUAMI_VIBRATION_COUNT_PREFIX, "")
.replace(PREF_HUAMI_VIBRATION_PROFILE_PREFIX, "")
.replace(PREF_HUAMI_VIBRATION_TRY_PREFIX, "")
.toUpperCase(Locale.ROOT);
final HuamiVibrationPatternNotificationType notificationType = HuamiVibrationPatternNotificationType.valueOf(notificationTypeName);
final boolean isTry = preferenceKey.startsWith(PREF_HUAMI_VIBRATION_TRY_PREFIX);
final VibrationProfile vibrationProfile = HuamiCoordinator.getVibrationProfile(getDevice().getAddress(), notificationType);
setVibrationPattern(builder, notificationType, isTry, vibrationProfile);
}
/**
* Test or set a {@link VibrationProfile}.
*
* @param builder the {@link TransactionBuilder}
* @param notificationType the notification type
* @param test test the pattern (only vibrate the band, do not set it)
* @param profile the {@link VibrationProfile}
*/
private void setVibrationPattern(final TransactionBuilder builder,
final HuamiVibrationPatternNotificationType notificationType,
final boolean test,
final VibrationProfile profile) {
final int MAX_TOTAL_LENGTH_MS = 10_000; // 10 seconds, about as long as Mi Fit allows
int totalLengthMs = 0;
// The on-off sequence, until the max total length is reached
final List<Short> onOff = new ArrayList<>(profile.getOnOffSequence().length);
for (int c = 0; c < profile.getRepeat(); c++) {
for (int i = 0; i < profile.getOnOffSequence().length; i += 2) {
final short on = (short) profile.getOnOffSequence()[i];
final short off = (short) profile.getOnOffSequence()[i + 1];
if (totalLengthMs + on + off > MAX_TOTAL_LENGTH_MS) {
LOG.warn("VibrationProfile {} too long, truncating to {} ms", profile.getId(), MAX_TOTAL_LENGTH_MS);
break;
}
onOff.add(on);
onOff.add(off);
totalLengthMs += on + off;
}
}
final ByteBuffer buf = ByteBuffer.allocate(3 + 2 * onOff.size());
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 0x20);
buf.put(notificationType.getCode());
byte flag = (byte) (onOff.size() / 2);
flag |= 0x40;
if (test) {
flag |= 0x80;
}
buf.put(flag);
for (Short time : onOff) {
buf.putShort(time);
}
writeToChunked(builder, 2, buf.array());
}
@Override

View File

@ -0,0 +1,42 @@
/* Copyright (C) 2022 José Rebelo
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.service.devices.huami;
/**
* The notification types for which vibration patterns are customizable. If these change, the
* constants in {@link nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst} need to be updated.
*/
public enum HuamiVibrationPatternNotificationType {
APP_ALERTS(0x00),
INCOMING_CALL(0x01),
INCOMING_SMS(0x02),
GOAL_NOTIFICATION(0x04),
ALARM(0x05),
IDLE_ALERTS(0x06),
EVENT_REMINDER(0x08),
FIND_BAND(0x09);
private final byte code;
HuamiVibrationPatternNotificationType(final int code) {
this.code = (byte) code;
}
public byte getCode() {
return code;
}
}

View File

@ -1,10 +1,10 @@
<!--drawable/watch-vibrate.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="45sp"
android:height="45sp"
android:viewportWidth="25"
android:viewportHeight="25">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#000000"
android:fillColor="#7E7E7E"
android:pathData="M3 17V7h2v10H3m16 0V7h2v10h-2m3-8h2v6h-2V9M0 15V9h2v6H0m17.96-3.03c0 1.9-0.89 3.6-2.28 4.7l-0.71 4.28H9l-0.73-4.28C6.88 15.57 6 13.87 6 11.97c0-1.9 0.88-3.6 2.27-4.69L9 3h5.97l0.71 4.28c1.39 1.09 2.28 2.79 2.28 4.69m-10.46 0c0 2.48 2 4.49 4.47 4.49a4.5 4.5 0 0 0 4.49-4.49c0-2.47-2.01-4.47-4.49-4.47a4.47 4.47 0 0 0-4.47 4.47z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="#7E7E7E"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#7E7E7E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#7E7E7E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7.59,5.41c-0.78,-0.78 -0.78,-2.05 0,-2.83 0.78,-0.78 2.05,-0.78 2.83,0 0.78,0.78 0.78,2.05 0,2.83 -0.79,0.79 -2.05,0.79 -2.83,0zM6,16L6,7L4,7v9c0,2.76 2.24,5 5,5h6v-2L9,19c-1.66,0 -3,-1.34 -3,-3zM20,20.07L14.93,15L11.5,15v-3.68c1.4,1.15 3.6,2.16 5.5,2.16v-2.16c-1.66,0.02 -3.61,-0.87 -4.67,-2.04l-1.4,-1.55c-0.19,-0.21 -0.43,-0.38 -0.69,-0.5 -0.29,-0.14 -0.62,-0.23 -0.96,-0.23h-0.03C8.01,7 7,8.01 7,9.25L7,15c0,1.66 1.34,3 3,3h5.07l3.5,3.5L20,20.07z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#7E7E7E"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" />
</vector>

View File

@ -471,6 +471,11 @@
<string name="pref_screen_notification_profile_low_power">Low power warning</string>
<string name="pref_screen_notification_profile_anti_loss">Anti-loss warning</string>
<string name="prefs_title_heartrate_measurement_interval">Whole day HR measurement</string>
<string name="pref_screen_notification_profile_event_reminder">Event reminder</string>
<string name="pref_screen_notification_profile_find_device">Find device</string>
<string name="pref_screen_notification_idle_alerts">Idle Alerts</string>
<string name="pref_screen_vibration_patterns_title">Vibration Patterns</string>
<string name="pref_screen_vibration_patterns_summary">Configure the vibration patterns for different notifications</string>
<string name="interval_one_minute">once a minute</string>
<string name="interval_five_minutes">every 5 minutes</string>
<string name="interval_ten_minutes">every 10 minutes</string>

View File

@ -0,0 +1,253 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_vibration"
android:key="vibration_patterns_key"
android:persistent="false"
android:summary="@string/pref_screen_vibration_patterns_summary"
android:title="@string/pref_screen_vibration_patterns_title">
<PreferenceCategory android:title="@string/pref_screen_vibration_patterns_title" />
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_settings_applications"
android:title="@string/pref_screen_notification_profile_generic"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_profile_generic" />
<ListPreference
android:defaultValue="@string/p_short"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_app_alerts"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="2"
android:inputType="number"
android:key="huami_vibration_count_app_alerts"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_app_alerts"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_phone"
android:title="@string/pref_screen_notification_profile_incoming_call"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_profile_incoming_call" />
<ListPreference
android:defaultValue="@string/p_ring"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_incoming_call"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="1"
android:inputType="number"
android:key="huami_vibration_count_incoming_call"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_incoming_call"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_message_outline"
android:title="@string/pref_screen_notification_profile_sms"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_profile_sms" />
<ListPreference
android:defaultValue="@string/p_staccato"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_incoming_sms"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="2"
android:inputType="number"
android:key="huami_vibration_count_incoming_sms"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_incoming_sms"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_star_gray"
android:title="@string/mi2_prefs_goal_notification"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/mi2_prefs_goal_notification" />
<ListPreference
android:defaultValue="@string/p_long"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_goal_notification"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="1"
android:inputType="number"
android:key="huami_vibration_count_goal_notification"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_goal_notification"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_access_alarms"
android:title="@string/vibration_profile_alarm_clock"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/vibration_profile_alarm_clock" />
<ListPreference
android:defaultValue="@string/p_alarm_clock"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_alarm"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="1"
android:inputType="number"
android:key="huami_vibration_count_alarm"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_alarm"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_seat_normal"
android:title="@string/pref_screen_notification_idle_alerts"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_idle_alerts" />
<ListPreference
android:defaultValue="@string/p_normal"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_idle_alerts"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="2"
android:inputType="number"
android:key="huami_vibration_count_idle_alerts"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_idle_alerts"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_device_set_reminders"
android:title="@string/pref_screen_notification_profile_event_reminder"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_profile_event_reminder" />
<ListPreference
android:defaultValue="@string/p_long"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_event_reminder"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="1"
android:inputType="number"
android:key="huami_vibration_count_event_reminder"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_event_reminder"
android:title="@string/vibration_try"/>
</PreferenceScreen>
<PreferenceScreen
android:key="vibration_profile_key"
android:icon="@drawable/ic_action_find_lost_device"
android:title="@string/pref_screen_notification_profile_find_device"
android:persistent="false">
<!-- workaround for missing toolbar -->
<PreferenceCategory android:title="@string/pref_screen_notification_profile_find_device" />
<ListPreference
android:defaultValue="@string/p_ring"
android:entries="@array/vibration_profile"
android:entryValues="@array/vibration_profile_values"
android:key="huami_vibration_profile_find_band"
android:title="@string/miband_prefs_vibration"
android:summary="%s" />
<EditTextPreference
android:defaultValue="3"
android:inputType="number"
android:key="huami_vibration_count_find_band"
android:maxLength="1"
android:title="@string/pref_title_notifications_repetitions" />
<Preference
android:persistent="false"
android:key="huami_vibration_try_find_band"
android:title="@string/vibration_try"/>
</PreferenceScreen>
</PreferenceScreen>
</androidx.preference.PreferenceScreen>