1919#include " systemtask/SystemTask.h"
2020#include " task.h"
2121#include < chrono>
22+ #include < libraries/log/nrf_log.h>
2223
2324using namespace Pinetime ::Controllers;
2425using namespace std ::chrono_literals;
2526
26- AlarmController::AlarmController (Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
27+ AlarmController::AlarmController (Controllers::DateTime& dateTimeController, Controllers::FS& fs)
28+ : dateTimeController {dateTimeController}, fs {fs} {
2729}
2830
2931namespace {
@@ -36,11 +38,28 @@ namespace {
3638void AlarmController::Init (System::SystemTask* systemTask) {
3739 this ->systemTask = systemTask;
3840 alarmTimer = xTimerCreate (" Alarm" , 1 , pdFALSE, this , SetOffAlarm);
41+ LoadSettingsFromFile ();
42+ if (alarm.isEnabled ) {
43+ NRF_LOG_INFO (" [AlarmController] Loaded alarm was enabled, scheduling" );
44+ ScheduleAlarm ();
45+ }
46+ }
47+
48+ void AlarmController::SaveAlarm () {
49+ // verify if it is necessary to save
50+ if (alarmChanged) {
51+ SaveSettingsToFile ();
52+ }
53+ alarmChanged = false ;
3954}
4055
4156void AlarmController::SetAlarmTime (uint8_t alarmHr, uint8_t alarmMin) {
42- hours = alarmHr;
43- minutes = alarmMin;
57+ if (alarm.hours == alarmHr && alarm.minutes == alarmMin) {
58+ return ;
59+ }
60+ alarm.hours = alarmHr;
61+ alarm.minutes = alarmMin;
62+ alarmChanged = true ;
4463}
4564
4665void AlarmController::ScheduleAlarm () {
@@ -53,18 +72,19 @@ void AlarmController::ScheduleAlarm() {
5372 tm* tmAlarmTime = std::localtime (&ttAlarmTime);
5473
5574 // If the time being set has already passed today,the alarm should be set for tomorrow
56- if (hours < dateTimeController.Hours () || (hours == dateTimeController.Hours () && minutes <= dateTimeController.Minutes ())) {
75+ if (alarm.hours < dateTimeController.Hours () ||
76+ (alarm.hours == dateTimeController.Hours () && alarm.minutes <= dateTimeController.Minutes ())) {
5777 tmAlarmTime->tm_mday += 1 ;
5878 // tm_wday doesn't update automatically
5979 tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1 ) % 7 ;
6080 }
6181
62- tmAlarmTime->tm_hour = hours;
63- tmAlarmTime->tm_min = minutes;
82+ tmAlarmTime->tm_hour = alarm. hours ;
83+ tmAlarmTime->tm_min = alarm. minutes ;
6484 tmAlarmTime->tm_sec = 0 ;
6585
6686 // if alarm is in weekday-only mode, make sure it shifts to the next weekday
67- if (recurrence == RecurType::Weekdays) {
87+ if (alarm. recurrence == RecurType::Weekdays) {
6888 if (tmAlarmTime->tm_wday == 0 ) { // Sunday, shift 1 day
6989 tmAlarmTime->tm_mday += 1 ;
7090 } else if (tmAlarmTime->tm_wday == 6 ) { // Saturday, shift 2 days
@@ -79,7 +99,10 @@ void AlarmController::ScheduleAlarm() {
7999 xTimerChangePeriod (alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0 );
80100 xTimerStart (alarmTimer, 0 );
81101
82- state = AlarmState::Set;
102+ if (!alarm.isEnabled ) {
103+ alarm.isEnabled = true ;
104+ alarmChanged = true ;
105+ }
83106}
84107
85108uint32_t AlarmController::SecondsToAlarm () const {
@@ -88,20 +111,72 @@ uint32_t AlarmController::SecondsToAlarm() const {
88111
89112void AlarmController::DisableAlarm () {
90113 xTimerStop (alarmTimer, 0 );
91- state = AlarmState::Not_Set;
114+ isAlerting = false ;
115+ if (alarm.isEnabled ) {
116+ alarm.isEnabled = false ;
117+ alarmChanged = true ;
118+ }
92119}
93120
94121void AlarmController::SetOffAlarmNow () {
95- state = AlarmState::Alerting ;
122+ isAlerting = true ;
96123 systemTask->PushMessage (System::Messages::SetOffAlarm);
97124}
98125
99126void AlarmController::StopAlerting () {
100- // Alarm state is off unless this is a recurring alarm
101- if (recurrence == RecurType::None) {
102- state = AlarmState::Not_Set;
127+ isAlerting = false ;
128+ // Disable alarm unless it is recurring
129+ if (alarm.recurrence == RecurType::None) {
130+ alarm.isEnabled = false ;
131+ alarmChanged = true ;
103132 } else {
104133 // set next instance
105134 ScheduleAlarm ();
106135 }
107136}
137+
138+ void AlarmController::SetRecurrence (RecurType recurrence) {
139+ if (alarm.recurrence != recurrence) {
140+ alarm.recurrence = recurrence;
141+ alarmChanged = true ;
142+ }
143+ }
144+
145+ void AlarmController::LoadSettingsFromFile () {
146+ lfs_file_t alarmFile;
147+ AlarmSettings alarmBuffer;
148+
149+ if (fs.FileOpen (&alarmFile, " /.system/alarm.dat" , LFS_O_RDONLY) != LFS_ERR_OK) {
150+ NRF_LOG_WARNING (" [AlarmController] Failed to open alarm data file" );
151+ return ;
152+ }
153+
154+ fs.FileRead (&alarmFile, reinterpret_cast <uint8_t *>(&alarmBuffer), sizeof (alarmBuffer));
155+ fs.FileClose (&alarmFile);
156+ if (alarmBuffer.version != alarmFormatVersion) {
157+ NRF_LOG_WARNING (" [AlarmController] Loaded alarm settings has version %u instead of %u, discarding" ,
158+ alarmBuffer.version ,
159+ alarmFormatVersion);
160+ return ;
161+ }
162+
163+ alarm = alarmBuffer;
164+ NRF_LOG_INFO (" [AlarmController] Loaded alarm settings from file" );
165+ }
166+
167+ void AlarmController::SaveSettingsToFile () const {
168+ lfs_dir systemDir;
169+ if (fs.DirOpen (" /.system" , &systemDir) != LFS_ERR_OK) {
170+ fs.DirCreate (" /.system" );
171+ }
172+ fs.DirClose (&systemDir);
173+ lfs_file_t alarmFile;
174+ if (fs.FileOpen (&alarmFile, " /.system/alarm.dat" , LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) {
175+ NRF_LOG_WARNING (" [AlarmController] Failed to open alarm data file for saving" );
176+ return ;
177+ }
178+
179+ fs.FileWrite (&alarmFile, reinterpret_cast <const uint8_t *>(&alarm), sizeof (alarm));
180+ fs.FileClose (&alarmFile);
181+ NRF_LOG_INFO (" [AlarmController] Saved alarm settings with format version %u to file" , alarm.version );
182+ }
0 commit comments