diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index 354c6e275..8cf3e0b07 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -345,6 +345,7 @@ public class GBDaoGenerator { private static void addAlarms(Schema schema, Entity user, Entity device) { Entity alarm = addEntity(schema, "Alarm"); + alarm.implementsInterface("nodomain.freeyourgadget.gadgetbridge.model.Alarm"); Property deviceId = alarm.addLongProperty("deviceId").notNull().getProperty(); Property userId = alarm.addLongProperty("userId").notNull().getProperty(); Property position = alarm.addIntProperty("position").notNull().getProperty(); @@ -355,8 +356,11 @@ public class GBDaoGenerator { indexUnique.makeUnique(); alarm.addIndex(indexUnique); alarm.addBooleanProperty("enabled").notNull(); - alarm.addBooleanProperty("smartAlarm").notNull(); - alarm.addIntProperty("repetition").notNull(); + alarm.addBooleanProperty("smartWakeup").notNull(); + alarm.addIntProperty("repetition").notNull().codeBeforeGetter( + "public boolean isRepetitive() { return getRepetition() != ALARM_ONCE; } " + + "public boolean getRepetition(int dow) { return (this.repetition & dow) > 0; }" + ); alarm.addIntProperty("hour").notNull(); alarm.addIntProperty("minute").notNull(); alarm.addToOne(user, userId); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java index cb725a0ef..98815091d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java @@ -31,7 +31,6 @@ import java.util.Calendar; import java.util.GregorianCalendar; import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.util.GB; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java index c4f69881f..af7ddbd60 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -26,14 +26,16 @@ import android.widget.TimePicker; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.entities.Alarm; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; public class AlarmDetails extends AbstractGBActivity { - private GBAlarm alarm; + private Alarm alarm; private TimePicker timePicker; private CheckedTextView cbSmartWakeup; private CheckedTextView cbMonday; @@ -50,7 +52,7 @@ public class AlarmDetails extends AbstractGBActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_alarm_details); - alarm = getIntent().getParcelableExtra("alarm"); + alarm = (Alarm) getIntent().getSerializableExtra(nodomain.freeyourgadget.gadgetbridge.model.Alarm.EXTRA_ALARM); device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE); timePicker = findViewById(R.id.alarm_time_picker); @@ -109,17 +111,17 @@ public class AlarmDetails extends AbstractGBActivity { timePicker.setCurrentHour(alarm.getHour()); timePicker.setCurrentMinute(alarm.getMinute()); - cbSmartWakeup.setChecked(alarm.isSmartWakeup()); + cbSmartWakeup.setChecked(alarm.getSmartWakeup()); int smartAlarmVisibility = supportsSmartWakeup() ? View.VISIBLE : View.GONE; cbSmartWakeup.setVisibility(smartAlarmVisibility); - 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)); + cbMonday.setChecked(alarm.getRepetition(Alarm.ALARM_MON)); + cbTuesday.setChecked(alarm.getRepetition(Alarm.ALARM_TUE)); + cbWednesday.setChecked(alarm.getRepetition(Alarm.ALARM_WED)); + cbThursday.setChecked(alarm.getRepetition(Alarm.ALARM_THU)); + cbFriday.setChecked(alarm.getRepetition(Alarm.ALARM_FRI)); + cbSaturday.setChecked(alarm.getRepetition(Alarm.ALARM_SAT)); + cbSunday.setChecked(alarm.getRepetition(Alarm.ALARM_SUN)); } @@ -144,10 +146,11 @@ public class AlarmDetails extends AbstractGBActivity { private void updateAlarm() { alarm.setSmartWakeup(supportsSmartWakeup() && cbSmartWakeup.isChecked()); - alarm.setRepetition(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked()); + int repetitionMask = AlarmUtils.createRepetitionMassk(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked()); + alarm.setRepetition(repetitionMask); alarm.setHour(timePicker.getCurrentHour()); alarm.setMinute(timePicker.getCurrentMinute()); - alarm.store(); + DBHelper.store(alarm); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java index 6259f0e2f..4ff3a3194 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -19,31 +19,33 @@ package nodomain.freeyourgadget.gadgetbridge.activities; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.MenuItem; -import java.util.ArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.List; -import de.greenrobot.dao.query.QueryBuilder; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; -import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.entities.Alarm; -import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; +import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; -import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class ConfigureAlarms extends AbstractGBActivity { + private static final Logger LOG = LoggerFactory.getLogger(ConfigureAlarms.class); private static final int REQ_CONFIGURE_ALARM = 1; @@ -84,42 +86,46 @@ public class ConfigureAlarms extends AbstractGBActivity { } } + /** + * Reads the available alarms from the database and updates the view afterwards. + */ private void updateAlarmsFromDB() { - Prefs prefs = GBApplication.getPrefs(); - int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0); - - DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice); - int alarmSlots = coordinator.getAlarmSlotCount(); - - Long deviceId; - List allAlarms = null; - try (DBHandler db = GBApplication.acquireDB()) { - AlarmDao alarmDao = db.getDaoSession().getAlarmDao(); - Device dbDevice = DBHelper.findDevice(gbDevice, db.getDaoSession()); - deviceId = dbDevice.getId(); - QueryBuilder qb = alarmDao.queryBuilder(); - qb.where(AlarmDao.Properties.DeviceId.eq(deviceId)).orderAsc(AlarmDao.Properties.Position).limit(alarmSlots - reservedSlots); - allAlarms = qb.build().list(); - } catch (Exception e) { - return; + List alarms = DBHelper.getAlarms(getGbDevice()); + if (alarms.isEmpty()) { + alarms = AlarmUtils.readAlarmsFromPrefs(getGbDevice()); + storeMigratedAlarms(alarms); } + addMissingAlarms(alarms); - List gbAlarms = new ArrayList<>(); - if (allAlarms != null) { - for (Alarm alarm : allAlarms) { - gbAlarms.add(new GBAlarm(deviceId, alarm.getPosition(), alarm.getEnabled(), - alarm.getSmartAlarm(), alarm.getRepetition(), alarm.getHour(), alarm.getMinute())); + mGBAlarmListAdapter.setAlarmList(alarms); + mGBAlarmListAdapter.notifyDataSetChanged(); + } + + private void storeMigratedAlarms(List alarms) { + for (Alarm alarm : alarms) { + DBHelper.store(alarm); + } + } + + private void addMissingAlarms(List alarms) { + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(getGbDevice()); + int supportedNumAlarms = coordinator.getAlarmSlotCount(); + if (supportedNumAlarms > alarms.size()) { + try (DBHandler db = GBApplication.acquireDB()) { + DaoSession daoSession = db.getDaoSession(); + Device device = DBHelper.getDevice(getGbDevice(), daoSession); + User user = DBHelper.getUser(daoSession); + while (supportedNumAlarms > alarms.size()) { + alarms.add(createDefaultAlarm(device, user, alarms.size())); + } + } catch (Exception e) { + LOG.error("Error accessing database", e); } } - int hour = 5; - while (gbAlarms.size() < alarmSlots) { - GBAlarm gbAlarm = new GBAlarm(deviceId, gbAlarms.size(), false, false, 31, hour++, 30); - gbAlarms.add(gbAlarm); - gbAlarm.store(); - } + } - mGBAlarmListAdapter.setAlarmList(gbAlarms); - mGBAlarmListAdapter.notifyDataSetChanged(); + private Alarm createDefaultAlarm(@NonNull Device device, @NonNull User user, int position) { + return new Alarm(device.getId(), user.getId(), position, false, false,0, 6, 30); } @Override @@ -133,10 +139,10 @@ public class ConfigureAlarms extends AbstractGBActivity { return super.onOptionsItemSelected(item); } - public void configureAlarm(GBAlarm alarm) { + public void configureAlarm(Alarm alarm) { avoidSendAlarmsToDevice = true; Intent startIntent = new Intent(getApplicationContext(), AlarmDetails.class); - startIntent.putExtra("alarm", alarm); + startIntent.putExtra(Alarm.EXTRA_ALARM, alarm); startIntent.putExtra(GBDevice.EXTRA_DEVICE, getGbDevice()); startActivityForResult(startIntent, REQ_CONFIGURE_ALARM); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java index 755d01a73..7f7ce047b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -35,33 +35,32 @@ import java.util.List; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; -import nodomain.freeyourgadget.gadgetbridge.model.Alarm; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.entities.Alarm; +import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; /** * Adapter for displaying GBAlarm instances. */ public class GBAlarmListAdapter extends RecyclerView.Adapter { - private final Context mContext; - private List alarmList; + private ArrayList alarmList; public GBAlarmListAdapter(Context context) { this.mContext = context; } - public void setAlarmList(List alarmList) { - this.alarmList = alarmList; + public void setAlarmList(List alarms) { + this.alarmList = new ArrayList<>(alarms); } - public ArrayList getAlarmList() { - return (ArrayList) alarmList; + public ArrayList getAlarmList() { + return alarmList; } - - public void update(GBAlarm alarm) { - alarm.store(); + private void updateInDB(Alarm alarm) { + DBHelper.store(alarm); } @NonNull @@ -74,7 +73,7 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter query = deviceDao.queryBuilder().where(DeviceDao.Properties.Identifier.eq(gbDevice.getAddress())).build(); @@ -561,6 +572,49 @@ public class DBHelper { return tag; } + /** + * Returns all user-configurable alarms for the given user and device. The list is sorted by + * {@link Alarm#position}. Calendar events that may also be modeled as alarms are not stored + * in the database and hence not returned by this method. + * @param gbDevice the device for which the alarms shall be loaded + * @return the list of alarms for the given device + */ + @NonNull + public static List getAlarms(@NonNull GBDevice gbDevice) { + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice); + Prefs prefs = GBApplication.getPrefs(); + // TODO: this alarm reservation is a device dependent detail + int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0); + int alarmSlots = coordinator.getAlarmSlotCount(); + + try (DBHandler db = GBApplication.acquireDB()) { + DaoSession daoSession = db.getDaoSession(); + User user = getUser(daoSession); + Device dbDevice = DBHelper.findDevice(gbDevice, daoSession); + if (dbDevice != null) { + AlarmDao alarmDao = daoSession.getAlarmDao(); + Long deviceId = dbDevice.getId(); + QueryBuilder qb = alarmDao.queryBuilder(); + qb.where( + AlarmDao.Properties.UserId.eq(user.getId()), + AlarmDao.Properties.DeviceId.eq(deviceId)).orderAsc(AlarmDao.Properties.Position).limit(alarmSlots - reservedSlots); + return qb.build().list(); + } + } catch (Exception e) { + LOG.warn("Error reading alarms from db", e); + } + return Collections.emptyList(); + } + + public static void store(Alarm alarm) { + try (DBHandler db = GBApplication.acquireDB()) { + DaoSession daoSession = db.getDaoSession(); + daoSession.insertOrReplace(alarm); + } catch (Exception e) { + LOG.error("Error acquiring database", e); + } + } + public static void clearSession() { try (DBHandler dbHandler = GBApplication.acquireDB()) { DaoSession session = dbHandler.getDaoSession(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBAlarm.java deleted file mode 100644 index 0ba597173..000000000 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBAlarm.java +++ /dev/null @@ -1,215 +0,0 @@ -/* Copyright (C) 2015-2018 Andreas Shimokawa, Carsten Pfeiffer, Daniele - Gobbetti - - 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 . */ -package nodomain.freeyourgadget.gadgetbridge.impl; - -import android.os.Parcel; -import android.support.annotation.NonNull; - -import java.util.Calendar; -import java.util.Locale; - -import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; -import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; -import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; -import nodomain.freeyourgadget.gadgetbridge.model.Alarm; - - -public class GBAlarm implements Alarm { - - private final int index; - private boolean enabled; - private boolean smartWakeup; - private int repetition; - private int hour; - private int minute; - private long deviceId; - - public GBAlarm(Long deviceId, int index, boolean enabled, boolean smartWakeup, int repetition, int hour, int minute) { - this.deviceId = deviceId; - this.index = index; - this.enabled = enabled; - this.smartWakeup = smartWakeup; - this.repetition = repetition; - this.hour = hour; - this.minute = minute; - } - - public static GBAlarm createSingleShot(long deviceId, int index, boolean smartWakeup, Calendar calendar) { - return new GBAlarm(deviceId, index, true, smartWakeup, Alarm.ALARM_ONCE, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE)); - } - - private static GBAlarm readFromParcel(Parcel pc) { - long deviceId = pc.readLong(); - 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(deviceId, index, enabled, smartWakeup, 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.writeLong(deviceId); - 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(@NonNull Alarm another) { - if (this.getIndex() < another.getIndex()) { - return -1; - } else if (this.getIndex() > another.getIndex()) { - return 1; - } - return 0; - } - - @Override - public int getIndex() { - return this.index; - } - - @Override - public String getTime() { - return String.format(Locale.US, "%02d", this.hour) + ":" + String.format(Locale.US, "%02d", this.minute); - } - - public int getHour() { - return this.hour; - } - - public int getMinute() { - return this.minute; - } - - @Override - public Calendar getAlarmCal() { - - Calendar alarm = Calendar.getInstance(); - Calendar now = Calendar.getInstance(); - alarm.set(Calendar.HOUR_OF_DAY, this.hour); - alarm.set(Calendar.MINUTE, this.minute); - if (now.after(alarm) && repetition == ALARM_ONCE) { - //if the alarm is in the past set it to tomorrow - alarm.add(Calendar.DATE, 1); - } - return alarm; - } - - @Override - public boolean isEnabled() { - return this.enabled; - } - - @Override - public boolean isSmartWakeup() { - return this.smartWakeup; - } - - @Override - public boolean getRepetition(int dow) { - return (this.repetition & dow) > 0; - } - - @Override - public int getRepetitionMask() { - return this.repetition; - } - - @Override - public boolean isRepetitive() { - return getRepetitionMask() != ALARM_ONCE; - } - - 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 = (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() { - try (DBHandler db = GBApplication.acquireDB()) { - DaoSession daoSession = db.getDaoSession(); - Long userId = DBHelper.getUser(daoSession).getId(); - nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm(deviceId, userId, index, enabled, smartWakeup, repetition, hour, minute); - daoSession.insertOrReplace(alarm); - } catch (Exception e) { - // LOG.error("Error acquiring database", e); - } - } - - public static final Creator CREATOR = new Creator() { - @Override - public GBAlarm createFromParcel(Parcel in) { - return readFromParcel(in); - } - - @Override - public GBAlarm[] newArray(int size) { - return new GBAlarm[size]; - } - - }; -} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index be917e9be..b4d91b31d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -176,7 +176,7 @@ public class GBDeviceService implements DeviceService { @Override public void onSetAlarms(ArrayList alarms) { Intent intent = createIntent().setAction(ACTION_SET_ALARMS) - .putParcelableArrayListExtra(EXTRA_ALARMS, alarms); + .putExtra(EXTRA_ALARMS, alarms); invokeService(intent); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Alarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Alarm.java index f977ca14a..57aded93d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Alarm.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Alarm.java @@ -16,11 +16,14 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.model; -import android.os.Parcelable; +import java.io.Serializable; -import java.util.Calendar; +public interface Alarm extends Serializable { + /** + * The {@link android.os.Bundle} name for transferring pacreled alarms. + */ + String EXTRA_ALARM = "alarm"; -public interface Alarm extends Parcelable, Comparable { byte ALARM_ONCE = 0; byte ALARM_MON = 1; byte ALARM_TUE = 2; @@ -30,19 +33,19 @@ public interface Alarm extends Parcelable, Comparable { byte ALARM_SAT = 32; byte ALARM_SUN = 64; - int getIndex(); + int getPosition(); - Calendar getAlarmCal(); + boolean getEnabled(); - String getTime(); + boolean getSmartWakeup(); - boolean isEnabled(); - - boolean isSmartWakeup(); - - int getRepetitionMask(); + int getRepetition(); boolean isRepetitive(); boolean getRepetition(int dow); -} + + int getHour(); + + int getMinute(); +} \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index 742be6d2e..3f5077278 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -548,7 +548,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere } break; case ACTION_SET_ALARMS: - ArrayList alarms = intent.getParcelableArrayListExtra(EXTRA_ALARMS); + ArrayList alarms = (ArrayList) intent.getSerializableExtra(EXTRA_ALARMS); mDeviceSupport.onSetAlarms(alarms); break; case ACTION_ENABLE_REALTIME_STEPS: { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java index 7460cbf9f..65b666c39 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java @@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; @@ -430,13 +431,13 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { for (Alarm alarm : alarms) { - if (!alarm.isEnabled()) + if (!alarm.getEnabled()) continue; - if (alarm.isSmartWakeup()) //Not available + if (alarm.getSmartWakeup()) //Not available continue; - Calendar t = alarm.getAlarmCal(); + Calendar t = AlarmUtils.toCalendar(alarm); setAlarm(builder, t); builder.queue(getQueue()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index c8810ed24..377d837b5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -72,11 +72,11 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService; import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; +import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.User; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; @@ -113,6 +113,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.Upd import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.RealtimeSamplesSupport; import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils; @@ -614,7 +615,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { TransactionBuilder builder = performInitialized("Set alarm"); boolean anyAlarmEnabled = false; for (Alarm alarm : alarms) { - anyAlarmEnabled |= alarm.isEnabled(); + anyAlarmEnabled |= alarm.getEnabled(); queueAlarm(alarm, builder, characteristic); } builder.queue(getQueue()); @@ -1402,29 +1403,29 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { * @param characteristic */ private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) { - Calendar calendar = alarm.getAlarmCal(); + Calendar calendar = AlarmUtils.toCalendar(alarm); DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice); int maxAlarms = coordinator.getAlarmSlotCount(); - if (alarm.getIndex() >= maxAlarms) { - if (alarm.isEnabled()) { + if (alarm.getPosition() >= maxAlarms) { + if (alarm.getEnabled()) { GB.toast(getContext(), "Only " + maxAlarms + " alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN); } return; } int base = 0; - if (alarm.isEnabled()) { + if (alarm.getEnabled()) { base = 128; } - int daysMask = alarm.getRepetitionMask(); + int daysMask = alarm.getRepetition(); if (!alarm.isRepetitive()) { daysMask = 128; } byte[] alarmMessage = new byte[] { (byte) 0x2, // TODO what is this? - (byte) (base + alarm.getIndex()), // 128 is the base, alarm slot is added + (byte) (base + alarm.getPosition()), // 128 is the base, alarm slot is added (byte) calendar.get(Calendar.HOUR_OF_DAY), (byte) calendar.get(Calendar.MINUTE), (byte) daysMask, @@ -1477,14 +1478,6 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { CalendarEvents upcomingEvents = new CalendarEvents(); List mEvents = upcomingEvents.getCalendarEventList(getContext()); - Long deviceId; - try (DBHandler handler = GBApplication.acquireDB()) { - DaoSession session = handler.getDaoSession(); - deviceId = DBHelper.getDevice(getDevice(), session).getId(); - } catch (Exception e) { - LOG.error("Could not acquire DB", e); - return this; - } int iteration = 0; for (CalendarEvents.CalendarEvent mEvt : mEvents) { @@ -1494,7 +1487,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { int slotToUse = 2 - iteration; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(mEvt.getBegin()); - Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar); + Alarm alarm = AlarmUtils.createSingleShot(slotToUse, false, calendar); queueAlarm(alarm, builder, characteristic); iteration++; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java index 839d820a9..2dff60273 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java @@ -45,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; @@ -277,11 +278,11 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { default: return; } - Calendar cal = alarms.get(i).getAlarmCal(); + Calendar cal = AlarmUtils.toCalendar(alarms.get(i)); builder.write(ctrlCharacteristic, commandWithChecksum( cmd, - alarms.get(i).isEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1, - alarms.get(i).isEnabled() ? cal.get(Calendar.MINUTE) : -1 + alarms.get(i).getEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1, + alarms.get(i).getEnabled() ? cal.get(Calendar.MINUTE) : -1 )); } builder.queue(getQueue()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java index 65d1b699c..7c295775c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java @@ -56,7 +56,6 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.User; -import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; @@ -87,6 +86,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotific import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.FetchActivityOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.UpdateFirmwareOperation; import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils; @@ -560,7 +560,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { TransactionBuilder builder = performInitialized("Set alarm"); boolean anyAlarmEnabled = false; for (Alarm alarm : alarms) { - anyAlarmEnabled |= alarm.isEnabled(); + anyAlarmEnabled |= alarm.getEnabled(); queueAlarm(alarm, builder, characteristic); } builder.queue(getQueue()); @@ -1134,20 +1134,20 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { * @param characteristic */ private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) { - byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(alarm.getAlarmCal()); + byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(AlarmUtils.toCalendar(alarm)); byte[] alarmMessage = new byte[]{ MiBandService.COMMAND_SET_TIMER, - (byte) alarm.getIndex(), - (byte) (alarm.isEnabled() ? 1 : 0), + (byte) alarm.getPosition(), + (byte) (alarm.getEnabled() ? 1 : 0), alarmCalBytes[0], alarmCalBytes[1], alarmCalBytes[2], alarmCalBytes[3], alarmCalBytes[4], alarmCalBytes[5], - (byte) (alarm.isSmartWakeup() ? 30 : 0), - (byte) alarm.getRepetitionMask() + (byte) (alarm.getSmartWakeup() ? 30 : 0), + (byte) alarm.getRepetition() }; builder.write(characteristic, alarmMessage); } @@ -1231,15 +1231,6 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { CalendarEvents upcomingEvents = new CalendarEvents(); List mEvents = upcomingEvents.getCalendarEventList(getContext()); - Long deviceId; - try (DBHandler handler = GBApplication.acquireDB()) { - DaoSession session = handler.getDaoSession(); - deviceId = DBHelper.getDevice(getDevice(), session).getId(); - } catch (Exception e) { - LOG.error("Could not acquire DB", e); - return; - } - int iteration = 0; for (CalendarEvents.CalendarEvent mEvt : mEvents) { if (iteration >= availableSlots || iteration > 2) { @@ -1248,7 +1239,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { int slotToUse = 2 - iteration; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(mEvt.getBegin()); - Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar); + Alarm alarm = AlarmUtils.createSingleShot(slotToUse, false, calendar); queueAlarm(alarm, builder, characteristic); iteration++; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java index f339c949c..a15de8853 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java @@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import static org.apache.commons.lang3.math.NumberUtils.min; @@ -188,20 +189,20 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { TransactionBuilder builder = performInitialized("Set alarm"); boolean anyAlarmEnabled = false; for (Alarm alarm : alarms) { - anyAlarmEnabled |= alarm.isEnabled(); - Calendar calendar = alarm.getAlarmCal(); + anyAlarmEnabled |= alarm.getEnabled(); + Calendar calendar = AlarmUtils.toCalendar(alarm); int maxAlarms = 3; - if (alarm.getIndex() >= maxAlarms) { - if (alarm.isEnabled()) { + if (alarm.getPosition() >= maxAlarms) { + if (alarm.getEnabled()) { GB.toast(getContext(), "Only 3 alarms are supported.", Toast.LENGTH_LONG, GB.WARN); } return; } int daysMask = 0; - if (alarm.isEnabled()) { - daysMask = alarm.getRepetitionMask(); + if (alarm.getEnabled()) { + daysMask = alarm.getRepetition(); // Mask for this device starts from sunday and not from monday. daysMask = (daysMask / 64) + (daysMask >> 1); } @@ -210,11 +211,11 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { (byte) daysMask, (byte) calendar.get(Calendar.HOUR_OF_DAY), (byte) calendar.get(Calendar.MINUTE), - (byte) (alarm.isEnabled() ? 2 : 0), // vibration duration - (byte) (alarm.isEnabled() ? 10 : 0), // vibration count - (byte) (alarm.isEnabled() ? 2 : 0), // unknown + (byte) (alarm.getEnabled() ? 2 : 0), // vibration duration + (byte) (alarm.getEnabled() ? 10 : 0), // vibration count + (byte) (alarm.getEnabled() ? 2 : 0), // unknown (byte) 0, - (byte) (alarm.getIndex() + 1) + (byte) (alarm.getPosition() + 1) }; builder.write(ctrlCharacteristic, alarmMessage); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/watch9/Watch9DeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/watch9/Watch9DeviceSupport.java index 1be7bab0e..754b691a9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/watch9/Watch9DeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/watch9/Watch9DeviceSupport.java @@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.watch9.operations.InitOperation; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport { @@ -331,7 +332,7 @@ public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport { try { TransactionBuilder builder = performInitialized("setAlarms"); for (Alarm alarm : alarms) { - setAlarm(alarm, alarm.getIndex() + 1, builder); + setAlarm(alarm, alarm.getPosition() + 1, builder); } builder.queue(getQueue()); } catch (IOException e) { @@ -352,14 +353,14 @@ public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport { private void setAlarm(Alarm alarm, int index, TransactionBuilder builder) { // Shift the GB internal repetition mask to match the device specific one. - byte repetitionMask = (byte) ((alarm.getRepetitionMask() << 1) | (alarm.isRepetitive() ? 0x80 : 0x00)); + byte repetitionMask = (byte) ((alarm.getRepetition() << 1) | (alarm.isRepetitive() ? 0x80 : 0x00)); repetitionMask |= (alarm.getRepetition(Alarm.ALARM_SUN) ? 0x01 : 0x00); if (0 < index && index < 4) { byte[] alarmValue = new byte[]{(byte) index, - Conversion.toBcd8(alarm.getAlarmCal().get(Calendar.HOUR_OF_DAY)), - Conversion.toBcd8(alarm.getAlarmCal().get(Calendar.MINUTE)), + Conversion.toBcd8(AlarmUtils.toCalendar(alarm).get(Calendar.HOUR_OF_DAY)), + Conversion.toBcd8(AlarmUtils.toCalendar(alarm).get(Calendar.MINUTE)), repetitionMask, - (byte) (alarm.isEnabled() ? 0x01 : 0x00), + (byte) (alarm.getEnabled() ? 0x01 : 0x00), 0x00 // TODO: Unknown }; builder.write(getCharacteristic(Watch9Constants.UUID_CHARACTERISTIC_WRITE), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AlarmUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AlarmUtils.java new file mode 100644 index 000000000..5f1cb6733 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AlarmUtils.java @@ -0,0 +1,131 @@ +package nodomain.freeyourgadget.gadgetbridge.util; + +import android.support.annotation.NonNull; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; +import nodomain.freeyourgadget.gadgetbridge.entities.Alarm; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.User; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; + +/** + * Some utility methods for dealing with Alarms. + */ +public class AlarmUtils { + /** + * Creates an auto-generated (not user-configurable), non-recurring alarm. This alarm + * may not be stored in the database. Some features are not available (e.g. device id, user id). + * @param index + * @param smartWakeup + * @param calendar + * @return + */ + public static nodomain.freeyourgadget.gadgetbridge.model.Alarm createSingleShot(int index, boolean smartWakeup, Calendar calendar) { + return new Alarm(-1, -1, index, true, smartWakeup, Alarm.ALARM_ONCE, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE)); + } + + /** + * Creates a Calendar object representing the time of the given alarm (not taking the + * day/date into account. + * @param alarm + * @return + */ + public static Calendar toCalendar(nodomain.freeyourgadget.gadgetbridge.model.Alarm alarm) { + Calendar result = Calendar.getInstance(); + Calendar now = Calendar.getInstance(); + result.set(Calendar.HOUR_OF_DAY, alarm.getHour()); + result.set(Calendar.MINUTE, alarm.getMinute()); + if (now.after(result) && alarm.getRepetition() == Alarm.ALARM_ONCE) { + //if the alarm is in the past set it to tomorrow + result.add(Calendar.DATE, 1); + } + return result; + } + + /** + * Returns a repetition mask suitable for {@link Alarm#repetition} + * @param mon whether the alarm shall repeat every Monday + * @param tue whether the alarm shall repeat every Tuesday + * @param wed whether the alarm shall repeat every Wednesday + * @param thu whether the alarm shall repeat every Thursday + * @param fri whether the alarm shall repeat every Friday + * @param sat whether the alarm shall repeat every Saturday + * @param sun whether the alarm shall repeat every Sunday + * @return the created repetition mask + */ + public static int createRepetitionMassk(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) { + int repetitionMask = (mon ? Alarm.ALARM_MON : 0) | + (tue ? Alarm.ALARM_TUE : 0) | + (wed ? Alarm.ALARM_WED : 0) | + (thu ? Alarm.ALARM_THU : 0) | + (fri ? Alarm.ALARM_FRI : 0) | + (sat ? Alarm.ALARM_SAT : 0) | + (sun ? Alarm.ALARM_SUN : 0); + return repetitionMask; + } + + /** + * Just for backward compatibility, do not call in new code. + * @param gbDevice + * @return + * @deprecated use {@link DBHelper#getAlarms(GBDevice)} instead + */ + @NonNull + public static List readAlarmsFromPrefs(GBDevice gbDevice) { + Prefs prefs = GBApplication.getPrefs(); + Set stringAlarms = prefs.getStringSet(MiBandConst.PREF_MIBAND_ALARMS, new HashSet()); + List alarms = new ArrayList<>(stringAlarms.size()); + + try { + DBHandler db = GBApplication.acquireDB(); + DaoSession daoSession = db.getDaoSession(); + User user = DBHelper.getUser(daoSession); + Device device = DBHelper.getDevice(gbDevice, daoSession); + for (String stringAlarm : stringAlarms) { + alarms.add(createAlarmFromPreference(stringAlarm, device, user)); + } + Collections.sort(alarms, AlarmUtils.createComparator()); + return alarms; + } catch (Exception e) { + GB.log("Error accessing database", GB.ERROR, e); + return Collections.emptyList(); + } + } + + private static Alarm createAlarmFromPreference(String fromPreferences, Device device, User user) { + String[] tokens = fromPreferences.split(","); + int index = Integer.parseInt(tokens[0]); + boolean enabled = Boolean.parseBoolean(tokens[1]); + boolean smartWakeup = Boolean.parseBoolean(tokens[2]); + int repetition = Integer.parseInt(tokens[3]); + int hour = Integer.parseInt(tokens[4]); + int minute = Integer.parseInt(tokens[5]); + + return new Alarm(device.getId(), user.getId(), index, enabled, smartWakeup, repetition, hour, minute); + } + + private static Comparator createComparator() { + return new Comparator() { + + @Override + public int compare(Alarm o1, Alarm o2) { + int p1 = o1.getPosition(); + int p2 = o2.getPosition(); + + return Integer.compare(p1, p2); + } + }; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DateTimeUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DateTimeUtils.java index 1f5017094..1d558ab95 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DateTimeUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DateTimeUtils.java @@ -33,6 +33,7 @@ import java.util.TimeZone; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.model.Alarm; public class DateTimeUtils { private static SimpleDateFormat DAY_STORAGE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US); @@ -136,6 +137,11 @@ public class DateTimeUtils { return HOURS_MINUTES_FORMAT.format(date); } + public static String formatTime(int hours, int minutes) { + return String.format(Locale.US, "%02d", hours) + ":" + String.format(Locale.US, "%02d", minutes); + } + + public static Date todayUTC() { Calendar cal = getCalendarUTC(); return cal.getTime();