Implement persistent alarm storage
This commit is contained in:
parent
685e0950bf
commit
e4668f0c04
@ -1,5 +1,5 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS "alarms.c"
|
SRCS "alarm_store.c" "alarms.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES console_wrapper sound time
|
REQUIRES console_wrapper esp_partition fatal sound system_utils time
|
||||||
)
|
)
|
||||||
|
77
components/alarms/alarm_store.c
Normal file
77
components/alarms/alarm_store.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Copyright (c) Camden Dixie O'Brien
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "alarm_store.h"
|
||||||
|
|
||||||
|
#include "fatal.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_partition.h"
|
||||||
|
#include "system_utils.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define TAG "Alarm store"
|
||||||
|
|
||||||
|
Alarm alarms[CONFIG_MAX_ALARMS];
|
||||||
|
|
||||||
|
static const esp_partition_t *partition;
|
||||||
|
|
||||||
|
static unsigned erase_size(void)
|
||||||
|
{
|
||||||
|
unsigned sector_count = sizeof(alarms) / partition->erase_size;
|
||||||
|
if (sizeof(alarms) % partition->erase_size != 0)
|
||||||
|
++sector_count;
|
||||||
|
return partition->erase_size * sector_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load()
|
||||||
|
{
|
||||||
|
const esp_err_t error
|
||||||
|
= esp_partition_read(partition, 0, alarms, sizeof(alarms));
|
||||||
|
if (error != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error reading from alarms partition: %02x", error);
|
||||||
|
FATAL();
|
||||||
|
}
|
||||||
|
unsigned count = 0;
|
||||||
|
for (unsigned i = 0; i < CONFIG_MAX_ALARMS; ++i) {
|
||||||
|
if (alarms[i].set)
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Loaded %u alarms from storage", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void alarm_store_init()
|
||||||
|
{
|
||||||
|
partition = esp_partition_find_first(
|
||||||
|
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_UNDEFINED,
|
||||||
|
"alarms");
|
||||||
|
if (partition == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Unable to find alarms partition");
|
||||||
|
FATAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_first_boot()) {
|
||||||
|
ESP_LOGI(TAG, "Zeroing alarm store");
|
||||||
|
memset(alarms, 0, sizeof(alarms));
|
||||||
|
alarm_store_save();
|
||||||
|
} else {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void alarm_store_save()
|
||||||
|
{
|
||||||
|
esp_err_t error;
|
||||||
|
|
||||||
|
error = esp_partition_erase_range(partition, 0, erase_size());
|
||||||
|
if (error != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error erasing alarm storage: %02x", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = esp_partition_write(partition, 0, alarms, sizeof(alarms));
|
||||||
|
if (error != ESP_OK)
|
||||||
|
ESP_LOGE(TAG, "Error writing alarm storage: %02x", error);
|
||||||
|
}
|
31
components/alarms/alarm_store.h
Normal file
31
components/alarms/alarm_store.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Copyright (c) Camden Dixie O'Brien
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ALARM_STORE_H
|
||||||
|
#define ALARM_STORE_H
|
||||||
|
|
||||||
|
#include "time_manager.h"
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool set;
|
||||||
|
Time time;
|
||||||
|
} Alarm;
|
||||||
|
|
||||||
|
extern Alarm alarms[CONFIG_MAX_ALARMS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize alarm store and load alarms from storage.
|
||||||
|
*/
|
||||||
|
void alarm_store_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save alarms to storage.
|
||||||
|
*/
|
||||||
|
void alarm_store_save(void);
|
||||||
|
|
||||||
|
#endif
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#include "alarms.h"
|
#include "alarms.h"
|
||||||
|
|
||||||
|
#include "alarm_store.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "time_manager.h"
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -18,17 +18,11 @@
|
|||||||
|
|
||||||
#define TAG "Alarms"
|
#define TAG "Alarms"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool set;
|
|
||||||
Time time;
|
|
||||||
} Alarm;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const Alarm *alarm;
|
const Alarm *alarm;
|
||||||
Time end;
|
Time end;
|
||||||
} ActiveAlarm;
|
} ActiveAlarm;
|
||||||
|
|
||||||
static Alarm alarms[CONFIG_MAX_ALARMS];
|
|
||||||
static ActiveAlarm active[CONFIG_MAX_ALARMS];
|
static ActiveAlarm active[CONFIG_MAX_ALARMS];
|
||||||
static unsigned active_count;
|
static unsigned active_count;
|
||||||
static ActiveAlarm snoozed[CONFIG_MAX_ALARMS];
|
static ActiveAlarm snoozed[CONFIG_MAX_ALARMS];
|
||||||
@ -53,6 +47,7 @@ static bool add_alarm(Time time)
|
|||||||
if (!alarms[i].set) {
|
if (!alarms[i].set) {
|
||||||
alarms[i].set = true;
|
alarms[i].set = true;
|
||||||
alarms[i].time = time;
|
alarms[i].time = time;
|
||||||
|
alarm_store_save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +57,7 @@ static bool add_alarm(Time time)
|
|||||||
static void remove_alarm(unsigned index)
|
static void remove_alarm(unsigned index)
|
||||||
{
|
{
|
||||||
alarms[index].set = false;
|
alarms[index].set = false;
|
||||||
|
alarm_store_save();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void activate(const Alarm *alarm)
|
static void activate(const Alarm *alarm)
|
||||||
@ -212,13 +208,14 @@ static int command_func(int argc, char **argv)
|
|||||||
|
|
||||||
void alarms_init(void)
|
void alarms_init(void)
|
||||||
{
|
{
|
||||||
memset(alarms, 0, sizeof(alarms));
|
|
||||||
memset(active, 0, sizeof(active));
|
memset(active, 0, sizeof(active));
|
||||||
active_count = 0;
|
active_count = 0;
|
||||||
memset(snoozed, 0, sizeof(snoozed));
|
memset(snoozed, 0, sizeof(snoozed));
|
||||||
snoozed_count = 0;
|
snoozed_count = 0;
|
||||||
last_check = get_time();
|
last_check = get_time();
|
||||||
|
|
||||||
|
alarm_store_init();
|
||||||
|
|
||||||
add_time_callback(check_alarms);
|
add_time_callback(check_alarms);
|
||||||
|
|
||||||
console_register(
|
console_register(
|
||||||
|
6
partitions.csv
Normal file
6
partitions.csv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# ESP-IDF Partition Table
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs,data,nvs,0x9000,24K,
|
||||||
|
phy_init,data,phy,0xf000,4K,
|
||||||
|
factory,app,factory,0x10000,1M,
|
||||||
|
alarms,data,undefined,,8K
|
|
@ -1,4 +1,5 @@
|
|||||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||||
#
|
#
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_FREERTOS_UNICORE=y
|
CONFIG_FREERTOS_UNICORE=y
|
||||||
|
Loading…
x
Reference in New Issue
Block a user