Skip to content

Commit

Permalink
Added key-press factory reset.
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul D.Smith committed Dec 28, 2023
1 parent dfc7966 commit ae7a8e7
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 30 deletions.
175 changes: 170 additions & 5 deletions esp32/cloudsmets/main/cs_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
#include "esp_event.h"
#include "esp_timer.h"
#include "driver/gpio.h"

// #include "ft_err.h"
Expand All @@ -34,16 +35,32 @@
#include "cs_time.h"
#include "cs_zigbee.h"
#include "cs_flash.h"
#include "cs_app.h"

/* Task Configuration */
#define CS_APP_TASK_QUEUE_SIZE CONFIG_CS_TASK_QUEUE_SIZE
#define CS_APP_TASK_PRIORITY_DEFAULT CONFIG_CS_TASK_PRIORITY_DEFAULT
#define CS_APP_TASK_STACK_SIZE CONFIG_CS_TASK_STACK_SIZE

#define TLSR8258_POWER GPIO_NUM_0
// TODO: Should be common.
#define BLUE_LED GPIO_NUM_3
#define TLSR8258_POWER GPIO_NUM_0
#define CLEAR_KEY GPIO_NUM_2

static const char *cs_app_task = "App";
#define TAG cs_app_task
/* Times. */
#define FIRST_JAN_2023 1672531200
#define FACTORY_RESET_PRESS 10
#define ZIGBEE_RESET_PRESS 4
#define FACTORY_RESET_TIMER_WAIT ((uint64_t)1000 * 1000 * 2)

#define TAG cs_app_task_name

esp_timer_handle_t factory_reset_timer_handle = NULL;

ESP_EVENT_DEFINE_BASE(CS_APP_EVENT);

static esp_event_loop_handle_t app_event_loop_handle = NULL;
static esp_event_loop_handle_t zigbee_event_loop_handle = NULL;

union cs_create_parms_t {
cs_flash_create_parms_t flash;
Expand Down Expand Up @@ -88,6 +105,133 @@ static void esp32_info()
"Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());
}

/**
* Note that the line is pull DOWN by a key press.
* We send ourselves an event to avoid any processing that might not be
* possible from inside an interrupt handler.
*/
static void intr_handler(void *arg)
{
time_t pressed = 0;
time_t released = 0;
int level;

level = gpio_get_level(CLEAR_KEY);
if (level)
{
/* Rising line; key has been released. */
released = time(NULL);
released = released - pressed;
if (released > FIRST_JAN_2023)
{
/**
* Time has been set whilst we were pressing the key so we cannot
* tell how long it was held for; have to just ignore it.
*/
}
else if (released > FACTORY_RESET_PRESS)
{
/**
* Factory resetting the ESP32c3 will happen on a timer to allow
* the tlsr8258 to be reset first.
*/
ESP_ERROR_CHECK(esp_event_isr_post_to(
app_event_loop_handle,
CS_APP_EVENT,
CS_APP_EVENT_FACTORY_RESET,
NULL,
0,
NULL));
}
else if (released > ZIGBEE_RESET_PRESS)
{
ESP_ERROR_CHECK(esp_event_isr_post_to(
app_event_loop_handle,
CS_APP_EVENT,
CS_APP_EVENT_FACTORY_RESET,
NULL,
0,
NULL));
}
}
else
{
/* Falling line; key has been pressed. */
pressed = time(NULL);
released = pressed;
}
}

static void init_gpio(void)
{
/* Configure the LED GPIO lines used by T-ZigBee. */
gpio_config_t gpio_config_data = {
.pin_bit_mask = (1 << BLUE_LED) | (1 << TLSR8258_POWER),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
ESP_ERROR_CHECK(gpio_config(&gpio_config_data));

/* Configure the input key GPIO line used by T-ZigBee. */
gpio_config_data.pin_bit_mask = (1 << CLEAR_KEY);
gpio_config_data.mode = GPIO_MODE_INPUT;
gpio_config_data.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config_data.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config_data.intr_type = GPIO_INTR_ANYEDGE;
ESP_ERROR_CHECK(gpio_config(&gpio_config_data));
ESP_ERROR_CHECK(gpio_isr_register(intr_handler, NULL, ESP_INTR_FLAG_LEVEL1, NULL));
ESP_ERROR_CHECK(gpio_intr_enable(CLEAR_KEY));
}

static void factory_reset_timer_cb(void *arg)
{
cs_cfg_factory_reset();
esp_restart();
}

static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_base == CS_APP_EVENT)
{
switch (event_id)
{
case CS_APP_EVENT_FACTORY_RESET:
ESP_ERROR_CHECK(esp_event_post_to(
zigbee_event_loop_handle,
CS_ZIGBEE_EVENT,
CS_ZIGBEE_EVENT_FACTORY_RESET,
NULL,
0,
10));

/* Delay the ESP32c3 reset to allow ZigBee time to reset first. */
ESP_ERROR_CHECK(esp_timer_start_once(factory_reset_timer_handle, FACTORY_RESET_TIMER_WAIT));
break;

case CS_APP_EVENT_ZIGBEE_RESET:
ESP_ERROR_CHECK(esp_event_post_to(
zigbee_event_loop_handle,
CS_ZIGBEE_EVENT,
CS_ZIGBEE_EVENT_FACTORY_RESET,
NULL,
0,
10));
break;

default:
ESP_LOGE(TAG, "Unexpected flash event: %d", event_id);
break;
}
}
else
{
ESP_LOGE(TAG, "Unexpected event: %s, %d", event_base, event_id);
}
}

static void start_of_day()
{
/*
Expand Down Expand Up @@ -115,18 +259,28 @@ void app_main(void)
static esp_event_loop_handle_t web_event_loop_handle = NULL;
static esp_event_loop_handle_t ota_event_loop_handle = NULL;
static esp_event_loop_handle_t mqtt_event_loop_handle = NULL;
static esp_event_loop_handle_t zigbee_event_loop_handle = NULL;

// TODO: Remove this.
esp_log_level_set(TAG, ESP_LOG_VERBOSE);

/*
* Perform start-of-day checking.
*/
// TODO: Should be cs_cfg_init();
// TODO: Should be cs_cfg_init(); Also very messy having lots of stuff here!
cs_cfg_init();
init_gpio();
start_of_day();

/**
* Create various timers.
*/
esp_timer_create_args_t timer_create_args =
{
.callback = factory_reset_timer_cb,
.name = "F.Reset"
};
ESP_ERROR_CHECK(esp_timer_create(&timer_create_args, &factory_reset_timer_handle));

/**
* Instead of using FreeRTOS tasks and queues, CloudSMETS uses the ESP-IDF
* Event Loop Library. Each event loop is instantiated as a FreeRTOS task
Expand Down Expand Up @@ -198,6 +352,17 @@ void app_main(void)
create_parms.wifi.flash_event_loop_handle = flash_event_loop_handle;
cs_wifi_task(&create_parms.wifi);

/**
* Listen for events targetted to this app.
*/
ESP_ERROR_CHECK(esp_event_handler_instance_register_with(
app_event_loop_handle,
CS_APP_EVENT,
ESP_EVENT_ANY_ID,
event_handler,
NULL,
NULL));

// TODO: remove this which was added for testing.
#define NOW 1703592595
struct timeval now = { .tv_sec = NOW };
Expand Down
6 changes: 6 additions & 0 deletions esp32/cloudsmets/main/cs_app.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
typedef enum {
CS_APP_EVENT_FACTORY_RESET, /*!< Reset everything! */
CS_APP_EVENT_ZIGBEE_RESET, /*!< Reset ZigBee (new join). */
} cs_app_event_t;

ESP_EVENT_DECLARE_BASE(CS_APP_EVENT);
9 changes: 9 additions & 0 deletions esp32/cloudsmets/main/cs_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ static void cs_cfg_default(void)
#endif
}

/**
* Wipe all configuration from the NVS. We expect an immediate reboot after
* this happens.
*/
void cs_cfg_factory_reset(void)
{
nvs_flash_erase();
}

void cs_cfg_init(void)
{
// TODO: Remove this.
Expand Down
1 change: 1 addition & 0 deletions esp32/cloudsmets/main/cs_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,4 @@ extern void cs_cfg_write_uint8(const char *ns, const char *key, uint8_t value);
extern void cs_cfg_write_uint16(const char *ns, const char *key, uint16_t value);
extern void cs_cfg_write_uint32(const char *ns, const char *key, uint32_t value);
extern void cs_cfg_write_str(const char *ns, const char *key, const char *value);
extern void cs_cfg_factory_reset(void);
1 change: 0 additions & 1 deletion esp32/cloudsmets/main/cs_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ void update_flash_status(uint8_t status)
* - Triple flash, also connected to Azure IotHub
* - Solid blue, also receiving and relaying ZigBee messages.
*/

static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
Expand Down
26 changes: 13 additions & 13 deletions esp32/cloudsmets/main/cs_mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static void quote_plus(cs_string *in_str, cs_string *out_str)
out_str->length = out_len;
if (out_str->length > 0)
{
CS_STRING_MALLOC(out_str->value, (out_len + 1));
CS_STRING_MALLOC(out_str, (out_len + 1));
}
ESP_LOGV(TAG, "out_str len: %u, %p", out_str->length, out_str->value);

Expand Down Expand Up @@ -231,14 +231,14 @@ static void read_config()
unsigned char *sptr;

/* Free existing values and read new ones. */
CS_STRING_FREE(iothub_url);
CS_STRING_FREE(quoted_device_url);
CS_STRING_FREE(sign_key);
CS_STRING_FREE(device);
CS_STRING_FREE(username);
CS_STRING_FREE(access_keys[0]);
CS_STRING_FREE(access_keys[1]);
CS_STRING_FREE(sas_token);
CS_STRING_FREE(&iothub_url);
CS_STRING_FREE(&quoted_device_url);
CS_STRING_FREE(&sign_key);
CS_STRING_FREE(&device);
CS_STRING_FREE(&username);
CS_STRING_FREE(&access_keys[0]);
CS_STRING_FREE(&access_keys[1]);
CS_STRING_FREE(&sas_token);

/**
* Note that the length of read strings includes the NULL terminator so
Expand Down Expand Up @@ -285,7 +285,7 @@ static void read_config()
* Username is "<iothub-url-without-protocol>/devicename"
*/
username.length = iothub_url.length - PROTOCOL_MQTTS_LENGTH + 1+ device.length + 1;
CS_STRING_MALLOC(username.value, username.length);
CS_STRING_MALLOC(&username, username.length);
sptr = username.value;
memcpy(sptr, &iothub_url.value[PROTOCOL_MQTTS_LENGTH], (iothub_url.length - PROTOCOL_MQTTS_LENGTH));
sptr += iothub_url.length - PROTOCOL_MQTTS_LENGTH;
Expand All @@ -301,7 +301,7 @@ static void read_config()
#define DEVICES "/Devices/"
#define DEVICES_LEN (sizeof(DEVICES) - 1)
temp_url.length = iothub_url.length - PROTOCOL_MQTTS_LENGTH + DEVICES_LEN + device.length + 1;
CS_STRING_MALLOC(temp_url.value, temp_url.length);
CS_STRING_MALLOC(&temp_url, temp_url.length);
sptr = temp_url.value;
memcpy(sptr, &iothub_url.value[PROTOCOL_MQTTS_LENGTH], (iothub_url.length - PROTOCOL_MQTTS_LENGTH));
sptr += iothub_url.length - PROTOCOL_MQTTS_LENGTH;
Expand Down Expand Up @@ -332,7 +332,7 @@ static void read_config()
*/
sas_token.length = SAS_TOKEN_START_LEN + quoted_device_url.length + SAS_TOKEN_AND_SIG_LEN + URLENCODED_BASE64_SHA256_LEN + 10 + 1;
ESP_LOGV(TAG, "ST: %u", sas_token.length);
CS_STRING_MALLOC(sas_token.value, sas_token.length);
CS_STRING_MALLOC(&sas_token, sas_token.length);

/* Now we preload as much as we can into the token. */
sptr = sas_token.value;
Expand All @@ -353,7 +353,7 @@ static void read_config()
* plus a stringified time.
*/
sign_key.length = quoted_device_url.length + 1 + 11;
CS_STRING_MALLOC(sign_key.value, sign_key.length);
CS_STRING_MALLOC(&sign_key, sign_key.length);
sptr = sign_key.value;
memcpy(sptr, quoted_device_url.value, quoted_device_url.length);
sptr += quoted_device_url.length;
Expand Down
12 changes: 6 additions & 6 deletions esp32/cloudsmets/main/cs_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ typedef struct
} cs_string;

#define CS_STRING_FREE(X) \
if ((X.value) != NULL) \
if ((X)->value != NULL) \
{ \
free((X).value); \
(X).value = NULL; \
(X).length = 0; \
free((X)->value); \
(X)->value = NULL; \
(X)->length = 0; \
}

#define CS_STRING_MALLOC(DST, LEN) \
(DST) = malloc(LEN); \
if ((DST) == NULL) \
(DST)->value = malloc(LEN); \
if ((DST)->value == NULL) \
{ \
ESP_LOGE(TAG, "malloc failed for length: %d", (LEN)); \
ESP_ERROR_CHECK(ESP_FAIL); \
Expand Down
Loading

0 comments on commit ae7a8e7

Please sign in to comment.