Skip to content

Commit

Permalink
Add flashing LED.
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul D.Smith committed Dec 28, 2023
1 parent 909582a commit dfc7966
Show file tree
Hide file tree
Showing 12 changed files with 374 additions and 9 deletions.
2 changes: 1 addition & 1 deletion esp32/cloudsmets/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# As well as the source code, register the HTML and CSS files that we use to
# provide the web server.
idf_component_register(
SRCS "cs_app.c" "cs_cfg.c" "cs_mqtt.c" "cs_ota.c" "cs_time.c" "cs_web.c" "cs_wifi.c" "cs_zigbee.c"
SRCS "cs_app.c" "cs_flash.c" "cs_cfg.c" "cs_mqtt.c" "cs_ota.c" "cs_time.c" "cs_web.c" "cs_wifi.c" "cs_zigbee.c"
INCLUDE_DIRS "."
EMBED_TXTFILES index.html
EMBED_TXTFILES menu.html
Expand Down
29 changes: 28 additions & 1 deletion 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 "driver/gpio.h"

// #include "ft_err.h"
#include "pd_err.h"
Expand All @@ -31,20 +32,26 @@
#include "cs_ota.h"
#include "cs_mqtt.h"
#include "cs_time.h"
#include "cs_zigbee.h"
#include "cs_flash.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

static const char *cs_app_task = "App";
#define TAG cs_app_task

union cs_create_parms_t {
cs_flash_create_parms_t flash;
cs_wifi_create_parms_t wifi;
cs_web_create_parms_t web;
cs_ota_create_parms_t ota;
cs_mqtt_create_parms_t mqtt;
cs_zigbee_create_parms_t zigbee;
};

/*
Expand Down Expand Up @@ -96,14 +103,19 @@ static void start_of_day()
*/
ESP_LOGI(TAG, "start-of-day");
esp32_info();

/* Turn on the tlsr8258 by setting the GPIO that controls its power. */
ESP_ERROR_CHECK(gpio_set_level(TLSR8258_POWER, 1));
}

void app_main(void)
{
union cs_create_parms_t create_parms;
static esp_event_loop_handle_t flash_event_loop_handle = NULL;
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);
Expand Down Expand Up @@ -140,16 +152,24 @@ void app_main(void)
.task_stack_size = 32768,
.task_core_id = tskNO_AFFINITY
};
esp_event_loop_args.task_name = cs_flash_task_name;
ESP_ERROR_CHECK(esp_event_loop_create(&esp_event_loop_args, &flash_event_loop_handle));
esp_event_loop_args.task_name = cs_web_task_name;
ESP_ERROR_CHECK(esp_event_loop_create(&esp_event_loop_args, &web_event_loop_handle));
esp_event_loop_args.task_name = cs_ota_task_name;
ESP_ERROR_CHECK(esp_event_loop_create(&esp_event_loop_args, &ota_event_loop_handle));
esp_event_loop_args.task_name = cs_mqtt_task_name;
ESP_ERROR_CHECK(esp_event_loop_create(&esp_event_loop_args, &mqtt_event_loop_handle));
esp_event_loop_args.task_name = cs_zigbee_task_name;
ESP_ERROR_CHECK(esp_event_loop_create(&esp_event_loop_args, &zigbee_event_loop_handle));

ESP_LOGI(TAG, "Creating tasks...");
// TODO: Create Azure, ZigBee etc.

/* Create the LED flasher task. */
create_parms.flash.flash_event_loop_handle = flash_event_loop_handle;
cs_flash_task(&create_parms.flash);

/* Web server needs to know about any task that can be configured. */
create_parms.web.web_event_loop_handle = web_event_loop_handle;
create_parms.web.ota_event_loop_handle = ota_event_loop_handle;
Expand All @@ -162,13 +182,20 @@ void app_main(void)

/* Create the MQTT task. */
create_parms.mqtt.mqtt_event_loop_handle = mqtt_event_loop_handle;
create_parms.mqtt.flash_event_loop_handle = flash_event_loop_handle;
cs_mqtt_task(&create_parms.mqtt);

/* Create the ZigBee task. */
create_parms.zigbee.zigbee_event_loop_handle = zigbee_event_loop_handle;
create_parms.zigbee.mqtt_event_loop_handle = mqtt_event_loop_handle;
create_parms.zigbee.flash_event_loop_handle = flash_event_loop_handle;
cs_zigbee_task(&create_parms.zigbee);

/**
* Wifi has to start before anything else can happen.
* starting the Wifi task should also get the entire app rolling.
*/
create_parms.wifi.dummy = NULL;
create_parms.wifi.flash_event_loop_handle = flash_event_loop_handle;
cs_wifi_task(&create_parms.wifi);

// TODO: remove this which was added for testing.
Expand Down
1 change: 1 addition & 0 deletions esp32/cloudsmets/main/cs_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ESP_EVENT_DEFINE_BASE(CS_CONFIG_EVENT);
* Namespaces, used to partition components.
*/
const char *cs_app_task_name = "App";
const char *cs_flash_task_name = "Flash";
const char *cs_wifi_task_name = "WiFi";
const char *cs_web_task_name = "Web";
// const char *cs_cfg__log_task_name = "Log";
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 @@ -24,6 +24,7 @@ ESP_EVENT_DECLARE_BASE(CS_CONFIG_EVENT);
* Namespaces and task names.
*/
extern const char *cs_app_task_name;
extern const char *cs_flash_task_name;
extern const char *cs_wifi_task_name;
extern const char *cs_web_task_name;
// extern const char *cfgDbg;
Expand Down
248 changes: 248 additions & 0 deletions esp32/cloudsmets/main/cs_flash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*
* Copyright (c) 2023 Paul D.Smith ([email protected]).
* License: Free to copy providing the author is acknowledged.
*
* Configuration store using ESP-IDF no-volatile storage.
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/nvs_flash.html?highlight=non%20volatile
*
* Note that this API operates on the default NVRAM partition.
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
/**
* Allow logging in this file; disabled unless explcitly set.
*/
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_timer.h"
#include "driver/gpio.h"
#include "mqtt_client.h"

#include "cs_cfg.h"
#include "cs_flash.h"
#include "cs_zigbee.h"

#define TAG cs_flash_task_name

ESP_EVENT_DEFINE_BASE(CS_FLASH_EVENT);

/* This is a little naughty, but we know it does exist! */
ESP_EVENT_DECLARE_BASE(MQTT_EVENTS);

esp_event_loop_handle_t flash_event_loop_handle;

#define STATUS_WIFI_SOFTAP_CONNECTED 0x01
#define STATUS_WIFI_AP_CONNECTED 0x02
#define STATUS_MQTT_CONNECTED 0x04
#define STATUS_ZIGBEE_CONNECTED 0x08

#define ALL_ZIGBEE_ACTIVE 0x0F
#define ALL_MQTT_ACTIVE 0x07
#define ALL_WIFI_AP_ACTIVE 0x03
#define ALL_WIFI_SOFTAP_ACTIVE 0x01

#define BLUE_LED GPIO_NUM_3

esp_timer_handle_t flash_timer_handle = NULL;

static int flashes_per_cycle = 0;

static void led_on()
{
esp_timer_stop(flash_timer_handle);
ESP_ERROR_CHECK(gpio_set_level(BLUE_LED, 1));
}

static void led_off()
{
esp_timer_stop(flash_timer_handle);
ESP_ERROR_CHECK(gpio_set_level(BLUE_LED, 0));
}

#define FLASH_TIME_PERIOD (uint64_t)1000 * 500
static void led_flash(int flashes)
{
// TODO: Much nicer if we get rid of globals.
flashes_per_cycle = flashes;
if (!esp_timer_is_active(flash_timer_handle))
{
esp_timer_start_periodic(flash_timer_handle, FLASH_TIME_PERIOD);
}
}

/**
* The timer is intended to flash as follows:
* on, off, off, off
* on, off, on, off, off, off
* on, off, on, off, on, off, off, off
* So a sequence of X (on, off) followed by (off, off).
*/
void flash_timer_cb(void *arg)
{
static int count = 0;
static bool lit = false;

if (lit)
{
/* From lit, always off. */
led_off();
}
else
{
if (count <= 0)
{
/* Time for next cycle but LED stays off for this cycle. */
count = flashes_per_cycle;
}
else
{
/* Turn the LED on. */
led_on();
}
count--;
}
lit = !lit;
}

void update_flash_status(uint8_t status)
{
if ((status & ALL_ZIGBEE_ACTIVE) == ALL_ZIGBEE_ACTIVE)
{
led_on();
}
else if ((status & ALL_MQTT_ACTIVE) == ALL_MQTT_ACTIVE)
{
led_flash(3);
}
else if ((status & ALL_WIFI_AP_ACTIVE) == ALL_WIFI_AP_ACTIVE)
{
led_flash(2);
}
else if ((status & ALL_WIFI_SOFTAP_ACTIVE) == ALL_WIFI_SOFTAP_ACTIVE)
{
led_flash(1);
}
else
{
led_off();
}
}

/***
* Status of the device will be identified as follows:
* - No light, not even SoftAP is ready.
* - Single flash, SoftAP web server is available
* - Double flash, also connected to AP (router)
* - 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)
{
uint8_t status = 0;

if (event_base == WIFI_EVENT)
{
switch (event_id)
{
case WIFI_EVENT_AP_STACONNECTED:
status |= STATUS_WIFI_SOFTAP_CONNECTED;
break;

case WIFI_EVENT_AP_STADISCONNECTED:
status &= ~STATUS_WIFI_SOFTAP_CONNECTED;
break;

case WIFI_EVENT_STA_CONNECTED:
status |= STATUS_WIFI_AP_CONNECTED;
break;

case WIFI_EVENT_STA_DISCONNECTED:
status &= ~STATUS_WIFI_AP_CONNECTED;
break;

default:
ESP_LOGE(TAG, "Unexpected flash event: %d", event_id);
break;
}
}
else if (event_base == MQTT_EVENTS)
{
switch (event_id)
{
case MQTT_EVENT_CONNECTED:
status |= STATUS_MQTT_CONNECTED;
break;

case MQTT_EVENT_DISCONNECTED:
status &= ~STATUS_MQTT_CONNECTED;
break;

default:
ESP_LOGE(TAG, "Unexpected flash event: %d", event_id);
break;
}
}
else if (event_base == CS_ZIGBEE_EVENT)
{
switch (event_id)
{
case CS_ZIGBEE_EVENT_CONNECTED:
status |= STATUS_ZIGBEE_CONNECTED;
break;

case CS_ZIGBEE_EVENT_DISCONNECTED:
status &= ~STATUS_ZIGBEE_CONNECTED;
break;

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

void cs_flash_task(cs_flash_create_parms_t *create_parms)
{
static int flashes = 0;

flash_event_loop_handle = create_parms->flash_event_loop_handle;

/**
* We can listen for WiFi events but only on the default event loop and
* we cannot register for MQTT events because they are obfuscated. So we
* rely on the various components sending events to our handler.
*/
ESP_ERROR_CHECK(esp_event_handler_instance_register_with(
flash_event_loop_handle,
WIFI_EVENT,
ESP_EVENT_ANY_ID,
event_handler,
(void *)&flashes,
NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register_with(
flash_event_loop_handle,
MQTT_EVENTS,
ESP_EVENT_ANY_ID,
event_handler,
(void *)&flashes,
NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register_with(
flash_event_loop_handle,
CS_ZIGBEE_EVENT,
ESP_EVENT_ANY_ID,
event_handler,
(void *)&flashes,
NULL));
}
Loading

0 comments on commit dfc7966

Please sign in to comment.