8 changed files with 617 additions and 997 deletions
@ -1,292 +0,0 @@
|
||||
#include "https_client.h" |
||||
|
||||
static const char *TAG = "https_client"; |
||||
|
||||
static const char *REQUEST = "GET " CONFIG_OTA_HTTPS_URL " HTTP/1.1\r\n" |
||||
"Host: "CONFIG_OTA_HTTPS_SERVER_COMMON_NAME"\r\n" |
||||
"User-Agent: esp-idf/1.0 esp32\r\n" |
||||
"Authorization: Basic " CONFIG_OTA_HTTPS_AUTH "\r\n" |
||||
"\r\n"; |
||||
|
||||
|
||||
static HTTPS_Client_t sHTTPS_ClientConfig; |
||||
|
||||
https_client_ret_t https_clientInitEmbedTLS(); |
||||
https_client_ret_t https_clientConnectToServer(); |
||||
https_client_ret_t https_clientValidateServer(); |
||||
https_client_ret_t https_clientSendRequest(); |
||||
|
||||
https_client_ret_t https_clientInitialize() |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
|
||||
i32RetHTTPClient = https_clientInitEmbedTLS(); |
||||
|
||||
if(i32RetHTTPClient == HTTPS_CLIENT_OK) |
||||
{ |
||||
i32RetHTTPClient = https_clientConnectToServer(); |
||||
} |
||||
|
||||
if(i32RetHTTPClient == HTTPS_CLIENT_OK) |
||||
{ |
||||
i32RetHTTPClient = https_clientValidateServer(); |
||||
} |
||||
|
||||
if(i32RetHTTPClient == HTTPS_CLIENT_OK) |
||||
{ |
||||
i32RetHTTPClient = https_clientSendRequest(); |
||||
} |
||||
|
||||
switch (i32RetHTTPClient) |
||||
{ |
||||
case HTTPS_CLIENT_ERROR_INIT_EMBEDTLS: |
||||
ESP_LOGE(TAG, "Unable to initialize EmbedTLS"); |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
break; |
||||
case HTTPS_CLIENT_ERROR_INIT_CONNECT_TWO_SERVER: |
||||
ESP_LOGE(TAG, "Unable to connect to server"); |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
break; |
||||
case HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER: |
||||
ESP_LOGE(TAG, "Unable to validate the server"); |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
break; |
||||
case HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST: |
||||
ESP_LOGE(TAG, "Unable to send request to server"); |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
break; |
||||
case HTTPS_CLIENT_OK: |
||||
ESP_LOGI(TAG, "HTTPS Client successfully initialized"); |
||||
i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
break; |
||||
default: |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
ESP_LOGE(TAG, "Unknown error while init https client"); |
||||
break; |
||||
} |
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32BytesRead) |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
int32_t i32RetRetrieveData = ESP_OK; |
||||
bool bRetriveData = true; |
||||
|
||||
bzero(pu8Data, *pu32DataLenght); |
||||
*pu32BytesRead = 0U; |
||||
|
||||
while (bRetriveData) |
||||
{ |
||||
//Reading HTTP response
|
||||
i32RetRetrieveData = mbedtls_ssl_read(&sHTTPS_ClientConfig.ssl, (unsigned char *)(pu8Data+(*pu32BytesRead)), ((*pu32DataLenght)-(*pu32BytesRead))); |
||||
|
||||
if(i32RetRetrieveData > 0) |
||||
{ |
||||
//Data received
|
||||
*pu32BytesRead = *pu32BytesRead + i32RetRetrieveData; |
||||
|
||||
if(*pu32DataLenght > 0) |
||||
{ |
||||
//buffer not full yet --> read some more
|
||||
bRetriveData = true; |
||||
} |
||||
else |
||||
{ |
||||
//buffer full --> stop reading
|
||||
bRetriveData = false; |
||||
} |
||||
} |
||||
|
||||
if(i32RetRetrieveData == 0) |
||||
{ |
||||
//all data read --> stop reading
|
||||
bRetriveData = false; |
||||
pu32BytesRead = 0; |
||||
} |
||||
|
||||
if(i32RetRetrieveData == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) |
||||
{ |
||||
//connection is going to be closed
|
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR; |
||||
bRetriveData = false; |
||||
} |
||||
} |
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientDeinitialize() |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
|
||||
i32RetHTTPClient = mbedtls_ssl_close_notify(&sHTTPS_ClientConfig.ssl); //close session
|
||||
|
||||
if(i32RetHTTPClient != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ssl_close_notify returned 0x%x", i32RetHTTPClient); |
||||
} |
||||
|
||||
mbedtls_ssl_session_reset(&sHTTPS_ClientConfig.ssl); //reset embedssl
|
||||
mbedtls_net_free(&sHTTPS_ClientConfig.server_fd); //free ram
|
||||
|
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientInitEmbedTLS() { |
||||
|
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
int32_t i32RetEmbedTLS = ESP_OK; |
||||
|
||||
mbedtls_ssl_init(&sHTTPS_ClientConfig.ssl); |
||||
mbedtls_x509_crt_init(&sHTTPS_ClientConfig.cacert); |
||||
mbedtls_ctr_drbg_init(&sHTTPS_ClientConfig.ctr_drbg); |
||||
mbedtls_ssl_config_init(&sHTTPS_ClientConfig.conf); |
||||
mbedtls_entropy_init(&sHTTPS_ClientConfig.entropy); |
||||
|
||||
i32RetEmbedTLS = mbedtls_ctr_drbg_seed(&sHTTPS_ClientConfig.ctr_drbg, mbedtls_entropy_func, &sHTTPS_ClientConfig.entropy, NULL, 0); |
||||
|
||||
if(i32RetEmbedTLS!= ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", i32RetEmbedTLS); |
||||
} |
||||
|
||||
if(i32RetEmbedTLS == ESP_OK) |
||||
{ |
||||
//Attaching the certificate bundle
|
||||
i32RetEmbedTLS = esp_crt_bundle_attach(&sHTTPS_ClientConfig.conf); |
||||
if(i32RetEmbedTLS != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "esp_crt_bundle_attach returned 0x%x\n\n", i32RetEmbedTLS); |
||||
} |
||||
} |
||||
|
||||
if(i32RetEmbedTLS == ESP_OK) |
||||
{ |
||||
//Setting hostname for TLS session.
|
||||
i32RetEmbedTLS = mbedtls_ssl_set_hostname(&sHTTPS_ClientConfig.ssl, CONFIG_OTA_HTTPS_SERVER_COMMON_NAME); |
||||
// Hostname set here should match CN in server certificate
|
||||
if(i32RetEmbedTLS != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned 0x%x", i32RetEmbedTLS); |
||||
} |
||||
} |
||||
if(i32RetEmbedTLS == ESP_OK) |
||||
{ |
||||
//Setting up the SSL/TLS structure
|
||||
i32RetEmbedTLS = mbedtls_ssl_config_defaults(&sHTTPS_ClientConfig.conf, |
||||
MBEDTLS_SSL_IS_CLIENT, |
||||
MBEDTLS_SSL_TRANSPORT_STREAM, |
||||
MBEDTLS_SSL_PRESET_DEFAULT); |
||||
|
||||
if(i32RetEmbedTLS != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", i32RetEmbedTLS); |
||||
} |
||||
} |
||||
|
||||
if(i32RetEmbedTLS == ESP_OK) |
||||
{ |
||||
mbedtls_ssl_conf_authmode(&sHTTPS_ClientConfig.conf, MBEDTLS_SSL_VERIFY_REQUIRED); |
||||
mbedtls_ssl_conf_ca_chain(&sHTTPS_ClientConfig.conf, &sHTTPS_ClientConfig.cacert, NULL); |
||||
mbedtls_ssl_conf_rng(&sHTTPS_ClientConfig.conf, mbedtls_ctr_drbg_random, &sHTTPS_ClientConfig.ctr_drbg); |
||||
|
||||
i32RetEmbedTLS = mbedtls_ssl_setup(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.conf); |
||||
if(i32RetEmbedTLS != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", i32RetEmbedTLS); |
||||
} |
||||
} |
||||
|
||||
if(i32RetEmbedTLS == ESP_OK) |
||||
{ |
||||
mbedtls_net_init(&sHTTPS_ClientConfig.server_fd); |
||||
} |
||||
|
||||
if (i32RetEmbedTLS != ESP_OK) |
||||
{ |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR_INIT_EMBEDTLS; |
||||
} |
||||
|
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientConnectToServer() |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
int32_t i32RetServerConnect = ESP_OK; |
||||
|
||||
//Connecting to server
|
||||
i32RetServerConnect = mbedtls_net_connect(&sHTTPS_ClientConfig.server_fd, CONFIG_OTA_HTTPS_SERVER_COMMON_NAME, CONFIG_OTA_HTTPS_SERVER_PORT, MBEDTLS_NET_PROTO_TCP); |
||||
if (i32RetServerConnect != ESP_OK) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_net_connect returned %x", i32RetServerConnect); |
||||
} |
||||
|
||||
if(i32RetServerConnect == ESP_OK) |
||||
{ |
||||
mbedtls_ssl_set_bio(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); |
||||
|
||||
//Performing the SSL/TLS handshake
|
||||
while ((i32RetServerConnect = mbedtls_ssl_handshake(&sHTTPS_ClientConfig.ssl)) != 0) |
||||
{ |
||||
if ((i32RetServerConnect != MBEDTLS_ERR_SSL_WANT_READ) && (i32RetServerConnect != MBEDTLS_ERR_SSL_WANT_WRITE)) |
||||
{ |
||||
ESP_LOGE(TAG, "mbedtls_ssl_handshake returned 0x%x", i32RetServerConnect); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if(i32RetServerConnect != ESP_OK) |
||||
{ |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR_INIT_CONNECT_TWO_SERVER; |
||||
} |
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientValidateServer() |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
int32_t i32RetValidateServer = ESP_OK; |
||||
|
||||
//Verifying peer X.509 certificate
|
||||
if ((i32RetValidateServer = mbedtls_ssl_get_verify_result(&sHTTPS_ClientConfig.ssl)) != 0) |
||||
{ |
||||
ESP_LOGE(TAG, "Failed to verify peer certificate!"); |
||||
} |
||||
|
||||
if(i32RetValidateServer != ESP_OK) |
||||
{ |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER; |
||||
} |
||||
return i32RetHTTPClient; |
||||
} |
||||
|
||||
https_client_ret_t https_clientSendRequest() |
||||
{ |
||||
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; |
||||
int32_t i32RetSendRequest = ESP_OK; |
||||
uint32_t u32WrittenBytes = 0; |
||||
bool bWrite = true; //flag to stop loop
|
||||
|
||||
//Writing HTTP request
|
||||
while((u32WrittenBytes < strlen(REQUEST)) && bWrite) |
||||
{ |
||||
i32RetSendRequest = mbedtls_ssl_write(&sHTTPS_ClientConfig.ssl, |
||||
(const unsigned char *)REQUEST + u32WrittenBytes, |
||||
strlen(REQUEST) - u32WrittenBytes); |
||||
if (i32RetSendRequest >= 0) |
||||
{ |
||||
//bytes written
|
||||
u32WrittenBytes += i32RetSendRequest; |
||||
} else if (i32RetSendRequest != MBEDTLS_ERR_SSL_WANT_WRITE && i32RetSendRequest != MBEDTLS_ERR_SSL_WANT_READ) { |
||||
ESP_LOGE(TAG, "mbedtls_ssl_write returned 0x%x", i32RetSendRequest); |
||||
bWrite = false; |
||||
} |
||||
} |
||||
|
||||
if(bWrite == false) |
||||
{ |
||||
i32RetHTTPClient = HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST; |
||||
} |
||||
return i32RetHTTPClient; |
||||
} |
@ -1,75 +0,0 @@
|
||||
#ifndef H_HTTPS_CLIENT |
||||
#define H_HTTPS_CLIENT |
||||
|
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include "freertos/FreeRTOS.h" |
||||
#include "freertos/task.h" |
||||
#include "esp_wifi.h" |
||||
#include "esp_event.h" |
||||
#include "esp_log.h" |
||||
#include "esp_system.h" |
||||
#include "nvs_flash.h" |
||||
#include "esp_netif.h" |
||||
|
||||
#include "lwip/err.h" |
||||
#include "lwip/sockets.h" |
||||
#include "lwip/sys.h" |
||||
#include "lwip/netdb.h" |
||||
#include "lwip/dns.h" |
||||
|
||||
#include "mbedtls/platform.h" |
||||
#include "mbedtls/net_sockets.h" |
||||
#include "mbedtls/esp_debug.h" |
||||
#include "mbedtls/ssl.h" |
||||
#include "mbedtls/entropy.h" |
||||
#include "mbedtls/ctr_drbg.h" |
||||
#include "mbedtls/error.h" |
||||
#include "mbedtls/certs.h" |
||||
#include "esp_crt_bundle.h" |
||||
|
||||
#ifndef CONFIG_OTA_HTTPS_URL |
||||
#define CONFIG_OTA_HTTPS_URL "https://exmaple.com/theImage.bin"
|
||||
#endif |
||||
|
||||
#ifndef CONFIG_OTA_HTTPS_SERVER_PORT |
||||
#define CONFIG_OTA_HTTPS_SERVER_PORT "443" |
||||
#endif |
||||
|
||||
#ifndef CONFIG_OTA_HTTPS_AUTH |
||||
#define CONFIG_OTA_HTTPS_AUTH "base64(user:password)" |
||||
#endif |
||||
|
||||
#ifndef CONFIG_OTA_HTTPS_SERVER_COMMON_NAME |
||||
#define CONFIG_OTA_HTTPS_SERVER_COMMON_NAME "exmaple.com" |
||||
#endif |
||||
|
||||
#define HTTPS_CLIENT_OK 0 |
||||
#define HTTPS_CLIENT_ERROR -1 |
||||
#define HTTPS_CLIENT_ERROR_INIT_EMBEDTLS -2 |
||||
#define HTTPS_CLIENT_ERROR_INIT_CONNECT_TWO_SERVER -3 |
||||
#define HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER -4 |
||||
#define HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST -5 |
||||
|
||||
struct HTTPS_Client |
||||
{ |
||||
mbedtls_entropy_context entropy; |
||||
mbedtls_ctr_drbg_context ctr_drbg; |
||||
mbedtls_ssl_context ssl; |
||||
mbedtls_x509_crt cacert; |
||||
mbedtls_ssl_config conf; |
||||
mbedtls_net_context server_fd; |
||||
}; |
||||
|
||||
typedef int32_t https_client_ret_t; |
||||
typedef struct HTTPS_Client HTTPS_Client_t; |
||||
|
||||
https_client_ret_t https_clientInitialize(); |
||||
https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32BytesRead); |
||||
https_client_ret_t https_clientDeinitialize(); |
||||
|
||||
#endif /* H_HTTPS_CLIENT */ |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
#ifndef H_MESH_NETWORK |
||||
#define H_MESH_NETWORK |
||||
|
||||
#include <string.h> |
||||
#include "esp_wifi.h" |
||||
#include "esp_system.h" |
||||
#include "esp_event.h" |
||||
#include "esp_log.h" |
||||
#include "esp_mesh.h" |
||||
#include "esp_mesh_internal.h" |
||||
|
||||
|
||||
#define RX_SIZE (1234) |
||||
#define TX_SIZE (1234) |
||||
|
||||
esp_err_t errMeshNetworkInitialize(); |
||||
esp_err_t errMeshNetworkInitializeWiFi(); |
||||
esp_err_t errMeshNetworkInitializeRouter(mesh_cfg_t* cfg); |
||||
|
||||
|
||||
bool bCheckMACEquality(uint8_t* pu8aMAC, uint8_t* pu8bMAC); |
||||
esp_err_t errGetChildren(mesh_addr_t children[], uint16_t* pu16ChildrenSize); |
||||
esp_err_t errSendPacket(mesh_addr_t* dest, struct ota_mesh_packet* packet); |
||||
void vMeshEventHandler(void *arg, esp_event_base_t event_base, int32_t i32EventID, void* vpEventData); |
||||
void vIPEventHandler(void *arg, esp_event_base_t event_base, int32_t i32EventID, void *event_data); |
||||
|
||||
#endif /* H_MESH_NETWORK */ |
||||
|
@ -0,0 +1,444 @@
|
||||
|
||||
#include "mesh_ota.h" |
||||
|
||||
static const char *LOG_TAG = "mesh_network"; |
||||
static const uint8_t MESH_ID[6] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77}; |
||||
static uint8_t tx_buf[TX_SIZE] = { 0, }; |
||||
static uint8_t rx_buf[RX_SIZE] = { 0, }; |
||||
static bool is_mesh_connected = false; |
||||
static mesh_addr_t mesh_parent_addr; |
||||
|
||||
static int mesh_layer = -1; |
||||
static esp_netif_t *netif_sta = NULL; |
||||
|
||||
uint8_t ownMAC[6]; |
||||
|
||||
|
||||
esp_err_t errMeshNetworkInitialize() |
||||
{ |
||||
esp_err_t err; |
||||
|
||||
err = nvs_flash_init(); //init non-volatile storage
|
||||
|
||||
#ifdef ERASE_NVS |
||||
if(err == ESP_ERR_NVS_NO_FREE_PAGES) //check if storage is full
|
||||
{ |
||||
ERROR_CHECK(nvs_flash_erase()); |
||||
} |
||||
#endif |
||||
|
||||
// tcpip initialization
|
||||
ERROR_CHECK(esp_netif_init()); |
||||
|
||||
//event initialization
|
||||
ERROR_CHECK(esp_event_loop_create_default()); |
||||
|
||||
//create network interfaces for mesh (only station instance saved for further manipulation, soft AP instance ignored
|
||||
ERROR_CHECK(esp_netif_create_default_wifi_mesh_netifs(&netif_sta, NULL)); |
||||
|
||||
//wifi initialization
|
||||
ERROR_CHECK(errMeshNetworkInitializeWiFi()); |
||||
|
||||
//mesh initialization
|
||||
ERROR_CHECK(esp_mesh_init()); |
||||
|
||||
//mesh initialization
|
||||
ERROR_CHECK(esp_event_handler_register(MESH_EVENT, ESP_EVENT_ANY_ID, &vMeshEventHandler, NULL)); |
||||
|
||||
//set mesh topology
|
||||
ERROR_CHECK(esp_mesh_set_topology(CONFIG_MESH_TOPOLOGY)); |
||||
|
||||
//set mesh max layer according to the topology
|
||||
ERROR_CHECK(esp_mesh_set_max_layer(CONFIG_MESH_MAX_LAYER)); |
||||
ERROR_CHECK(esp_mesh_set_vote_percentage(1)); |
||||
ERROR_CHECK(esp_mesh_set_xon_qsize(128)); |
||||
|
||||
//Disable mesh PS function
|
||||
ERROR_CHECK(esp_mesh_disable_ps()); |
||||
ERROR_CHECK(esp_mesh_set_ap_assoc_expire(10)); |
||||
|
||||
mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT(); |
||||
|
||||
/* mesh ID */ |
||||
memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6); |
||||
|
||||
ERROR_CHECK(errMeshNetworkInitializeRouter(&cfg)); |
||||
|
||||
/* mesh softAP */ |
||||
ERROR_CHECK(esp_mesh_set_ap_authmode(CONFIG_MESH_AP_AUTHMODE)); |
||||
cfg.mesh_ap.max_connection = CONFIG_MESH_AP_CONNECTIONS; |
||||
memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD, |
||||
strlen(CONFIG_MESH_AP_PASSWD)); |
||||
ERROR_CHECK(esp_mesh_set_config(&cfg)); |
||||
|
||||
/* mesh start */ |
||||
ERROR_CHECK(esp_mesh_start()); |
||||
|
||||
ERROR_CHECK(esp_base_mac_addr_get(ownMAC)) |
||||
|
||||
//debug info
|
||||
ESP_LOGD(LOG_TAG, "mesh starts successfully, heap:%d, %s<%d>%s, ps:%d\n", esp_get_minimum_free_heap_size(), |
||||
esp_mesh_is_root_fixed() ? "root fixed" : "root not fixed", |
||||
esp_mesh_get_topology(), esp_mesh_get_topology() ? "(chain)":"(tree)", esp_mesh_is_ps_enabled()); |
||||
|
||||
|
||||
ESP_LOGI(LOG_TAG, "Node MAC: \"%x:%x:%x:%x:%x:%x\" ", ownMAC[0], ownMAC[1], ownMAC[2], ownMAC[3], ownMAC[4], ownMAC[5]); |
||||
|
||||
return ESP_OK; |
||||
} |
||||
|
||||
esp_err_t errMeshNetworkInitializeWiFi() |
||||
{ |
||||
//wifi initialization
|
||||
esp_err_t err = ESP_OK; |
||||
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); |
||||
ERROR_CHECK(esp_wifi_init(&config)); |
||||
ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &vIPEventHandler, NULL)); |
||||
ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); |
||||
ERROR_CHECK(esp_wifi_start()); |
||||
return err; |
||||
|
||||
} |
||||
|
||||
esp_err_t errMeshNetworkInitializeRouter(mesh_cfg_t* cfg) |
||||
{ |
||||
//router initialization
|
||||
esp_err_t err = ESP_OK; |
||||
(*cfg).channel = CONFIG_MESH_CHANNEL; |
||||
(*cfg).router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID); |
||||
memcpy((uint8_t *) &(*cfg).router.ssid, CONFIG_MESH_ROUTER_SSID, (*cfg).router.ssid_len); |
||||
memcpy((uint8_t *) &(*cfg).router.password, CONFIG_MESH_ROUTER_PASSWD, |
||||
strlen(CONFIG_MESH_ROUTER_PASSWD)); |
||||
return err; |
||||
} |
||||
|
||||
//returns true if MAC address is equal
|
||||
bool bCheckMACEquality(uint8_t* pu8aMAC, uint8_t* pu8bMAC) |
||||
{ |
||||
bool bRet = true; |
||||
uint8_t index = 0; |
||||
|
||||
while ((index < 6) && (bRet == true)) |
||||
{ |
||||
if(pu8aMAC[index] != pu8bMAC[index]) |
||||
{ |
||||
bRet = false; |
||||
} |
||||
index++; |
||||
} |
||||
return bRet; |
||||
} |
||||
|
||||
esp_err_t errGetChildren(mesh_addr_t children[], uint16_t* pu16ChildrenSize) |
||||
{ |
||||
esp_err_t err = ESP_OK; |
||||
int route_table_size = 0; |
||||
*pu16ChildrenSize = 0; |
||||
mesh_addr_t route_table[CONFIG_MESH_ROUTE_TABLE_SIZE]; |
||||
ERROR_CHECK(esp_mesh_get_routing_table((mesh_addr_t *) &route_table, (CONFIG_MESH_ROUTE_TABLE_SIZE * 6), &route_table_size)); |
||||
|
||||
if (err == ESP_OK) |
||||
{ |
||||
for(uint16_t index = 0; index < esp_mesh_get_routing_table_size(); index++) |
||||
{ |
||||
if(! (bCheckMACEquality(ownMAC, route_table[index].addr)) ) |
||||
{ |
||||
//child node
|
||||
//ESP_LOGI(MESH_TAG, "adding Node: \"0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\" ", route_table[index].addr[0], route_table[index].addr[1], route_table[index].addr[2], route_table[index].addr[3], route_table[index].addr[4], route_table[index].addr[5]);
|
||||
children[*pu16ChildrenSize] = route_table[index]; |
||||
*pu16ChildrenSize = (*pu16ChildrenSize)+1; |
||||
} |
||||
} |
||||
} |
||||
return err; |
||||
} |
||||
|
||||
/*
|
||||
esp_err_t errSendPacket(mesh_addr_t* dest, struct ota_mesh_packet* packet) |
||||
{ |
||||
esp_err_t err; |
||||
mesh_data_t data; |
||||
data.data = tx_buf; |
||||
data.size = sizeof(tx_buf); |
||||
data.proto = MESH_PROTO_BIN; |
||||
data.tos = MESH_TOS_P2P; |
||||
memcpy(tx_buf, (uint8_t *)packet, sizeof(struct ota_mesh_packet)); |
||||
err = esp_mesh_send(dest, &data, MESH_DATA_P2P, NULL, 0); |
||||
return err; |
||||
} |
||||
*/ |
||||
|
||||
void esp_mesh_p2p_rx_main(void *arg) |
||||
{ |
||||
esp_err_t err; |
||||
mesh_addr_t from; |
||||
mesh_data_t data; |
||||
int flag = 0; |
||||
data.data = rx_buf; |
||||
data.size = RX_SIZE; |
||||
|
||||
while (true) |
||||
{ |
||||
data.size = RX_SIZE; |
||||
err = esp_mesh_recv(&from, &data, portMAX_DELAY, &flag, NULL, 0); |
||||
if (err != ESP_OK || !data.size) |
||||
{ |
||||
ESP_LOGE(LOG_TAG, "err:0x%x, size:%d", err, data.size); |
||||
continue; |
||||
} |
||||
|
||||
struct ota_mesh_packet packet; |
||||
memcpy(&packet, (uint8_t *)rx_buf, sizeof(struct ota_mesh_packet)); |
||||
|
||||
switch (packet.type) |
||||
{ |
||||
case APP_Version_Request: |
||||
ESP_LOGI(LOG_TAG, "recv: APP_Version_Request"); |
||||
packet.type=APP_Version_Response; |
||||
packet.au8Payload[0] = 42; //TODO get current running version
|
||||
// ESP_ERROR_CHECK (esp_mesh_send_packet(&from, &packet)); //send back to parent
|
||||
break; |
||||
case APP_Version_Response: |
||||
ESP_LOGI(LOG_TAG, "recv: APP_Version_Response - App Version %i: ", packet.au8Payload[0]); |
||||
//check if node is out-dated
|
||||
// esp_mesh_ota_send(&from);
|
||||
break; |
||||
case OTA_Data: |
||||
ESP_LOGI(LOG_TAG, "recv: OTA_Data"); |
||||
//esp_mesh_ota_receive(&from, &packet);
|
||||
packet.type=OTA_ACK; |
||||
//ESP_ERROR_CHECK (esp_mesh_send_packet(&from, &packet)); //send back to parent
|
||||
break; |
||||
case OTA_ACK: |
||||
ESP_LOGI(LOG_TAG, "recv: OTA_ACK"); |
||||
//esp_mesh_ota_send(&from);
|
||||
break; |
||||
case OTA_Complete: |
||||
ESP_LOGI(LOG_TAG, "recv: OTA_Complete"); |
||||
break; |
||||
default: |
||||
ESP_LOGE(LOG_TAG, "recv: something"); |
||||
break; |
||||
} |
||||
|
||||
} //end while
|
||||
vTaskDelete(NULL); |
||||
} |
||||
|
||||
|
||||
esp_err_t esp_mesh_comm_p2p_start(void) |
||||
{ |
||||
static bool is_comm_p2p_started = false; |
||||
if (!is_comm_p2p_started) |
||||
{ |
||||
is_comm_p2p_started = true; |
||||
xTaskCreate(esp_mesh_p2p_rx_main, "MPRX", 7000, NULL, 5, NULL); |
||||
} |
||||
return ESP_OK; |
||||
} |
||||
|
||||
void vMeshEventHandler(void *arg, esp_event_base_t event_base, int32_t i32EventID, void* vpEventData) |
||||
{ |
||||
mesh_addr_t id = {0,}; |
||||
static uint16_t last_layer = 0; |
||||
|
||||
switch (i32EventID) |
||||
{ |
||||
case MESH_EVENT_STARTED: |
||||
{ |
||||
esp_mesh_get_id(&id); |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_MESH_STARTED>ID:"MACSTR"", MAC2STR(id.addr)); |
||||
is_mesh_connected = false; |
||||
mesh_layer = esp_mesh_get_layer(); |
||||
} |
||||
break; |
||||
case MESH_EVENT_STOPPED: { |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_STOPPED>"); |
||||
is_mesh_connected = false; |
||||
mesh_layer = esp_mesh_get_layer(); |
||||
} |
||||
break; |
||||
case MESH_EVENT_CHILD_CONNECTED: { |
||||
mesh_event_child_connected_t *child_connected = (mesh_event_child_connected_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_CHILD_CONNECTED>aid:%d, "MACSTR"", |
||||
child_connected->aid, |
||||
MAC2STR(child_connected->mac)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_CHILD_DISCONNECTED: { |
||||
mesh_event_child_disconnected_t *child_disconnected = (mesh_event_child_disconnected_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_CHILD_DISCONNECTED>aid:%d, "MACSTR"", |
||||
child_disconnected->aid, |
||||
MAC2STR(child_disconnected->mac)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROUTING_TABLE_ADD: { |
||||
mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)vpEventData; |
||||
ESP_LOGW(LOG_TAG, "<MESH_EVENT_ROUTING_TABLE_ADD>add %d, new:%d, layer:%d", |
||||
routing_table->rt_size_change, |
||||
routing_table->rt_size_new, mesh_layer); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROUTING_TABLE_REMOVE: { |
||||
mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)vpEventData; |
||||
ESP_LOGW(LOG_TAG, "<MESH_EVENT_ROUTING_TABLE_REMOVE>remove %d, new:%d, layer:%d", |
||||
routing_table->rt_size_change, |
||||
routing_table->rt_size_new, mesh_layer); |
||||
} |
||||
break; |
||||
case MESH_EVENT_NO_PARENT_FOUND: { |
||||
mesh_event_no_parent_found_t *no_parent = (mesh_event_no_parent_found_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_NO_PARENT_FOUND>scan times:%d", |
||||
no_parent->scan_times); |
||||
} |
||||
/* TODO handler for the failure */ |
||||
break; |
||||
case MESH_EVENT_PARENT_CONNECTED: { |
||||
mesh_event_connected_t *connected = (mesh_event_connected_t *)vpEventData; |
||||
esp_mesh_get_id(&id); |
||||
mesh_layer = connected->self_layer; |
||||
memcpy(&mesh_parent_addr.addr, connected->connected.bssid, 6); |
||||
ESP_LOGI(LOG_TAG, |
||||
"<MESH_EVENT_PARENT_CONNECTED>layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR", duty:%d", |
||||
last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr), |
||||
esp_mesh_is_root() ? "<ROOT>" : |
||||
(mesh_layer == 2) ? "<layer2>" : "", MAC2STR(id.addr), connected->duty); |
||||
last_layer = mesh_layer; |
||||
// mesh_connected_indicator(mesh_layer);
|
||||
is_mesh_connected = true; |
||||
if (esp_mesh_is_root()) { |
||||
esp_netif_dhcpc_start(netif_sta); |
||||
} |
||||
esp_mesh_comm_p2p_start();//start receiving
|
||||
} |
||||
break; |
||||
case MESH_EVENT_PARENT_DISCONNECTED: { |
||||
mesh_event_disconnected_t *disconnected = (mesh_event_disconnected_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, |
||||
"<MESH_EVENT_PARENT_DISCONNECTED>reason:%d", |
||||
disconnected->reason); |
||||
is_mesh_connected = false; |
||||
// mesh_disconnected_indicator();
|
||||
mesh_layer = esp_mesh_get_layer(); |
||||
} |
||||
break; |
||||
case MESH_EVENT_LAYER_CHANGE: { |
||||
mesh_event_layer_change_t *layer_change = (mesh_event_layer_change_t *)vpEventData; |
||||
mesh_layer = layer_change->new_layer; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_LAYER_CHANGE>layer:%d-->%d%s", |
||||
last_layer, mesh_layer, |
||||
esp_mesh_is_root() ? "<ROOT>" : |
||||
(mesh_layer == 2) ? "<layer2>" : ""); |
||||
last_layer = mesh_layer; |
||||
// mesh_connected_indicator(mesh_layer);
|
||||
} |
||||
break; |
||||
case MESH_EVENT_ROOT_ADDRESS: { |
||||
mesh_event_root_address_t *root_addr = (mesh_event_root_address_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_ROOT_ADDRESS>root address:"MACSTR"", |
||||
MAC2STR(root_addr->addr)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_VOTE_STARTED: { |
||||
mesh_event_vote_started_t *vote_started = (mesh_event_vote_started_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, |
||||
"<MESH_EVENT_VOTE_STARTED>attempts:%d, reason:%d, rc_addr:"MACSTR"", |
||||
vote_started->attempts, |
||||
vote_started->reason, |
||||
MAC2STR(vote_started->rc_addr.addr)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_VOTE_STOPPED: { |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_VOTE_STOPPED>"); |
||||
break; |
||||
} |
||||
case MESH_EVENT_ROOT_SWITCH_REQ: { |
||||
mesh_event_root_switch_req_t *switch_req = (mesh_event_root_switch_req_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, |
||||
"<MESH_EVENT_ROOT_SWITCH_REQ>reason:%d, rc_addr:"MACSTR"", |
||||
switch_req->reason, |
||||
MAC2STR( switch_req->rc_addr.addr)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROOT_SWITCH_ACK: { |
||||
/* new root */ |
||||
mesh_layer = esp_mesh_get_layer(); |
||||
esp_mesh_get_parent_bssid(&mesh_parent_addr); |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_ROOT_SWITCH_ACK>layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_TODS_STATE: { |
||||
mesh_event_toDS_state_t *toDs_state = (mesh_event_toDS_state_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_TODS_REACHABLE>state:%d", *toDs_state); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROOT_FIXED: { |
||||
mesh_event_root_fixed_t *root_fixed = (mesh_event_root_fixed_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_ROOT_FIXED>%s", |
||||
root_fixed->is_fixed ? "fixed" : "not fixed"); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROOT_ASKED_YIELD: { |
||||
mesh_event_root_conflict_t *root_conflict = (mesh_event_root_conflict_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, |
||||
"<MESH_EVENT_ROOT_ASKED_YIELD>"MACSTR", rssi:%d, capacity:%d", |
||||
MAC2STR(root_conflict->addr), |
||||
root_conflict->rssi, |
||||
root_conflict->capacity); |
||||
} |
||||
break; |
||||
case MESH_EVENT_CHANNEL_SWITCH: { |
||||
mesh_event_channel_switch_t *channel_switch = (mesh_event_channel_switch_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_CHANNEL_SWITCH>new channel:%d", channel_switch->channel); |
||||
} |
||||
break; |
||||
case MESH_EVENT_SCAN_DONE: { |
||||
mesh_event_scan_done_t *scan_done = (mesh_event_scan_done_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_SCAN_DONE>number:%d", |
||||
scan_done->number); |
||||
} |
||||
break; |
||||
case MESH_EVENT_NETWORK_STATE: { |
||||
mesh_event_network_state_t *network_state = (mesh_event_network_state_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_NETWORK_STATE>is_rootless:%d", |
||||
network_state->is_rootless); |
||||
} |
||||
break; |
||||
case MESH_EVENT_STOP_RECONNECTION: { |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_STOP_RECONNECTION>"); |
||||
} |
||||
break; |
||||
case MESH_EVENT_FIND_NETWORK: { |
||||
mesh_event_find_network_t *find_network = (mesh_event_find_network_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_FIND_NETWORK>new channel:%d, router BSSID:"MACSTR"", |
||||
find_network->channel, MAC2STR(find_network->router_bssid)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_ROUTER_SWITCH: { |
||||
mesh_event_router_switch_t *router_switch = (mesh_event_router_switch_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_ROUTER_SWITCH>new router:%s, channel:%d, "MACSTR"", |
||||
router_switch->ssid, router_switch->channel, MAC2STR(router_switch->bssid)); |
||||
} |
||||
break; |
||||
case MESH_EVENT_PS_PARENT_DUTY: { |
||||
mesh_event_ps_duty_t *ps_duty = (mesh_event_ps_duty_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_PS_PARENT_DUTY>duty:%d", ps_duty->duty); |
||||
} |
||||
break; |
||||
case MESH_EVENT_PS_CHILD_DUTY: { |
||||
mesh_event_ps_duty_t *ps_duty = (mesh_event_ps_duty_t *)vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<MESH_EVENT_PS_CHILD_DUTY>cidx:%d, "MACSTR", duty:%d", ps_duty->child_connected.aid-1, |
||||
MAC2STR(ps_duty->child_connected.mac), ps_duty->duty); |
||||
} |
||||
break; |
||||
default: |
||||
ESP_LOGI(LOG_TAG, "unknown id:%d", i32EventID); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void vIPEventHandler(void *arg, esp_event_base_t event_base, int32_t i32EventID, void *vpEventData) |
||||
{ |
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) vpEventData; |
||||
ESP_LOGI(LOG_TAG, "<IP_EVENT_STA_GOT_IP>IP:" IPSTR, IP2STR(&event->ip_info.ip)); |
||||
} |