Files
JBao_Magic_Box_FW/apps/usr_app/app_no_disturb.c
T

146 lines
4.1 KiB
C

#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);
}