diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7df4110df..563016f89 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -194,6 +194,22 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="nodomain.freeyourgadget.gadgetbridge.ControlCenter" />
+
+
+
+
+
+
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
index e4d39b00e..83a4ae505 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
@@ -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 alarms = intent.getParcelableArrayListExtra("alarms");
+ mDeviceSupport.onSetAlarms(alarms);
+ break;
}
return START_STICKY;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
index c2f332782..22ca6ede9 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
@@ -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) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
index 3f4e76533..78995fd37 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
@@ -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 alarms);
+
void onSetCallState(String number, String name, GBCommand command);
void onSetMusicInfo(String artist, String album, String track);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java
new file mode 100644
index 000000000..7c542a4d6
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java
@@ -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 preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet());
+ //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 newPrefs = new HashSet(preferencesAlarmListSet);
+
+ Iterator 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];
+ }
+
+ };
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
index 9a17893b8..8ea3df39d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
@@ -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 alarms) {
+ if (checkBusy("set alarms")) {
+ return;
+ }
+ delegate.onSetAlarms(alarms);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java
new file mode 100644
index 000000000..db8a45bb7
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java
@@ -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();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java
new file mode 100644
index 000000000..ce3c147bc
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java
@@ -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 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());
+ 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());
+
+ 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);
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java
new file mode 100644
index 000000000..3abf16221
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java
@@ -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 {
+
+
+ private final Context mContext;
+ private ArrayList alarmList;
+
+ public GBAlarmListAdapter(Context context, ArrayList alarmList) {
+ super(context, 0, alarmList);
+
+ this.mContext = context;
+ this.alarmList = alarmList;
+ }
+
+ public GBAlarmListAdapter(Context context,Set preferencesAlarmListSet) {
+ super(context, 0, new ArrayList());
+
+ this.mContext = context;
+ alarmList = new ArrayList();
+
+ for (String alarmString : preferencesAlarmListSet) {
+ alarmList.add(new GBAlarm(alarmString));
+ }
+
+ Collections.sort(alarmList);
+ }
+
+ public void setAlarmList(Set preferencesAlarmListSet) {
+ alarmList = new ArrayList();
+
+ for (String alarmString : preferencesAlarmListSet) {
+ alarmList.add(new GBAlarm(alarmString));
+ }
+
+ Collections.sort(alarmList);
+ }
+
+ public ArrayList 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);
+ }
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java
index 9754a5fa0..d85cd5ebd 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java
@@ -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";
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java
index ff53ae32a..e9500f365 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java
@@ -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
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
index 40a03fb27..50356f3cf 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
@@ -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 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
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java
index c868adc0a..43b50d967 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java
@@ -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 alarms) {
+ //nothing to do ATM
+ }
}
diff --git a/app/src/main/res/layout/activity_alarm_details.xml b/app/src/main/res/layout/activity_alarm_details.xml
new file mode 100644
index 000000000..3a4d36d05
--- /dev/null
+++ b/app/src/main/res/layout/activity_alarm_details.xml
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_configure_alarms.xml b/app/src/main/res/layout/activity_configure_alarms.xml
new file mode 100644
index 000000000..3dd725a24
--- /dev/null
+++ b/app/src/main/res/layout/activity_configure_alarms.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/app/src/main/res/layout/alarm_item.xml b/app/src/main/res/layout/alarm_item.xml
new file mode 100644
index 000000000..6bfa02f7d
--- /dev/null
+++ b/app/src/main/res/layout/alarm_item.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/controlcenter_context.xml b/app/src/main/res/menu/controlcenter_context.xml
index 4002869d4..c9c07d963 100644
--- a/app/src/main/res/menu/controlcenter_context.xml
+++ b/app/src/main/res/menu/controlcenter_context.xml
@@ -6,6 +6,9 @@
+
diff --git a/app/src/main/res/menu/menu_alarm_details.xml b/app/src/main/res/menu/menu_alarm_details.xml
new file mode 100644
index 000000000..14e9fe768
--- /dev/null
+++ b/app/src/main/res/menu/menu_alarm_details.xml
@@ -0,0 +1,7 @@
+
diff --git a/app/src/main/res/menu/menu_set_alarm.xml b/app/src/main/res/menu/menu_set_alarm.xml
new file mode 100644
index 000000000..835ed8d52
--- /dev/null
+++ b/app/src/main/res/menu/menu_set_alarm.xml
@@ -0,0 +1,7 @@
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e9bfccd75..b1685f25f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -138,5 +138,17 @@
Find lost Device
Cancel to stop vibration.
ChartsActivity
-
+ Configure Alarms
+ Configure alarms
+ Alarm Details
+ Sun
+ Mon
+ Tue
+ Wed
+ Thu
+ Fri
+ Sat
+ smart wakeup
+ There was an error setting the alarms, please try again!
+ Alarms sent to device!