From d38934e76e30339568a5786498136161c6c0b281 Mon Sep 17 00:00:00 2001 From: Aaron Perley Date: Mon, 14 May 2018 18:58:22 -0400 Subject: [PATCH 1/3] Add runtime configuration mode using soft ap --- .gitmodules | 3 + README.md | 13 + .../components/http-parser/component.mk | 3 + .../components/http-parser/http-parser | 1 + Source/framework/main/config.c | 53 ++++ Source/framework/main/config_server.c | 115 +++++++++ Source/framework/main/http_server.c | 238 ++++++++++++++++++ Source/framework/main/include/config.h | 24 ++ Source/framework/main/include/config_server.h | 16 ++ Source/framework/main/include/http_server.h | 37 +++ Source/framework/main/include/wifi_module.h | 8 + Source/framework/main/wifi_module.c | 148 +++++++++-- 12 files changed, 632 insertions(+), 27 deletions(-) create mode 100644 Source/framework/components/http-parser/component.mk create mode 160000 Source/framework/components/http-parser/http-parser create mode 100644 Source/framework/main/config.c create mode 100644 Source/framework/main/config_server.c create mode 100644 Source/framework/main/http_server.c create mode 100644 Source/framework/main/include/config.h create mode 100644 Source/framework/main/include/config_server.h create mode 100644 Source/framework/main/include/http_server.h diff --git a/.gitmodules b/.gitmodules index b091b5fa..295dd4de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "Support/esp-idf"] path = Support/esp-idf url = https://github.com/WiseLabCMU/esp-idf.git +[submodule "Source/framework/components/http-parser/http-parser"] + path = Source/framework/components/http-parser/http-parser + url = https://github.com/nodejs/http-parser.git diff --git a/README.md b/README.md index 3f5bef25..1b303a6c 100644 --- a/README.md +++ b/README.md @@ -56,3 +56,16 @@ This small accessory board holds the connector to support CTA2045 and other RS48 ``` $ make flash ``` + +# Runtime Configuration +The WiFi SSID and password can be configured at runtime (without recompiling and reflashing the module). Other parameters could be added as necessary. +Configuration parameters are stored in flash using the [NVS Library](http://esp-idf.readthedocs.io/en/latest/api-reference/storage/nvs_flash.html). +On initialization of the wifi module, if stored wifi configuration parameters exist, they are loaded and used to connect to wifi. +If no parameters exist, the module launches configuration mode. + +In configuration mode, the module broadcasts a wifi network named "gridballast". A user can connect to the gridballast network and open +http://[module-ip]/ (by default 192.168.1.4, can be found programatically with `tcpip_adapter_get_ip_info`) in a web browser. The module will present a webpage where the SSID and password can be configured. +To exit configuration mode, the module must be rebooted. + +TODO: Gridballast should also support entering configuration mode by pushing a button. +This can be done by calling `wifi_enter_config_mode()` (see `Source/framework/main/include/wifi_module.h`). diff --git a/Source/framework/components/http-parser/component.mk b/Source/framework/components/http-parser/component.mk new file mode 100644 index 00000000..13c06f79 --- /dev/null +++ b/Source/framework/components/http-parser/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS = http-parser +COMPONENT_SRCDIRS = http-parser +COMPONENT_OBJS = http-parser/http_parser.o diff --git a/Source/framework/components/http-parser/http-parser b/Source/framework/components/http-parser/http-parser new file mode 160000 index 00000000..54f55a2f --- /dev/null +++ b/Source/framework/components/http-parser/http-parser @@ -0,0 +1 @@ +Subproject commit 54f55a2f02a823e5f5c87abe853bb76d1170718d diff --git a/Source/framework/main/config.c b/Source/framework/main/config.c new file mode 100644 index 00000000..7564061b --- /dev/null +++ b/Source/framework/main/config.c @@ -0,0 +1,53 @@ +/** + * @file config.c + * + * @brief manage config data saved in nonvolatile storage + * + * @author Aaron Perley + */ + +#include +#include +#include +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "config.h" + +static const char *TAG = "config"; +static nvs_handle handle = 0; + +void config_init() { + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // NVS partition was truncated and needs to be erased + ESP_LOGI(TAG, "Erasing and reinitializing NVS partition"); + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + ESP_ERROR_CHECK(nvs_open("config", NVS_READWRITE, &handle)); + ESP_LOGI(TAG, "NVS handle opened"); +} + +esp_err_t config_get_wifi(char *ssid, size_t ssid_len, char *password, size_t password_len) { + esp_err_t err = nvs_get_str(handle, "ssid", ssid, &ssid_len); + if (err != ESP_OK) { + return err; + } + + err = nvs_get_str(handle, "pass", password, &password_len); + return err; +} + +esp_err_t config_set(const char *field, const char *val) { + ESP_LOGI(TAG, "config setting %s = %s", field, val); + return nvs_set_str(handle, field, val); +} + +esp_err_t config_commit() { + return nvs_commit(handle); +} diff --git a/Source/framework/main/config_server.c b/Source/framework/main/config_server.c new file mode 100644 index 00000000..7f2eda45 --- /dev/null +++ b/Source/framework/main/config_server.c @@ -0,0 +1,115 @@ +/** + * @file config_server.h + * + * @brief serve configuration webpage + * + * @author Aaron Perley + */ + +#include +#include +#include "config.h" +#include "esp_log.h" +#include "http_server.h" +#include "http_parser.h" +#include "nvs.h" + +static const char *TAG = "config_server"; + +static const char * const config_html_fmt = +"" +"" +"" +"
" + "
" + "
" + "" +"
" +"" +""; + +static void send_html(http_client_conn_t *conn) { + // try to read saved wifi config + char ssid[ssid_maxlen] = ""; + char pass[pass_maxlen] = ""; + esp_err_t err = config_get_wifi(ssid, ssid_maxlen, pass, pass_maxlen); + if (err != ESP_ERR_NVS_NOT_FOUND) { + ESP_ERROR_CHECK(err); + } + + int buf_len = snprintf(NULL, 0, config_html_fmt, ssid, pass); + char *buf = malloc(buf_len + 1); + if (buf == NULL) { + return; + } + snprintf(buf, buf_len + 1, config_html_fmt, ssid, pass); + + http_client_send(conn, buf); + free(buf); +} + +static void handle_get(http_client_conn_t *conn) { + ESP_LOGI(TAG, "Got GET request"); + send_html(conn); +} + +static void parse_body(char *body) { + char *field = strtok(body, "="); + int fields_set = 0; + while (field != NULL) { + if (strcmp(field, "ssid") != 0 && strcmp(field, "pass") != 0) { + ESP_LOGE(TAG, "Unknown form field %s", field); + return; + } + + // copy from body into field + char *val = strtok(NULL, "&"); + if (val == NULL) { + return; + } + + // support spaces in value (which get encoded into +s) + for (char *chr = val; *chr != '\0'; chr++) { + if (*chr == '+') { + *chr = ' '; + } + } + ESP_ERROR_CHECK(config_set(field, val)); + fields_set++; + + // advance to next field + field = strtok(NULL, "="); + } + + if (fields_set == 2) { + ESP_ERROR_CHECK(config_commit()); + } +} + +static void handle_post(http_client_conn_t *conn, char *body) { + ESP_LOGI(TAG, "Got POST request %s", body); + parse_body(body); + send_html(conn); +} + +static void req_handler(http_client_conn_t *client_conn, http_req_t *req) { + if (strcmp(req->url, "/") == 0) { + // only serve index route + switch(req->method) { + case HTTP_GET: + handle_get(client_conn); + break; + case HTTP_POST: + handle_post(client_conn, req->body); + break; + default: + ESP_LOGE(TAG, "Unsupported HTTP method %d", req->method); + break; + } + } +} + +// Interface functions +void config_server_run() { + http_server_run(80, req_handler); +} diff --git a/Source/framework/main/http_server.c b/Source/framework/main/http_server.c new file mode 100644 index 00000000..72900093 --- /dev/null +++ b/Source/framework/main/http_server.c @@ -0,0 +1,238 @@ +/** + * @file http_server.c + * + * @brief Simple HTTP server for runtime system configuration + * + * @author Aaron Perley (aperley@andrew.cmu.edu) + */ + +#include +#include +#include +#include "esp_log.h" +#include "esp_system.h" +#include "lwip/err.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "http_parser.h" +#include "http_server.h" + +/** @brief Number of queued clients */ +#define LISTEN_QUEUE_LEN (5) + +static const char *TAG = "http_server"; + +/***************************************** + ************ MODULE FUNCTIONS *********** + *****************************************/ + +/** + * @brief utility function to append to a malloc'd string + * + * @param dest pointer to malloc'd string to append to + * @param src string to append + * @param len length to append + * + * @return 0 on success, -1 on failure + */ +static int create_or_append_str(char **dest, const char *src, size_t len) { + // malloc or realloc + if (*dest == NULL) { + // dest has not been allocated + *dest = malloc(len + 1); // extra byte for null terminator + if (*dest == NULL) { + return -1; + } + (*dest)[0] = '\0'; // initally null terminate so strncat will work + } else { + // dest has been allocated so grow + char *new_dest = realloc(*dest, strlen(*dest) + len + 1); + if (new_dest == NULL) { + free(*dest); + return -1; + } + *dest = new_dest; + } + + strncat(*dest, src, len); + return 0; +} + + +/** + * @brief callback that runs when the parse is complete + * + * Sets complete field of request data so we know to stop reading from client + */ +int on_complete_cb(http_parser *parser) { + http_req_t *req_data = (http_req_t *)parser->data; + req_data->complete = true; + return 0; +} + +/** + * @brief callback that runs when url is parsed + */ +int on_url_cb(http_parser *parser, const char *at, size_t length) { + http_req_t *req_data = (http_req_t *)parser->data; + req_data->method = parser->method; + return create_or_append_str(&req_data->url, at, length); +} + +/** + * @brief callback that runs when request body is received + */ +int on_body_cb(http_parser *parser, const char *at, size_t length) { + http_req_t *req_data = (http_req_t *)parser->data; + return create_or_append_str(&req_data->body, at, length); +} + +/** + * @brief parse http client request and trigger user callback + * + * @param fd socket file descriptor + */ +void handle_client(http_client_conn_t *conn, http_req_handler_t req_handler) { + const size_t buf_len = 1024; + char *buf = malloc(buf_len); + if (buf == NULL) { + return; + } + + // configure http parser + http_parser parser; + http_parser_init(&parser, HTTP_REQUEST); + http_parser_settings settings; + memset(&settings, 0, sizeof(settings)); + settings.on_message_complete = on_complete_cb; + settings.on_url = on_url_cb; + settings.on_body = on_body_cb; + + http_req_t *req_data = malloc(sizeof(http_req_t)); + if (req_data == NULL) { + free(buf); + return; + } + memset(req_data, 0, sizeof(http_req_t)); + parser.data = req_data; + + // read and parse request + bool read_err = false; + while (!req_data->complete && HTTP_PARSER_ERRNO(&parser) == HPE_OK) { + ssize_t read_len = read(conn->fd, buf, buf_len); + if (read_len < 0) { + read_err = true; + ESP_LOGE(TAG, "Socket read error: %s", strerror(errno)); + break; + } + + int nparsed = http_parser_execute(&parser, &settings, buf, read_len); + if (nparsed != read_len) { + read_err = true; + ESP_LOGE(TAG, "HTTP parser error: read %zd bytes but parsed %d bytes", + read_len, nparsed); + break; + } + } + + free(buf); + + if (!read_err) { + enum http_errno http_errno = HTTP_PARSER_ERRNO(&parser); + if (http_errno == HPE_OK) { + // let user handle request + req_handler(conn, req_data); + } else { + ESP_LOGE(TAG, "HTTP parser error: %s %s", http_errno_name(http_errno), + http_errno_description(http_errno)); + } + } + + if (req_data->url != NULL) { + free(req_data->url); + } + if (req_data->body != NULL) { + free(req_data->body); + } + free(req_data); +} + + +/***************************************** + *********** INTERFACE FUNCTIONS ********* + *****************************************/ + +/** + * @brief run http server + * + * @param port port to listen on + * @param req_handler user callback function to run on parsed request + */ +void http_server_run(int port, http_req_handler_t req_handler) { + struct sockaddr_in server_addr, client_addr; + socklen_t sin_size = sizeof(client_addr); + bzero(&server_addr, sizeof(struct sockaddr_in)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + int server_sock; + if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ESP_LOGE(TAG, "bind error %s", strerror(errno)); + } + if (bind(server_sock, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) < 0) { + ESP_LOGE(TAG, "bind error %s", strerror(errno)); + } + if (listen(server_sock, LISTEN_QUEUE_LEN) < 0) { + ESP_LOGE(TAG, "listen error %s", strerror(errno)); + } + + while (1) { + int client_sock = accept(server_sock, (struct sockaddr *) &client_addr, &sin_size); + if (client_sock < 0) { + ESP_LOGE(TAG, "accept error %s", strerror(errno)); + break; + } + http_client_conn_t client_conn; + client_conn.fd = client_sock; + handle_client(&client_conn, req_handler); + close(client_sock); + } +} + +const char *http_resp_header_fmt = + "HTTP/1.1 200 OK\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "Conent-Length: %zu\r\n" + "\r\n"; + +/** + * @brief send response data back to client + * + * @param client_conn client connection state + * @param buf response body + * + * @note This function must only be called once from inside the user request + * handler callback. It only supports 200 OK responses right now. + */ +int http_client_send(http_client_conn_t *client_conn, const char *buf) { + int header_len = snprintf(NULL, 0, http_resp_header_fmt, strlen(buf)); + char *header_buf = malloc(header_len + 1); + if (header_buf == NULL) { + return -1; + } + snprintf(header_buf, header_len + 1, http_resp_header_fmt, strlen(buf)); + ssize_t write_len = write(client_conn->fd, header_buf, header_len); + if (write_len < 0) { + free(header_buf); + return -1; + } + free(header_buf); + + write_len = write(client_conn->fd, buf, strlen(buf)); + if (write_len < 0) { + return -1; + } + return 0; +} diff --git a/Source/framework/main/include/config.h b/Source/framework/main/include/config.h new file mode 100644 index 00000000..f6941c31 --- /dev/null +++ b/Source/framework/main/include/config.h @@ -0,0 +1,24 @@ +/** + * @file config.h + * + * @brief manage config data saved in nonvolatile storage + * + * @author Aaron Perley + */ + +#ifndef __config_module_h_ +#define __config_module_h_ + +#include "esp_system.h" +#include "esp_wifi.h" + +#define ssid_maxlen sizeof(((wifi_config_t *)0)->sta.ssid) +#define pass_maxlen sizeof(((wifi_config_t *)0)->sta.password) + +void config_init(); +esp_err_t config_get_wifi(char *ssid, size_t ssid_len, char *password, size_t password_len); +esp_err_t config_set(const char *field, const char *val); +esp_err_t config_commit(); + +#endif /* __config_module_h_ */ + diff --git a/Source/framework/main/include/config_server.h b/Source/framework/main/include/config_server.h new file mode 100644 index 00000000..4e57af0b --- /dev/null +++ b/Source/framework/main/include/config_server.h @@ -0,0 +1,16 @@ +/** + * @file config_server.h + * + * @brief serve configuration webpage + * + * @author Aaron Perley + */ + +#ifndef __config_server_module_h_ +#define __config_server_module_h_ + +void config_server_run(); + +#endif /* __config_server_module_h_ */ + + diff --git a/Source/framework/main/include/http_server.h b/Source/framework/main/include/http_server.h new file mode 100644 index 00000000..84113b9e --- /dev/null +++ b/Source/framework/main/include/http_server.h @@ -0,0 +1,37 @@ +/** + * @file http_server.h + * + * @brief Simple HTTP server for runtime system configuration + * + * @author Aaron Perley (aperley@andrew.cmu.edu) + */ + +#ifndef __http_server_h_ +#define __http_server_h_ + +/** @brief http client connection state */ +typedef struct { + int fd; +} http_client_conn_t; + +/** @brief http request data */ +typedef struct { + unsigned int method; + char *url; + char *body; + bool complete; +} http_req_t; + +/** + * @brief callback to handle http connecton + * + * @param client_conn client connection state + * @param req request data + */ +typedef void (*http_req_handler_t)(http_client_conn_t *client_conn, http_req_t *req); + +void http_server_run(int port, http_req_handler_t req_handler); +int http_client_send(http_client_conn_t *client_conn, const char *buf); + +#endif /* __http_server_h_ */ + diff --git a/Source/framework/main/include/wifi_module.h b/Source/framework/main/include/wifi_module.h index b05baad2..721dca6e 100644 --- a/Source/framework/main/include/wifi_module.h +++ b/Source/framework/main/include/wifi_module.h @@ -24,4 +24,12 @@ extern const char * const wifi_task_name; */ void wifi_init_task( void ); +/** + * @brief exit normal data publish/receive mode and enter configuration mode + * + * @note configuration mode can only be exited by rebooting the module + * @note this function can be called from other tasks or interrupts + */ +void wifi_enter_config_mode(); + #endif /* __wifi_module_h_ */ diff --git a/Source/framework/main/wifi_module.c b/Source/framework/main/wifi_module.c index fedc51de..bad36776 100644 --- a/Source/framework/main/wifi_module.c +++ b/Source/framework/main/wifi_module.c @@ -24,9 +24,14 @@ #include "esp_request.h" #include "wifi_module.h" #include "util.h" +#include "config.h" +#include "nvs.h" +#include "config_server.h" -#define WIFI_SSID "CMU" -#define WIFI_PASS "" +typedef enum { + MODULE_MODE_NORMAL, + MODULE_MODE_CONFIG +} module_mode_t; /* OpenChirp transducer ids for system state fields */ #define TRANSDUCER_ID_TEMP_BOTTOM "5a016520f230cf7055615e56" @@ -37,12 +42,11 @@ const char * const wifi_task_name = "wifi_module_task"; static const char *TAG = "wifi"; -/** @brief FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; +static volatile module_mode_t module_mode; -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ +/** @brief FreeRTOS event group to signal when softap is up */ +static EventGroupHandle_t wifi_event_group; +const int SOFTAP_UP_BIT = BIT1; const int CONNECTED_BIT = BIT0; /* OpenChirp API definitions */ @@ -55,16 +59,35 @@ static system_state_t system_state; /* Static function definitions */ static void reset_transducer_response(); +static void run_mode_normal(); +static void run_mode_config(); /** * @brief Wifi event handler */ static esp_err_t event_handler(void *ctx, system_event_t *event) { switch(event->event_id) { + case SYSTEM_EVENT_AP_START: + ESP_LOGI(TAG, "Got event AP_START"); + xEventGroupSetBits(wifi_event_group, SOFTAP_UP_BIT); + break; + case SYSTEM_EVENT_AP_STOP: + ESP_LOGI(TAG, "Got event AP_STOP"); + xEventGroupClearBits(wifi_event_group, SOFTAP_UP_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "Got event AP_STACONNECTED"); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "Got event AP_STADISCONNECTED"); + break; case SYSTEM_EVENT_STA_START: ESP_LOGI(TAG, "Got event start"); esp_wifi_connect(); break; + case SYSTEM_EVENT_STA_STOP: + ESP_LOGI(TAG, "Got event stop"); + break; case SYSTEM_EVENT_STA_GOT_IP: ESP_LOGI(TAG, "Got event got ip"); xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); @@ -83,36 +106,54 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) { } /** - * @brief Initialize the wifi module + * @brief Common wifi initialization that occurs before the wifi task starts */ -static void initialise_wifi(void) { +static void init_wifi(void) { tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = WIFI_SSID, - .password = WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); + + config_init(); +} + +/** + * @brief Set wifi to station mode (connect to access point) + */ +static void init_mode_sta(const char *ssid, const char *password) { + wifi_config_t wifi_config; + strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); + strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password)); + + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s password %s", wifi_config.sta.ssid, wifi_config.sta.password); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - // Log MAC address - uint8_t mac[6]; - ESP_ERROR_CHECK( esp_wifi_get_mac(ESP_IF_WIFI_STA, mac) ); - char mac_str[18]; - sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]); - ESP_LOGI(TAG, "My MAC Address: %s", mac_str); - ESP_ERROR_CHECK( esp_wifi_start() ); +} - reset_transducer_response(); +/** + * @brief Set wifi to soft-ap mode (serve as access point) + */ +static void init_mode_ap(void) { + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) ); + wifi_config_t ap_config = { + .ap = { + .ssid = "gridballast", + .channel = 0, + .authmode = WIFI_AUTH_OPEN, + .ssid_hidden = 0, + .max_connection = 4, + .beacon_interval = 100 + } + }; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + ESP_ERROR_CHECK( esp_wifi_start() ); + ESP_LOGI(TAG, "Wifi started in AP mode, SSID %s", ap_config.ap.ssid); } /***************************************** @@ -357,7 +398,39 @@ static int send_data(system_state_t *system_state) { * @return void */ static void wifi_task_fn( void *pv_parameters ) { - while(1) { + // try to read saved wifi config + char ssid[ssid_maxlen]; + char pass[pass_maxlen]; + esp_err_t err = config_get_wifi(ssid, ssid_maxlen, pass, pass_maxlen); + if (err == ESP_ERR_NVS_NOT_FOUND) { + // no saved values, so enter config mode + module_mode = MODULE_MODE_CONFIG; + } else { + ESP_ERROR_CHECK(err); + // saved values, so enter normal mode + module_mode = MODULE_MODE_NORMAL; + } + + while (1) { + // loop to allow exiting normal mode and entering config mode + switch (module_mode) { + case MODULE_MODE_NORMAL: + init_mode_sta(ssid, pass); + run_mode_normal(); + break; + case MODULE_MODE_CONFIG: + init_mode_ap(); + run_mode_config(); + break; + } + ESP_ERROR_CHECK(esp_wifi_stop()); + } +} + +static void run_mode_normal() { + reset_transducer_response(); + ESP_LOGI(TAG, "Running normal mode"); + while (module_mode == MODULE_MODE_NORMAL) { /* Wait for the callback to set the CONNECTED_BIT in the event group. */ @@ -391,6 +464,17 @@ static void wifi_task_fn( void *pv_parameters ) { } } + +static void run_mode_config() { + xEventGroupWaitBits(wifi_event_group, SOFTAP_UP_BIT, false, true, portMAX_DELAY); + tcpip_adapter_ip_info_t ip_info; + ESP_ERROR_CHECK( tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info) ); + ESP_LOGI(TAG, "Config mode: connect to the gridballast wifi network and go to http://%s", ip4addr_ntoa(&ip_info.ip)); + ESP_LOGI(TAG, "Reboot to exit config mode"); + + config_server_run(); +} + /***************************************** *********** INTERFACE FUNCTIONS ********* *****************************************/ @@ -403,7 +487,7 @@ static void wifi_task_fn( void *pv_parameters ) { void wifi_init_task( void ) { printf("Intializing Wifi System..."); - initialise_wifi(); + init_wifi(); xTaskCreate( &wifi_task_fn, /* task function */ wifi_task_name, /* wifi task name */ @@ -414,3 +498,13 @@ void wifi_init_task( void ) { ); fflush(stdout); } + +/** + * @brief exit normal data publish/receive mode and enter configuration mode + * + * @note configuration mode can only be exited by rebooting the module + * @note this function can be called from other tasks or interrupts + */ +void wifi_enter_config_mode() { + module_mode = MODULE_MODE_CONFIG; +} From 511c36cca9bf0e9c82ccf89cfdba9bb9a584ef2c Mon Sep 17 00:00:00 2001 From: ro269 Date: Wed, 11 Jul 2018 14:46:49 -0400 Subject: [PATCH 2/3] Create pictures --- pictures | 1 + 1 file changed, 1 insertion(+) create mode 100644 pictures diff --git a/pictures b/pictures new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/pictures @@ -0,0 +1 @@ + From 2e0e00bcfd794af9c6ad1233cf0c02192af23968 Mon Sep 17 00:00:00 2001 From: ro269 Date: Wed, 11 Jul 2018 14:47:13 -0400 Subject: [PATCH 3/3] Delete pictures --- pictures | 1 - 1 file changed, 1 deletion(-) delete mode 100644 pictures diff --git a/pictures b/pictures deleted file mode 100644 index 8b137891..00000000 --- a/pictures +++ /dev/null @@ -1 +0,0 @@ -