Implement persistent alarm storage

This commit is contained in:
Camden Dixie O'Brien 2023-05-19 16:15:17 +01:00
parent 685e0950bf
commit e4668f0c04
6 changed files with 122 additions and 10 deletions

View File

@ -1,5 +1,5 @@
idf_component_register(
SRCS "alarms.c"
SRCS "alarm_store.c" "alarms.c"
INCLUDE_DIRS "."
REQUIRES console_wrapper sound time
REQUIRES console_wrapper esp_partition fatal sound system_utils time
)

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

View 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

View File

@ -5,9 +5,9 @@
#include "alarms.h"
#include "alarm_store.h"
#include "console.h"
#include "sound.h"
#include "time_manager.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
@ -18,17 +18,11 @@
#define TAG "Alarms"
typedef struct {
bool set;
Time time;
} Alarm;
typedef struct {
const Alarm *alarm;
Time end;
} ActiveAlarm;
static Alarm alarms[CONFIG_MAX_ALARMS];
static ActiveAlarm active[CONFIG_MAX_ALARMS];
static unsigned active_count;
static ActiveAlarm snoozed[CONFIG_MAX_ALARMS];
@ -53,6 +47,7 @@ static bool add_alarm(Time time)
if (!alarms[i].set) {
alarms[i].set = true;
alarms[i].time = time;
alarm_store_save();
return true;
}
}
@ -62,6 +57,7 @@ static bool add_alarm(Time time)
static void remove_alarm(unsigned index)
{
alarms[index].set = false;
alarm_store_save();
}
static void activate(const Alarm *alarm)
@ -212,13 +208,14 @@ static int command_func(int argc, char **argv)
void alarms_init(void)
{
memset(alarms, 0, sizeof(alarms));
memset(active, 0, sizeof(active));
active_count = 0;
memset(snoozed, 0, sizeof(snoozed));
snoozed_count = 0;
last_check = get_time();
alarm_store_init();
add_time_callback(check_alarms);
console_register(

6
partitions.csv Normal file
View 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 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs,data,nvs,0x9000,24K,
4 phy_init,data,phy,0xf000,4K,
5 factory,app,factory,0x10000,1M,
6 alarms,data,undefined,,8K

View File

@ -1,4 +1,5 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_FREERTOS_UNICORE=y