1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 21:06:50 +01:00

Merge pull request #81 from Freeyourgadget/set-alarm-tomerge

Set alarms on device (miband)
This commit is contained in:
Andreas Shimokawa 2015-06-30 09:43:51 +02:00
commit 594bf8c45b
20 changed files with 1028 additions and 3 deletions

View File

@ -194,6 +194,22 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="nodomain.freeyourgadget.gadgetbridge.ControlCenter" />
</activity>
<activity
android:name=".activities.ConfigureAlarms"
android:label="@string/title_activity_set_alarm"
android:parentActivityName=".SettingsActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="nodomain.freeyourgadget.gadgetbridge.SettingsActivity" />
</activity>
<activity
android:name=".activities.AlarmDetails"
android:label="@string/title_activity_alarm_details"
android:parentActivityName=".activities.ConfigureAlarms" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms" />
</activity>
</application>
</manifest>

View File

@ -21,6 +21,7 @@ import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBDevice.State;
@ -60,6 +61,7 @@ public class BluetoothCommunicationService extends Service {
public static final String ACTION_FETCH_ACTIVITY_DATA = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.fetch_activity_data";
public static final String ACTION_DISCONNECT = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.disconnect";
public static final String ACTION_FIND_DEVICE = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.find_device";
public static final String ACTION_SET_ALARMS = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.set_alarms";
public static final String EXTRA_PERFORM_PAIR = "perform_pair";
@ -265,6 +267,10 @@ public class BluetoothCommunicationService extends Service {
startForeground(GB.NOTIFICATION_ID, GB.createNotification(getString(R.string.gadgetbridge_running), this));
mStarted = true;
break;
case ACTION_SET_ALARMS:
ArrayList<GBAlarm> alarms = intent.getParcelableArrayListExtra("alarms");
mDeviceSupport.onSetAlarms(alarms);
break;
}
return START_STICKY;

View File

@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.activities.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.SleepChartActivity;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapter;
@ -230,6 +231,12 @@ public class ControlCenter extends Activity {
}
});
}
case R.id.controlcenter_configure_alarms:
if (selectedDevice != null) {
Intent startIntent;
startIntent = new Intent(ControlCenter.this, ConfigureAlarms.class);
startActivity(startIntent);
}
return true;
case R.id.controlcenter_take_screenshot:
if (selectedDevice != null) {

View File

@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge;
import android.net.Uri;
import java.util.ArrayList;
import java.util.UUID;
public interface EventHandler {
@ -13,6 +14,8 @@ public interface EventHandler {
void onSetTime(long ts);
void onSetAlarms(ArrayList<GBAlarm> alarms);
void onSetCallState(String number, String name, GBCommand command);
void onSetMusicInfo(String artist, String album, String track);

View File

@ -0,0 +1,211 @@
package nodomain.freeyourgadget.gadgetbridge;
import android.content.SharedPreferences;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARMS;
public class GBAlarm implements Parcelable, Comparable {
private int index;
private boolean enabled;
private boolean smartWakeup;
private int repetition;
private int hour;
private int minute;
public static final byte ALARM_ONCE = 0;
public static final byte ALARM_MON = 1;
public static final byte ALARM_TUE = 2;
public static final byte ALARM_WED = 4;
public static final byte ALARM_THU = 8;
public static final byte ALARM_FRI = 16;
public static final byte ALARM_SAT = 32;
public static final byte ALARM_SUN = 64;
public static final String[] DEFAULT_ALARMS = {"2,false,false,0,15,30","1,false,false,96,8,0","0,false,true,31,7,30"};
public GBAlarm(int index, boolean enabled, boolean smartWakeup, byte repetition, int hour, int minute) {
this.index = index;
this.enabled = enabled;
this.smartWakeup = smartWakeup;
this.repetition = repetition;
this.hour = hour;
this.minute = minute;
}
public GBAlarm(String fromPreferences){
String[] tokens = fromPreferences.split(",");
//TODO: sanify the string!
this.index = Integer.parseInt(tokens[0]);
this.enabled = Boolean.parseBoolean(tokens[1]);
this.smartWakeup = Boolean.parseBoolean(tokens[2]);
this.repetition = Integer.parseInt(tokens[3]);
this.hour = Integer.parseInt(tokens[4]);
this.minute = Integer.parseInt(tokens[5]);
}
private static GBAlarm readFromParcel(Parcel pc) {
int index = pc.readInt();
boolean enabled = Boolean.parseBoolean(pc.readString());
boolean smartWakeup = Boolean.parseBoolean(pc.readString());
int repetition = pc.readInt();
int hour = pc.readInt();
int minute = pc.readInt();
return new GBAlarm(index, enabled, smartWakeup, (byte)repetition, hour, minute);
}
@Override
public boolean equals(Object o) {
if (o instanceof GBAlarm) {
GBAlarm comp = (GBAlarm)o;
return comp.getIndex() == getIndex();
} else {
return false;
}
}
@Override
public int hashCode() {
return getIndex();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.index);
dest.writeString(String.valueOf(this.enabled));
dest.writeString(String.valueOf(this.smartWakeup));
dest.writeInt(this.repetition);
dest.writeInt(this.hour);
dest.writeInt(this.minute);
}
@Override
public int compareTo(Object another) {
if (this.getIndex() < ((GBAlarm)another).getIndex()) {
return -1;
}else if (this.getIndex() > ((GBAlarm)another).getIndex()) {
return 1;
}
return 0;
}
public int getIndex() {
return this.index;
}
public String getTime() {
return String.format("%02d",this.hour) + ":" + String.format("%02d",this.minute);
}
public int getHour(){
return this.hour;
}
public int getMinute(){
return this.minute;
}
public Calendar getAlarmCal() {
Calendar alarm = Calendar.getInstance();
alarm.set(Calendar.HOUR_OF_DAY, this.hour);
alarm.set(Calendar.MINUTE, this.minute);
return alarm;
}
public boolean isEnabled() {
return this.enabled;
}
public boolean isSmartWakeup() {
return this.smartWakeup;
}
public boolean getRepetition(int dow) {
return (this.repetition & dow) > 0;
}
public int getRepetitionMask() {
return this.repetition;
}
public String toPreferences() {
return String.valueOf(this.index)+','+
String.valueOf(this.enabled)+','+
String.valueOf(this.smartWakeup)+','+
String.valueOf(this.repetition)+','+
String.valueOf(this.hour)+','+
String.valueOf(this.minute);
}
public void setSmartWakeup(boolean smartWakeup) {
this.smartWakeup = smartWakeup;
}
public void setRepetition(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) {
this.repetition = ALARM_ONCE |
(mon ? ALARM_MON : 0) |
(tue ? ALARM_TUE : 0) |
(wed ? ALARM_WED : 0) |
(thu ? ALARM_THU : 0) |
(fri ? ALARM_FRI : 0) |
(sat ? ALARM_SAT : 0) |
(sun ? ALARM_SUN : 0);
}
public void setHour(int hour) {
this.hour = hour;
}
public void setMinute(int minute) {
this.minute = minute;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void store() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Set<String> preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
//the old Set cannot be updated in place see http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet%28java.lang.String,%20java.util.Set%3Cjava.lang.String%3E%29
Set<String> newPrefs = new HashSet<String>(preferencesAlarmListSet);
Iterator<String> iterator = newPrefs.iterator();
while (iterator.hasNext()) {
String alarmString = iterator.next();
if(this.equals(new GBAlarm(alarmString))) {
iterator.remove();
break;
}
}
newPrefs.add(this.toPreferences());
sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, newPrefs).commit();
return;
}
public static final Creator CREATOR = new Creator() {
public GBAlarm createFromParcel(Parcel in) {
return readFromParcel(in);
}
public GBAlarm[] newArray(int size) {
return new GBAlarm[size];
}
};
}

View File

@ -7,6 +7,7 @@ import android.net.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.UUID;
/**
@ -226,4 +227,12 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
delegate.onScreenshotReq();
}
@Override
public void onSetAlarms(ArrayList<GBAlarm> alarms) {
if (checkBusy("set alarms")) {
return;
}
delegate.onSetAlarms(alarms);
}
}

View File

@ -0,0 +1,81 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.app.Activity;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.TimePicker;
import nodomain.freeyourgadget.gadgetbridge.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
public class AlarmDetails extends Activity {
private GBAlarm alarm;
private TimePicker timePicker;
private CheckBox cbSmartWakeup;
private CheckBox cbMonday;
private CheckBox cbTuesday;
private CheckBox cbWednesday;
private CheckBox cbThursday;
private CheckBox cbFriday;
private CheckBox cbSaturday;
private CheckBox cbSunday;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_details);
Parcelable p = getIntent().getExtras().getParcelable("alarm");
alarm = (GBAlarm) p;
timePicker = (TimePicker) findViewById(R.id.alarm_time_picker);
cbSmartWakeup = (CheckBox) findViewById(R.id.alarm_cb_smart_wakeup);
cbMonday = (CheckBox) findViewById(R.id.alarm_cb_mon);
cbTuesday = (CheckBox) findViewById(R.id.alarm_cb_tue);
cbWednesday = (CheckBox) findViewById(R.id.alarm_cb_wed);
cbThursday = (CheckBox) findViewById(R.id.alarm_cb_thu);
cbFriday = (CheckBox) findViewById(R.id.alarm_cb_fri);
cbSaturday = (CheckBox) findViewById(R.id.alarm_cb_sat);
cbSunday = (CheckBox) findViewById(R.id.alarm_cb_sun);
timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext()));
timePicker.setCurrentHour(alarm.getHour());
timePicker.setCurrentMinute(alarm.getMinute());
cbSmartWakeup.setChecked(alarm.isSmartWakeup());
cbMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON));
cbTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE));
cbWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED));
cbThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU));
cbFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI));
cbSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT));
cbSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// back button
updateAlarm();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateAlarm() {
alarm.setSmartWakeup(cbSmartWakeup.isChecked());
alarm.setRepetition(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked());
alarm.setHour(timePicker.getCurrentHour());
alarm.setMinute(timePicker.getCurrentMinute());
alarm.store();
}
}

View File

@ -0,0 +1,86 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.app.ListActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.MenuItem;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.BluetoothCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter;
import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARMS;
public class ConfigureAlarms extends ListActivity {
private GBAlarmListAdapter mGBAlarmListAdapter;
private Set<String> preferencesAlarmListSet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_configure_alarms);
getActionBar().setDisplayHomeAsUpEnabled(true);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
if (preferencesAlarmListSet.isEmpty()) {
//initialize the preferences
preferencesAlarmListSet = new HashSet<>(Arrays.asList(GBAlarm.DEFAULT_ALARMS));
sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, preferencesAlarmListSet).commit();
}
mGBAlarmListAdapter = new GBAlarmListAdapter(this, preferencesAlarmListSet);
setListAdapter(mGBAlarmListAdapter);
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
mGBAlarmListAdapter.setAlarmList(preferencesAlarmListSet);
mGBAlarmListAdapter.notifyDataSetChanged();
sendAlarmsToDevice();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// back button
sendAlarmsToDevice();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public void configureAlarm(GBAlarm alarm) {
Intent startIntent;
startIntent = new Intent(getApplicationContext(), AlarmDetails.class);
startIntent.putExtra("alarm", alarm);
startActivity(startIntent);
}
private void sendAlarmsToDevice() {
Intent startIntent = new Intent(ConfigureAlarms.this, BluetoothCommunicationService.class);
startIntent.putParcelableArrayListExtra("alarms", mGBAlarmListAdapter.getAlarmList());
startIntent.setAction(BluetoothCommunicationService.ACTION_SET_ALARMS);
startService(startIntent);
}
}

View File

@ -0,0 +1,153 @@
package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
public class GBAlarmListAdapter extends ArrayAdapter<GBAlarm> {
private final Context mContext;
private ArrayList<GBAlarm> alarmList;
public GBAlarmListAdapter(Context context, ArrayList<GBAlarm> alarmList) {
super(context, 0, alarmList);
this.mContext = context;
this.alarmList = alarmList;
}
public GBAlarmListAdapter(Context context,Set<String> preferencesAlarmListSet) {
super(context, 0, new ArrayList<GBAlarm>());
this.mContext = context;
alarmList = new ArrayList<GBAlarm>();
for (String alarmString : preferencesAlarmListSet) {
alarmList.add(new GBAlarm(alarmString));
}
Collections.sort(alarmList);
}
public void setAlarmList(Set<String> preferencesAlarmListSet) {
alarmList = new ArrayList<GBAlarm>();
for (String alarmString : preferencesAlarmListSet) {
alarmList.add(new GBAlarm(alarmString));
}
Collections.sort(alarmList);
}
public ArrayList<GBAlarm> getAlarmList() {
return alarmList;
}
public void update(GBAlarm alarm) {
for (GBAlarm a : alarmList) {
if(alarm.equals(a)) {
a = alarm;
}
}
alarm.store();
}
@Override
public int getCount() {
if (alarmList != null) {
return alarmList.size();
}
return 0;
}
@Override
public GBAlarm getItem(int position) {
if (alarmList != null) {
return alarmList.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
if (alarmList != null) {
return alarmList.get(position).getIndex();
}
return 0;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
final GBAlarm alarm = getItem(position);
if (view == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.alarm_item, parent, false);
}
TextView alarmTime = (TextView) view.findViewById(R.id.alarm_item_time);
Switch isEnabled = (Switch) view.findViewById(R.id.alarm_item_toggle);
TextView isSmartWakeup = (TextView) view.findViewById(R.id.alarm_smart_wakeup);
highlightDay((TextView) view.findViewById(R.id.alarm_item_sunday), alarm.getRepetition(GBAlarm.ALARM_SUN));
highlightDay((TextView) view.findViewById(R.id.alarm_item_monday), alarm.getRepetition(GBAlarm.ALARM_MON));
highlightDay((TextView) view.findViewById(R.id.alarm_item_tuesday), alarm.getRepetition(GBAlarm.ALARM_TUE));
highlightDay((TextView) view.findViewById(R.id.alarm_item_wednesday), alarm.getRepetition(GBAlarm.ALARM_WED));
highlightDay((TextView) view.findViewById(R.id.alarm_item_thursday), alarm.getRepetition(GBAlarm.ALARM_THU));
highlightDay((TextView) view.findViewById(R.id.alarm_item_friday), alarm.getRepetition(GBAlarm.ALARM_FRI));
highlightDay((TextView) view.findViewById(R.id.alarm_item_saturday), alarm.getRepetition(GBAlarm.ALARM_SAT));
isEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
alarm.setEnabled(isChecked);
update(alarm);
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((ConfigureAlarms)mContext).configureAlarm(alarm);
}
});
alarmTime.setText(alarm.getTime());
isEnabled.setChecked(alarm.isEnabled());
if(alarm.isSmartWakeup()) {
isSmartWakeup.setVisibility(TextView.VISIBLE);
} else {
isSmartWakeup.setVisibility(TextView.GONE);
}
return view;
}
private void highlightDay(TextView view, boolean isOn) {
if (isOn) {
view.setTextColor(Color.BLUE);
} else {
view.setTextColor(Color.BLACK);
}
}
}

View File

@ -15,6 +15,7 @@ public final class MiBandConst {
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_ALARMS = "mi_alarms";
public static final String ORIGIN_SMS = "sms";
public static final String ORIGIN_INCOMING_CALL = "incoming_call";

View File

@ -134,6 +134,9 @@ public class MiBandService {
public static final byte COMMAND_CONFIRM_ACTIVITY_DATA_TRANSFER_COMPLETE = 0xa;
public static final byte COMMAND_FETCH_DATA = 0x6;
public static final byte COMMAND_SET_TIMER = 0x4;
/*
@ -152,8 +155,6 @@ public class MiBandService {
public static final COMMAND_SET_REALTIME_STEPS_NOTIFICATION = 0x3t
public static final COMMAND_SET_TIMER = 0x4t
public static final COMMAND_SET_WEAR_LOCATION = 0xft
public static final COMMAND_STOP_SYNC_DATA = 0x11t

View File

@ -6,18 +6,21 @@ import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBCommand;
import nodomain.freeyourgadget.gadgetbridge.GBDevice.State;
@ -323,6 +326,22 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
return VibrationProfile.getProfile(profileId, (byte) (repeat & 0xfff));
}
@Override
public void onSetAlarms(ArrayList<GBAlarm> alarms) {
try {
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
TransactionBuilder builder = performInitialized("Set alarm");
for (GBAlarm alarm : alarms) {
queueAlarm(alarm, builder, characteristic);
}
builder.queue(getQueue());
Toast.makeText(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT).show();
} catch (IOException ex) {
Toast.makeText(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_failed), Toast.LENGTH_LONG).show();
LOG.error("Unable to set alarms on MI device", ex);
}
}
@Override
public void onSMS(String from, String body) {
performPreferredNotification("sms received", ORIGIN_SMS, null);
@ -544,6 +563,25 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
}
private void queueAlarm(GBAlarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) {
Calendar alarmCal = alarm.getAlarmCal();
byte[] alarmMessage = new byte[] {
(byte) MiBandService.COMMAND_SET_TIMER,
(byte) alarm.getIndex(),
(byte) (alarm.isEnabled() ? 1: 0),
(byte) (alarmCal.get(Calendar.YEAR) - 2000),
(byte) alarmCal.get(Calendar.MONTH),
(byte) alarmCal.get(Calendar.DATE),
(byte) alarmCal.get(Calendar.HOUR_OF_DAY),
(byte) alarmCal.get(Calendar.MINUTE),
(byte) alarmCal.get(Calendar.SECOND),
(byte) (alarm.isSmartWakeup() ? 30 : 0),
(byte) alarm.getRepetitionMask()
};
builder.write(characteristic, alarmMessage);
}
private void handleActivityNotif(byte[] value) {
if (value.length == 11) {
// byte 0 is the data type: 1 means that each minute is represented by a triplet of bytes

View File

@ -2,7 +2,10 @@ package nodomain.freeyourgadget.gadgetbridge.pebble;
import android.net.Uri;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.AbstractBTDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceProtocol;
@ -38,4 +41,9 @@ public class PebbleSupport extends AbstractBTDeviceSupport {
public synchronized PebbleIoThread getDeviceIOThread() {
return (PebbleIoThread) super.getDeviceIOThread();
}
@Override
public void onSetAlarms(ArrayList<GBAlarm> alarms) {
//nothing to do ATM
}
}

View File

@ -0,0 +1,251 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.AlarmDetails">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TimePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_time_picker"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:timePickerMode="clock"
android:layout_weight="1" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_smart_wakeup"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_smart_wakeup"
android:id="@+id/alarm_label_smart_wakeup"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_smart_wakeup"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/dowSelector">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_mon"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_mon_short"
android:id="@+id/alarm_label_cb_mon"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_mon"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_tue"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_tue_short"
android:id="@+id/alarm_label_cb_tue"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_tue"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_wed"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_wed_short"
android:id="@+id/alarm_label_cb_wed"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_wed"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_thu"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_thu_short"
android:id="@+id/alarm_label_cb_thu"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_thu"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_fri"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_fri_short"
android:id="@+id/alarm_label_cb_fri"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_fri"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_sat"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_sat_short"
android:id="@+id/alarm_label_cb_sat"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_sat"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/alarm_cb_sun"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/alarm_sun_short"
android:id="@+id/alarm_label_cb_sun"
android:layout_gravity="center_horizontal|top"
android:labelFor="@id/alarm_cb_sun"
android:gravity="center_horizontal|top"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,16 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms">
<ListView
android:descendantFocusability="blocksDescendants"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@android:id/list"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp" >
<TextView
android:id="@+id/alarm_item_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="00:00"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(Smart)"
android:layout_toRightOf="@+id/alarm_item_time"
android:id="@+id/alarm_smart_wakeup"
android:visibility="invisible"
android:layout_alignBaseline="@+id/alarm_item_time" />
<TextView
android:id="@+id/alarm_item_monday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_mon_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_tuesday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_monday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_tue_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_wednesday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_tuesday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_wed_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_thursday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_wednesday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_thu_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_friday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_thursday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_fri_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_saturday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_friday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_sat_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/alarm_item_sunday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/alarm_item_saturday"
android:layout_below="@+id/alarm_item_time"
android:layout_marginLeft="4dp"
android:text="@string/alarm_sun_short"
android:textAppearance="?android:attr/textAppearanceSmall" />
<Switch
android:id="@+id/alarm_item_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
</FrameLayout>

View File

@ -6,6 +6,9 @@
<item
android:id="@+id/controlcenter_start_sleepmonitor"
android:title="@string/controlcenter_start_sleepmonitor"/>
<item
android:id="@+id/controlcenter_configure_alarms"
android:title="@string/controlcenter_start_configure_alarms"/>
<item
android:id="@+id/controlcenter_find_device"
android:title="@string/controlcenter_find_device"/>

View File

@ -0,0 +1,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.AlarmDetails">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>

View File

@ -0,0 +1,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>

View File

@ -138,5 +138,17 @@
<string name="control_center_find_lost_device">Find lost Device</string>
<string name="control_center_cancel_to_stop_vibration">Cancel to stop vibration.</string>
<string name="title_activity_charts">ChartsActivity</string>
<string name="title_activity_set_alarm">Configure Alarms</string>
<string name="controlcenter_start_configure_alarms">Configure alarms</string>
<string name="title_activity_alarm_details">Alarm Details</string>
<string name="alarm_sun_short">Sun</string>
<string name="alarm_mon_short">Mon</string>
<string name="alarm_tue_short">Tue</string>
<string name="alarm_wed_short">Wed</string>
<string name="alarm_thu_short">Thu</string>
<string name="alarm_fri_short">Fri</string>
<string name="alarm_sat_short">Sat</string>
<string name="alarm_smart_wakeup">smart wakeup</string>
<string name="user_feedback_miband_set_alarms_failed">There was an error setting the alarms, please try again!</string>
<string name="user_feedback_miband_set_alarms_ok">Alarms sent to device!</string>
</resources>