#include "app_no_disturb.h" #include "system/includes.h" #include "usr_rtc.h" #define APP_NO_DISTURB_VM_ID 28U #define APP_NO_DISTURB_MAGIC 0x4e44U #define APP_NO_DISTURB_VERSION 1U #define APP_MINUTES_PER_DAY (24U * 60U) typedef struct __attribute__((packed)) { uint16_t magic; uint8_t version; uint8_t cfg[APP_NO_DISTURB_CFG_LEN]; } AppNoDisturbVm_t; typedef struct { uint8_t enabled; uint8_t weekdays_mask; uint16_t start_minute; uint16_t end_minute; } AppNoDisturbCtx_t; static AppNoDisturbCtx_t s_no_disturb; static uint8_t app_no_disturb_cfg_valid(const uint8_t cfg[APP_NO_DISTURB_CFG_LEN]) { uint8_t i; if (!cfg || cfg[0] > 1U || cfg[9] >= 24U || cfg[11] >= 24U || cfg[10] >= 60U || cfg[12] >= 60U) { return 0; } for (i = 0; i < 7U; i++) { if (cfg[2U + i] > 1U) { return 0; } } return 1; } void app_no_disturb_configure(uint8_t enable, uint8_t weekdays_mask, uint16_t start_minute, uint16_t end_minute) { s_no_disturb.enabled = !!enable; s_no_disturb.weekdays_mask = weekdays_mask & 0x7fU; s_no_disturb.start_minute = start_minute; s_no_disturb.end_minute = end_minute; } uint8_t app_no_disturb_storage_load(uint8_t cfg[APP_NO_DISTURB_CFG_LEN]) { AppNoDisturbVm_t vm; int ret; if (!cfg) { return 0; } memset(&vm, 0, sizeof(vm)); ret = syscfg_read(APP_NO_DISTURB_VM_ID, &vm, sizeof(vm)); if (ret != (int)sizeof(vm) || vm.magic != APP_NO_DISTURB_MAGIC || vm.version != APP_NO_DISTURB_VERSION || !app_no_disturb_cfg_valid(vm.cfg)) { memset(cfg, 0, APP_NO_DISTURB_CFG_LEN); return 0; } memcpy(cfg, vm.cfg, APP_NO_DISTURB_CFG_LEN); return 1; } uint8_t app_no_disturb_storage_save(const uint8_t cfg[APP_NO_DISTURB_CFG_LEN]) { AppNoDisturbVm_t vm; if (!app_no_disturb_cfg_valid(cfg)) { return 0; } memset(&vm, 0, sizeof(vm)); vm.magic = APP_NO_DISTURB_MAGIC; vm.version = APP_NO_DISTURB_VERSION; memcpy(vm.cfg, cfg, APP_NO_DISTURB_CFG_LEN); return (uint8_t)(syscfg_write(APP_NO_DISTURB_VM_ID, &vm, sizeof(vm)) == (int)sizeof(vm)); } static uint8_t app_no_disturb_weekday_monday0(const struct sys_time *time) { static const uint8_t month_offset[12] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; uint32_t year = time->year; uint8_t sunday0; if (time->month < 3U) { year--; } sunday0 = (uint8_t)((year + year / 4U - year / 100U + year / 400U + month_offset[time->month - 1U] + time->day) % 7U); return (uint8_t)((sunday0 + 6U) % 7U); } static uint8_t app_no_disturb_day_selected(uint8_t weekday) { return (uint8_t)((s_no_disturb.weekdays_mask & (1U << weekday)) != 0U); } uint8_t app_no_disturb_is_active_at(const struct sys_time *time) { uint8_t weekday; uint16_t now_minute; if (!time || !s_no_disturb.enabled || !s_no_disturb.weekdays_mask || s_no_disturb.start_minute >= APP_MINUTES_PER_DAY || s_no_disturb.end_minute >= APP_MINUTES_PER_DAY || time->month < 1U || time->month > 12U || time->day < 1U || time->day > 31U || time->hour > 23U || time->min > 59U) { return 0; } weekday = app_no_disturb_weekday_monday0(time); now_minute = (uint16_t)(time->hour * 60U + time->min); if (s_no_disturb.start_minute == s_no_disturb.end_minute) { return app_no_disturb_day_selected(weekday); } if (s_no_disturb.start_minute < s_no_disturb.end_minute) { return app_no_disturb_day_selected(weekday) && now_minute >= s_no_disturb.start_minute && now_minute < s_no_disturb.end_minute; } if (now_minute >= s_no_disturb.start_minute) { return app_no_disturb_day_selected(weekday); } if (now_minute < s_no_disturb.end_minute) { return app_no_disturb_day_selected((uint8_t)((weekday + 6U) % 7U)); } return 0; } uint8_t app_no_disturb_is_active(void) { struct sys_time time; if (!usr_rtc_get_time(&time)) { return 0; } return app_no_disturb_is_active_at(&time); }