diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index 4ef0d8a1b..354c6e275 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -45,7 +45,7 @@ public class GBDaoGenerator { public static void main(String[] args) throws Exception { - Schema schema = new Schema(18, MAIN_PACKAGE + ".entities"); + Schema schema = new Schema(19, MAIN_PACKAGE + ".entities"); Entity userAttributes = addUserAttributes(schema); Entity user = addUserInfo(schema, userAttributes); @@ -73,6 +73,7 @@ public class GBDaoGenerator { addID115ActivitySample(schema, user, device); addCalendarSyncState(schema, device); + addAlarms(schema, user, device); addBipActivitySummary(schema, user, device); @@ -342,6 +343,26 @@ public class GBDaoGenerator { calendarSyncState.addIntProperty("hash").notNull(); } + private static void addAlarms(Schema schema, Entity user, Entity device) { + Entity alarm = addEntity(schema, "Alarm"); + Property deviceId = alarm.addLongProperty("deviceId").notNull().getProperty(); + Property userId = alarm.addLongProperty("userId").notNull().getProperty(); + Property position = alarm.addIntProperty("position").notNull().getProperty(); + Index indexUnique = new Index(); + indexUnique.addProperty(deviceId); + indexUnique.addProperty(userId); + indexUnique.addProperty(position); + indexUnique.makeUnique(); + alarm.addIndex(indexUnique); + alarm.addBooleanProperty("enabled").notNull(); + alarm.addBooleanProperty("smartAlarm").notNull(); + alarm.addIntProperty("repetition").notNull(); + alarm.addIntProperty("hour").notNull(); + alarm.addIntProperty("minute").notNull(); + alarm.addToOne(user, userId); + alarm.addToOne(device, deviceId); + } + private static void addBipActivitySummary(Schema schema, Entity user, Entity device) { Entity summary = addEntity(schema, "BaseActivitySummary"); summary.implementsInterface(ACTIVITY_SUMMARY); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java index b896a69d3..cb725a0ef 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java @@ -94,9 +94,10 @@ public class SleepAlarmWidget extends AppWidgetProvider { // overwrite the first alarm and activate it - GBAlarm alarm = GBAlarm.createSingleShot(0, true, calendar); +/* + GBAlarm alarm = GBAlarm.createSingleShot(0,0, true, calendar); // FIXME!!!! alarm.store(); - +*/ if (GBApplication.isRunningLollipopOrLater()) { setAlarmViaAlarmManager(context, calendar.getTimeInMillis()); } 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 876a19edc..6259f0e2f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -23,29 +23,33 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.MenuItem; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +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.Device; import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; -import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS; - public class ConfigureAlarms extends AbstractGBActivity { private static final int REQ_CONFIGURE_ALARM = 1; private GBAlarmListAdapter mGBAlarmListAdapter; - private Set preferencesAlarmListSet; private boolean avoidSendAlarmsToDevice; - private GBDevice device; + private GBDevice gbDevice; @Override protected void onCreate(Bundle savedInstanceState) { @@ -53,28 +57,20 @@ public class ConfigureAlarms extends AbstractGBActivity { setContentView(R.layout.activity_configure_alarms); - device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE); + gbDevice = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE); - Prefs prefs = GBApplication.getPrefs(); - preferencesAlarmListSet = prefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet()); - if (preferencesAlarmListSet.isEmpty()) { - //initialize the preferences - preferencesAlarmListSet = new HashSet<>(Arrays.asList(GBAlarm.DEFAULT_ALARMS)); - prefs.getPreferences().edit().putStringSet(PREF_MIBAND_ALARMS, preferencesAlarmListSet).apply(); - } + mGBAlarmListAdapter = new GBAlarmListAdapter(this); - mGBAlarmListAdapter = new GBAlarmListAdapter(this, preferencesAlarmListSet); - - RecyclerView alarmsRecyclerView = (RecyclerView) findViewById(R.id.alarm_list); + RecyclerView alarmsRecyclerView = findViewById(R.id.alarm_list); alarmsRecyclerView.setHasFixedSize(true); alarmsRecyclerView.setLayoutManager(new LinearLayoutManager(this)); alarmsRecyclerView.setAdapter(mGBAlarmListAdapter); - updateAlarmsFromPrefs(); + updateAlarmsFromDB(); } @Override protected void onPause() { - if (!avoidSendAlarmsToDevice) { + if (!avoidSendAlarmsToDevice && gbDevice.isInitialized()) { sendAlarmsToDevice(); } super.onPause(); @@ -84,16 +80,45 @@ public class ConfigureAlarms extends AbstractGBActivity { protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQ_CONFIGURE_ALARM) { avoidSendAlarmsToDevice = false; - updateAlarmsFromPrefs(); + updateAlarmsFromDB(); } } - private void updateAlarmsFromPrefs() { + private void updateAlarmsFromDB() { Prefs prefs = GBApplication.getPrefs(); - preferencesAlarmListSet = prefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet()); int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0); - mGBAlarmListAdapter.setAlarmList(preferencesAlarmListSet, reservedSlots); + 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 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())); + } + } + 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(); } @@ -112,12 +137,12 @@ public class ConfigureAlarms extends AbstractGBActivity { avoidSendAlarmsToDevice = true; Intent startIntent = new Intent(getApplicationContext(), AlarmDetails.class); startIntent.putExtra("alarm", alarm); - startIntent.putExtra(GBDevice.EXTRA_DEVICE, getDevice()); + startIntent.putExtra(GBDevice.EXTRA_DEVICE, getGbDevice()); startActivityForResult(startIntent, REQ_CONFIGURE_ALARM); } - private GBDevice getDevice() { - return device; + private GBDevice getGbDevice() { + return gbDevice; } private void sendAlarmsToDevice() { 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 83136d116..755d01a73 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.adapter; import android.content.Context; +import android.support.annotation.NonNull; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -30,9 +31,7 @@ import android.widget.Switch; import android.widget.TextView; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Set; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; @@ -48,58 +47,32 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter alarmList; - public GBAlarmListAdapter(Context context, List alarmList) { + public GBAlarmListAdapter(Context context) { this.mContext = context; + } + + public void setAlarmList(List alarmList) { this.alarmList = alarmList; } - public GBAlarmListAdapter(Context context, Set preferencesAlarmListSet) { - this.mContext = context; - alarmList = new ArrayList<>(); - - for (String alarmString : preferencesAlarmListSet) { - alarmList.add(new GBAlarm(alarmString)); - } - - Collections.sort(alarmList); - } - - public void setAlarmList(Set preferencesAlarmListSet, int reservedSlots) { - alarmList = new ArrayList<>(); - - for (String alarmString : preferencesAlarmListSet) { - alarmList.add(new GBAlarm(alarmString)); - } - - Collections.sort(alarmList); - - //cannot do this earlier because the Set is not guaranteed to be in order by ID - alarmList.subList(alarmList.size() - reservedSlots, alarmList.size()).clear(); - } - - public ArrayList getAlarmList() { + public ArrayList getAlarmList() { return (ArrayList) alarmList; } public void update(GBAlarm alarm) { - for (GBAlarm a : alarmList) { - if (alarm.equals(a)) { - a = alarm; - } - } alarm.store(); } + @NonNull @Override - public GBAlarmListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public GBAlarmListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_alarm, parent, false); - ViewHolder vh = new ViewHolder(view); - return vh; + return new ViewHolder(view); } @Override - public void onBindViewHolder(ViewHolder holder, final int position) { + public void onBindViewHolder(@NonNull ViewHolder holder, final int position) { final GBAlarm alarm = alarmList.get(position); @@ -159,21 +132,19 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter preferencesAlarmListSet = prefs.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; - } + 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); } - newPrefs.add(this.toPreferences()); - prefs.getPreferences().edit().putStringSet(PREF_MIBAND_ALARMS, newPrefs).apply(); } public static final Creator CREATOR = new Creator() { 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 4783b527a..7f3cf6934 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 @@ -1394,10 +1394,12 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) { Calendar calendar = alarm.getAlarmCal(); - int maxAlarms = 5; // arbitrary at the moment... + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice); + int maxAlarms = coordinator.getAlarmSlotCount(); + if (alarm.getIndex() >= maxAlarms) { if (alarm.isEnabled()) { - GB.toast(getContext(), "Only 5 alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN); + GB.toast(getContext(), "Only " + maxAlarms + " alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN); } return; } @@ -1465,7 +1467,16 @@ 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) { if (iteration >= availableSlots || iteration > 2) { break; @@ -1473,7 +1484,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { int slotToUse = 2 - iteration; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(mEvt.getBegin()); - Alarm alarm = GBAlarm.createSingleShot(slotToUse, false, calendar); + Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar); queueAlarm(alarm, builder, characteristic); iteration++; } 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 549cbb9d5..1f51f4b15 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 @@ -1225,6 +1225,15 @@ 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) { @@ -1233,7 +1242,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { int slotToUse = 2 - iteration; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(mEvt.getBegin()); - Alarm alarm = GBAlarm.createSingleShot(slotToUse, false, calendar); + Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar); queueAlarm(alarm, builder, characteristic); iteration++; }