summaryrefslogtreecommitdiff
path: root/fw/esp32/components/eos/wifi.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/esp32/components/eos/wifi.c')
-rwxr-xr-xfw/esp32/components/eos/wifi.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/fw/esp32/components/eos/wifi.c b/fw/esp32/components/eos/wifi.c
new file mode 100755
index 0000000..d47ae3a
--- /dev/null
+++ b/fw/esp32/components/eos/wifi.c
@@ -0,0 +1,343 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+
+#include <esp_system.h>
+#include <esp_event.h>
+#include <esp_log.h>
+#include <esp_err.h>
+#include <esp_wifi.h>
+#include <nvs_flash.h>
+
+#include "eos.h"
+#include "net.h"
+#include "wifi.h"
+
+// XXX: WiFi fail due to no DHCP server
+
+#define WIFI_MAX_SCAN_RECORDS 20
+#define WIFI_MAX_CONNECT_ATTEMPTS 3
+
+#define WIFI_STATE_STOPPED 0
+#define WIFI_STATE_SCANNING 1
+#define WIFI_STATE_CONNECTING 2
+#define WIFI_STATE_CONNECTED 3
+#define WIFI_STATE_DISCONNECTING 4
+#define WIFI_STATE_DISCONNECTED 5
+
+#define WIFI_ACTION_NONE 0
+#define WIFI_ACTION_SCAN 1
+#define WIFI_ACTION_CONNECT 2
+#define WIFI_ACTION_DISCONNECT 3
+
+static const char *TAG = "EOS WIFI";
+
+static SemaphoreHandle_t mutex;
+
+static wifi_config_t wifi_sta_config;
+static wifi_scan_config_t wifi_scan_config;
+
+static int wifi_connect_cnt = 0;
+static uint8_t wifi_action;
+static uint8_t wifi_state;
+static wifi_ap_record_t scan_r[WIFI_MAX_SCAN_RECORDS];
+static uint16_t scan_n;
+
+static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
+ esp_err_t ret = ESP_OK;
+ char _disconnect;
+ uint8_t _action, _state;
+ unsigned char *rbuf, *p;
+ int i, len;
+ ip_event_got_ip_t *got_ip;
+
+ if (event_base == WIFI_EVENT) {
+ switch(event_id) {
+ case WIFI_EVENT_SCAN_DONE:
+ scan_n = WIFI_MAX_SCAN_RECORDS;
+ memset(scan_r, 0, sizeof(scan_r));
+ esp_wifi_scan_get_ap_records(&scan_n, scan_r);
+
+ ESP_LOGI(TAG, "Scan done: %d", scan_n);
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ _state = wifi_state;
+ if (wifi_state == WIFI_STATE_CONNECTED) wifi_action = WIFI_ACTION_NONE;
+ xSemaphoreGive(mutex);
+
+ if (_state != WIFI_STATE_CONNECTED) ret = esp_wifi_stop();
+
+ rbuf = eos_net_alloc();
+ rbuf[0] = EOS_WIFI_MTYPE_SCAN;
+ p = rbuf + 1;
+ for (i=0; i<scan_n; i++) {
+ len = strnlen((char *)scan_r[i].ssid, 33);
+ if (len > 32) continue;
+ if (p - rbuf + len + 1 > EOS_NET_MTU) break;
+ strcpy((char *)p, (char *)scan_r[i].ssid);
+ p += len + 1;
+ }
+ eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, p - rbuf);
+ break;
+
+ case WIFI_EVENT_STA_START:
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ _action = wifi_action;
+ xSemaphoreGive(mutex);
+
+ switch (_action) {
+ case WIFI_ACTION_SCAN:
+ ret = esp_wifi_scan_start(&wifi_scan_config, 0);
+ break;
+
+ case WIFI_ACTION_CONNECT:
+ ret = esp_wifi_connect();
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case WIFI_EVENT_STA_STOP:
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ wifi_state = WIFI_STATE_STOPPED;
+ wifi_action = WIFI_ACTION_NONE;
+ xSemaphoreGive(mutex);
+ break;
+
+ case WIFI_EVENT_STA_CONNECTED:
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ wifi_state = WIFI_STATE_CONNECTED;
+ wifi_action = WIFI_ACTION_NONE;
+ wifi_connect_cnt = WIFI_MAX_CONNECT_ATTEMPTS;
+ xSemaphoreGive(mutex);
+ break;
+
+ case WIFI_EVENT_STA_DISCONNECTED:
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ if (wifi_connect_cnt) wifi_connect_cnt--;
+ _action = wifi_action;
+ _disconnect = (wifi_connect_cnt == 0);
+ if (_disconnect) wifi_state = WIFI_STATE_DISCONNECTED;
+ xSemaphoreGive(mutex);
+
+ if (_disconnect) {
+ rbuf = eos_net_alloc();
+ rbuf[0] = EOS_WIFI_MTYPE_DISCONNECT;
+ eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, 1);
+ if (!_action) ret = esp_wifi_stop();
+ } else {
+ ret = esp_wifi_connect();
+ }
+ break;
+
+ default: // Ignore the other event types
+ break;
+ }
+ } else if (event_base == IP_EVENT) {
+ switch(event_id) {
+ case IP_EVENT_STA_GOT_IP:
+ got_ip = (ip_event_got_ip_t *)event_data;
+ ESP_LOGI(TAG, "IP address: " IPSTR, IP2STR(&got_ip->ip_info.ip));
+ rbuf = eos_net_alloc();
+ rbuf[0] = EOS_WIFI_MTYPE_CONNECT;
+ rbuf[1] = EOS_OK;
+ eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, 2);
+
+ /* ip_changed is set even at normal connect!
+ if (got_ip->ip_changed) {
+ ESP_LOGI(TAG, "IP changed");
+ // send wifi reconnect
+ } else {
+ rbuf = eos_net_alloc();
+ rbuf[0] = EOS_WIFI_MTYPE_CONNECT;
+ rbuf[1] = EOS_OK;
+ eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, 2);
+ }
+ */
+ break;
+
+ default: // Ignore the other event types
+ break;
+ }
+ }
+
+ if (ret != ESP_OK) ESP_LOGE(TAG, "EVT HANDLER ERR:%d EVT:%d", ret, event_id);
+}
+
+static void wifi_handler(unsigned char _mtype, unsigned char *buffer, uint16_t size) {
+ uint8_t mtype;
+ int rv;
+ char *ssid, *pass;
+
+ if (size < 1) return;
+
+ mtype = buffer[0];
+ rv = EOS_OK;
+ buffer += 1;
+ size -= 1;
+
+ switch (mtype) {
+ case EOS_WIFI_MTYPE_SCAN:
+ rv = eos_wifi_scan();
+ break;
+
+ case EOS_WIFI_MTYPE_CONFIG:
+ ssid = (char *)buffer;
+ pass = ssid + strlen(ssid) + 1;
+ rv = eos_wifi_set_config(ssid, pass);
+ break;
+
+ case EOS_WIFI_MTYPE_CONNECT:
+ rv = eos_wifi_connect();
+ break;
+
+ case EOS_WIFI_MTYPE_DISCONNECT:
+ rv = eos_wifi_disconnect();
+ break;
+ }
+
+ if (rv) ESP_LOGE(TAG, "MSG HANDLER ERR:%d MSG:%d", rv, mtype);
+}
+
+void eos_wifi_init(void) {
+ esp_err_t ret;
+ wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT();
+
+ memset(&wifi_sta_config, 0, sizeof(wifi_sta_config));
+
+ esp_netif_create_default_wifi_sta();
+
+ ret = esp_wifi_init(&wifi_config);
+ assert(ret == ESP_OK);
+
+ ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL);
+ assert(ret == ESP_OK);
+
+ ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL);
+ assert(ret == ESP_OK);
+
+ ret = esp_wifi_set_storage(WIFI_STORAGE_RAM);
+ assert(ret == ESP_OK);
+
+ ret = esp_wifi_set_mode(WIFI_MODE_STA);
+ assert(ret == ESP_OK);
+
+ ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config);
+ assert(ret == ESP_OK);
+
+ ret = esp_wifi_stop();
+ assert(ret == ESP_OK);
+
+ mutex = xSemaphoreCreateBinary();
+ xSemaphoreGive(mutex);
+
+ eos_net_set_handler(EOS_NET_MTYPE_WIFI, wifi_handler);
+ ESP_LOGI(TAG, "INIT");
+}
+
+int eos_wifi_scan(void) {
+ int rv = EOS_OK;
+ esp_err_t ret = ESP_OK;
+ uint8_t _wifi_state = 0;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ if (!wifi_action) {
+ _wifi_state = wifi_state;
+
+ wifi_action = WIFI_ACTION_SCAN;
+ if (wifi_state == WIFI_STATE_STOPPED) wifi_state = WIFI_STATE_SCANNING;
+
+ memset(&wifi_scan_config, 0, sizeof(wifi_scan_config));
+ } else {
+ rv = EOS_ERR_BUSY;
+ }
+ xSemaphoreGive(mutex);
+
+ if (rv) return rv;
+
+ if (_wifi_state == WIFI_STATE_STOPPED) {
+ ret = esp_wifi_start();
+ } else {
+ ret = esp_wifi_scan_start(&wifi_scan_config, 0);
+ }
+ if (ret != ESP_OK) rv = EOS_ERR;
+
+ return rv;
+}
+
+int eos_wifi_set_config(char *ssid, char *pass) {
+ int rv = EOS_OK;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ if (!wifi_action) {
+ if (ssid) strncpy((char *)wifi_sta_config.sta.ssid, ssid, sizeof(wifi_sta_config.sta.ssid) - 1);
+ if (pass) strncpy((char *)wifi_sta_config.sta.password, pass, sizeof(wifi_sta_config.sta.password) - 1);
+ } else {
+ rv = EOS_ERR_BUSY;
+
+ }
+ xSemaphoreGive(mutex);
+
+ return rv;
+}
+
+int eos_wifi_connect(void) {
+ int rv = EOS_OK;
+ esp_err_t ret = ESP_OK;
+ uint8_t _wifi_state = 0;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ if (!wifi_action) {
+ _wifi_state = wifi_state;
+
+ wifi_action = WIFI_ACTION_CONNECT;
+ wifi_state = WIFI_STATE_CONNECTING;
+ wifi_connect_cnt = WIFI_MAX_CONNECT_ATTEMPTS;
+ } else {
+ rv = EOS_ERR_BUSY;
+ }
+ xSemaphoreGive(mutex);
+
+ if (rv) return rv;
+
+ esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config);
+
+ if (_wifi_state == WIFI_STATE_STOPPED) {
+ ret = esp_wifi_start();
+ } else {
+ ret = esp_wifi_connect();
+ }
+ if (ret != ESP_OK) rv = EOS_ERR;
+
+ return rv;
+}
+
+int eos_wifi_disconnect(void) {
+ int rv = EOS_OK;
+ esp_err_t ret = ESP_OK;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ if (!wifi_action) {
+ wifi_action = WIFI_ACTION_DISCONNECT;
+ wifi_state = WIFI_STATE_DISCONNECTING;
+ wifi_connect_cnt = 0;
+
+ memset(wifi_sta_config.sta.ssid, 0, sizeof(wifi_sta_config.sta.ssid));
+ memset(wifi_sta_config.sta.password, 0, sizeof(wifi_sta_config.sta.password));
+ } else {
+ rv = EOS_ERR_BUSY;
+ }
+ xSemaphoreGive(mutex);
+
+ if (rv) return rv;
+
+ ret = esp_wifi_stop();
+ if (ret != ESP_OK) rv = EOS_ERR;
+
+ return rv;
+}
+