aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/alarm/AlarmController.cpp
diff options
context:
space:
mode:
authorNeroBurner <pyro4hell@gmail.com>2024-09-28 08:14:08 +0200
committerGitHub <noreply@github.com>2024-09-28 08:14:08 +0200
commita0cd439efc9b0d0d9610dea7ff749f102d5a316d (patch)
treee03cfd44b5acb648d40c0bb07ff4002e56cf0733 /src/components/alarm/AlarmController.cpp
parent997e4cee8cc78a6e0b68cc78b604dc342f22b584 (diff)
Alarm persist to flash (#1367)
* AlarmController: Add saving alarm time to file Save the set alarm time to the SPI NOR flash, so it does not reset to the default value when the watch resets, e.g. due to watchdog timeout or reflashing of a new version of InfiniTime. Just like the `Settings.h` `LoadSettingsFromFile()` the previous alarm at boot (if available) and `SaveSettingsToFile()` the current alarm when the `Alarm.h` screen is closed (only if the settings have changed). The alarm-settings file is stored in `.system/alarm.dat`. The `.system` folder is created if it doesn't yet exist. Fixes: https://github.com/InfiniTimeOrg/InfiniTime/issues/1330 * alarmController: close .system dir after usage Close the `lfs_dir` object for the `.system` dir after usage. Otherwise on the second changed alarm the system will lockup because the `.system` dir is already open and was never closed. --------- Co-authored-by: Galdor Takacs <g@ldor.de>
Diffstat (limited to 'src/components/alarm/AlarmController.cpp')
-rw-r--r--src/components/alarm/AlarmController.cpp101
1 files changed, 88 insertions, 13 deletions
diff --git a/src/components/alarm/AlarmController.cpp b/src/components/alarm/AlarmController.cpp
index c4eb8ed0..7dbfb0e3 100644
--- a/src/components/alarm/AlarmController.cpp
+++ b/src/components/alarm/AlarmController.cpp
@@ -19,11 +19,13 @@
#include "systemtask/SystemTask.h"
#include "task.h"
#include <chrono>
+#include <libraries/log/nrf_log.h>
using namespace Pinetime::Controllers;
using namespace std::chrono_literals;
-AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
+AlarmController::AlarmController(Controllers::DateTime& dateTimeController, Controllers::FS& fs)
+ : dateTimeController {dateTimeController}, fs {fs} {
}
namespace {
@@ -36,11 +38,28 @@ namespace {
void AlarmController::Init(System::SystemTask* systemTask) {
this->systemTask = systemTask;
alarmTimer = xTimerCreate("Alarm", 1, pdFALSE, this, SetOffAlarm);
+ LoadSettingsFromFile();
+ if (alarm.isEnabled) {
+ NRF_LOG_INFO("[AlarmController] Loaded alarm was enabled, scheduling");
+ ScheduleAlarm();
+ }
+}
+
+void AlarmController::SaveAlarm() {
+ // verify if it is necessary to save
+ if (alarmChanged) {
+ SaveSettingsToFile();
+ }
+ alarmChanged = false;
}
void AlarmController::SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin) {
- hours = alarmHr;
- minutes = alarmMin;
+ if (alarm.hours == alarmHr && alarm.minutes == alarmMin) {
+ return;
+ }
+ alarm.hours = alarmHr;
+ alarm.minutes = alarmMin;
+ alarmChanged = true;
}
void AlarmController::ScheduleAlarm() {
@@ -53,18 +72,19 @@ void AlarmController::ScheduleAlarm() {
tm* tmAlarmTime = std::localtime(&ttAlarmTime);
// If the time being set has already passed today,the alarm should be set for tomorrow
- if (hours < dateTimeController.Hours() || (hours == dateTimeController.Hours() && minutes <= dateTimeController.Minutes())) {
+ if (alarm.hours < dateTimeController.Hours() ||
+ (alarm.hours == dateTimeController.Hours() && alarm.minutes <= dateTimeController.Minutes())) {
tmAlarmTime->tm_mday += 1;
// tm_wday doesn't update automatically
tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1) % 7;
}
- tmAlarmTime->tm_hour = hours;
- tmAlarmTime->tm_min = minutes;
+ tmAlarmTime->tm_hour = alarm.hours;
+ tmAlarmTime->tm_min = alarm.minutes;
tmAlarmTime->tm_sec = 0;
// if alarm is in weekday-only mode, make sure it shifts to the next weekday
- if (recurrence == RecurType::Weekdays) {
+ if (alarm.recurrence == RecurType::Weekdays) {
if (tmAlarmTime->tm_wday == 0) { // Sunday, shift 1 day
tmAlarmTime->tm_mday += 1;
} else if (tmAlarmTime->tm_wday == 6) { // Saturday, shift 2 days
@@ -79,7 +99,10 @@ void AlarmController::ScheduleAlarm() {
xTimerChangePeriod(alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0);
xTimerStart(alarmTimer, 0);
- state = AlarmState::Set;
+ if (!alarm.isEnabled) {
+ alarm.isEnabled = true;
+ alarmChanged = true;
+ }
}
uint32_t AlarmController::SecondsToAlarm() const {
@@ -88,20 +111,72 @@ uint32_t AlarmController::SecondsToAlarm() const {
void AlarmController::DisableAlarm() {
xTimerStop(alarmTimer, 0);
- state = AlarmState::Not_Set;
+ isAlerting = false;
+ if (alarm.isEnabled) {
+ alarm.isEnabled = false;
+ alarmChanged = true;
+ }
}
void AlarmController::SetOffAlarmNow() {
- state = AlarmState::Alerting;
+ isAlerting = true;
systemTask->PushMessage(System::Messages::SetOffAlarm);
}
void AlarmController::StopAlerting() {
- // Alarm state is off unless this is a recurring alarm
- if (recurrence == RecurType::None) {
- state = AlarmState::Not_Set;
+ isAlerting = false;
+ // Disable alarm unless it is recurring
+ if (alarm.recurrence == RecurType::None) {
+ alarm.isEnabled = false;
+ alarmChanged = true;
} else {
// set next instance
ScheduleAlarm();
}
}
+
+void AlarmController::SetRecurrence(RecurType recurrence) {
+ if (alarm.recurrence != recurrence) {
+ alarm.recurrence = recurrence;
+ alarmChanged = true;
+ }
+}
+
+void AlarmController::LoadSettingsFromFile() {
+ lfs_file_t alarmFile;
+ AlarmSettings alarmBuffer;
+
+ if (fs.FileOpen(&alarmFile, "/.system/alarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) {
+ NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file");
+ return;
+ }
+
+ fs.FileRead(&alarmFile, reinterpret_cast<uint8_t*>(&alarmBuffer), sizeof(alarmBuffer));
+ fs.FileClose(&alarmFile);
+ if (alarmBuffer.version != alarmFormatVersion) {
+ NRF_LOG_WARNING("[AlarmController] Loaded alarm settings has version %u instead of %u, discarding",
+ alarmBuffer.version,
+ alarmFormatVersion);
+ return;
+ }
+
+ alarm = alarmBuffer;
+ NRF_LOG_INFO("[AlarmController] Loaded alarm settings from file");
+}
+
+void AlarmController::SaveSettingsToFile() const {
+ lfs_dir systemDir;
+ if (fs.DirOpen("/.system", &systemDir) != LFS_ERR_OK) {
+ fs.DirCreate("/.system");
+ }
+ fs.DirClose(&systemDir);
+ lfs_file_t alarmFile;
+ if (fs.FileOpen(&alarmFile, "/.system/alarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) {
+ NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file for saving");
+ return;
+ }
+
+ fs.FileWrite(&alarmFile, reinterpret_cast<const uint8_t*>(&alarm), sizeof(alarm));
+ fs.FileClose(&alarmFile);
+ NRF_LOG_INFO("[AlarmController] Saved alarm settings with format version %u to file", alarm.version);
+}