summaryrefslogtreecommitdiff
path: root/src/components/alarm
diff options
context:
space:
mode:
authorMark Russell <mruss660@gmail.com>2021-09-10 18:40:13 -0400
committerMark Russell <mruss660@gmail.com>2021-09-10 18:40:13 -0400
commit1fb5757655c1cdf0e93f03ad27869e8c043d69f0 (patch)
tree398a6762e69a9ba41f4cbd4e9f8f9995c94cfb21 /src/components/alarm
parent6f9f0e8b0e42a5526d47ca664534fb6b0ccb6ace (diff)
Created basic alarm app
Diffstat (limited to 'src/components/alarm')
-rw-r--r--src/components/alarm/AlarmController.cpp118
-rw-r--r--src/components/alarm/AlarmController.h50
2 files changed, 168 insertions, 0 deletions
diff --git a/src/components/alarm/AlarmController.cpp b/src/components/alarm/AlarmController.cpp
new file mode 100644
index 00000000..5097936f
--- /dev/null
+++ b/src/components/alarm/AlarmController.cpp
@@ -0,0 +1,118 @@
+//
+// Created by mrussell on 30.08.21.
+//
+// Copied from Florian's Timer app
+
+#include "AlarmController.h"
+#include "systemtask/SystemTask.h"
+#include "app_timer.h"
+#include "task.h"
+#include <chrono>
+
+using namespace Pinetime::Controllers;
+using namespace std::chrono_literals;
+
+AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
+}
+
+APP_TIMER_DEF(alarmAppTimer);
+
+namespace {
+ void SetOffAlarm(void* p_context) {
+ auto* controller = static_cast<Pinetime::Controllers::AlarmController*>(p_context);
+ if (controller != nullptr)
+ controller->SetOffAlarmNow();
+ }
+}
+
+void AlarmController::Init() {
+ app_timer_create(&alarmAppTimer, APP_TIMER_MODE_SINGLE_SHOT, SetOffAlarm);
+}
+
+void AlarmController::SetAlarm(uint8_t alarmHr, uint8_t alarmMin) {
+ hours = alarmHr;
+ minutes = alarmMin;
+ state = AlarmState::Set;
+ scheduleAlarm();
+}
+
+void AlarmController::scheduleAlarm() {
+ // Determine the next time the alarm needs to go off and set the app_timer
+ app_timer_stop(alarmAppTimer);
+
+ auto now = dateTimeController.CurrentDateTime();
+ alarmTime = now;
+ time_t ttAlarmTime = std::chrono::system_clock::to_time_t(alarmTime);
+ 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())) {
+ 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_sec = 0;
+
+ // if alarm is in weekday-only mode, make sure it shifts to the next weekday
+ if (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
+ tmAlarmTime->tm_mday += 2;
+ }
+ }
+ tmAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST
+
+ // now can convert back to a time_point
+ alarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmAlarmTime));
+ auto mSecToAlarm = std::chrono::duration_cast<std::chrono::milliseconds>(alarmTime - now).count();
+ app_timer_start(alarmAppTimer, APP_TIMER_TICKS(mSecToAlarm), this);
+}
+
+uint32_t AlarmController::SecondsToAlarm() {
+ return std::chrono::duration_cast<std::chrono::seconds>(alarmTime - dateTimeController.CurrentDateTime()).count();
+}
+
+void AlarmController::DisableAlarm() {
+ app_timer_stop(alarmAppTimer);
+ state = AlarmState::Not_Set;
+}
+
+void AlarmController::SetOffAlarmNow() {
+ state = AlarmState::Alerting;
+ if (systemTask != nullptr) {
+ systemTask->PushMessage(System::Messages::SetOffAlarm);
+ }
+}
+
+void AlarmController::StopAlerting() {
+ if (systemTask != nullptr) {
+ systemTask->PushMessage(System::Messages::StopRinging);
+ }
+
+ // Alarm state is off unless this is a recurring alarm
+ if (recurrence == RecurType::None) {
+ state = AlarmState::Not_Set;
+ } else {
+ state = AlarmState::Set;
+ // set next instance
+ scheduleAlarm();
+ }
+}
+
+void AlarmController::ToggleRecurrence() {
+ if (recurrence == AlarmController::RecurType::None) {
+ recurrence = AlarmController::RecurType::Daily;
+ } else if (recurrence == AlarmController::RecurType::Daily) {
+ recurrence = AlarmController::RecurType::Weekdays;
+ } else {
+ recurrence = AlarmController::RecurType::None;
+ }
+}
+
+void AlarmController::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
diff --git a/src/components/alarm/AlarmController.h b/src/components/alarm/AlarmController.h
new file mode 100644
index 00000000..22259da8
--- /dev/null
+++ b/src/components/alarm/AlarmController.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <cstdint>
+#include "app_timer.h"
+#include "components/datetime/DateTimeController.h"
+
+namespace Pinetime {
+ namespace System {
+ class SystemTask;
+ }
+ namespace Controllers {
+ class AlarmController {
+ public:
+ AlarmController(Controllers::DateTime& dateTimeController);
+
+ void Init();
+ void SetAlarm(uint8_t alarmHr, uint8_t alarmMin);
+ void DisableAlarm();
+ void SetOffAlarmNow();
+ uint32_t SecondsToAlarm();
+ void StopAlerting();
+ void Register(System::SystemTask* systemTask);
+ enum class AlarmState { Not_Set, Set, Alerting };
+ enum class RecurType { None, Daily, Weekdays };
+ void ToggleRecurrence();
+ uint8_t Hours() const {
+ return hours;
+ }
+ uint8_t Minutes() const {
+ return minutes;
+ }
+ AlarmState State() const {
+ return state;
+ }
+ RecurType Recurrence() const {
+ return recurrence;
+ }
+
+ private:
+ Controllers::DateTime& dateTimeController;
+ System::SystemTask* systemTask = nullptr;
+ uint8_t hours;
+ uint8_t minutes;
+ std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> alarmTime;
+ AlarmState state = AlarmState::Not_Set;
+ RecurType recurrence = RecurType::None;
+ void scheduleAlarm();
+ };
+ }
+} \ No newline at end of file