basic framework

master
Jan Umbach 2023-08-14 00:04:58 +02:00
parent c97fd6a080
commit 75fb079e46
31 changed files with 1525 additions and 59 deletions

0
-s Normal file
View File

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
script.sh

346
22222publish_firmware.sh Normal file
View File

@ -0,0 +1,346 @@
#!/bin/bash
#BASEDIR=$(dirname "$0")
#cd "$BASEDIR"
# Set the IDF_PATH environment variable to point to the ESP-IDF installation
export IDF_PATH=~/esp/esp-idf
version_file="version.txt"
initial_version="1.0"
initProject="false"
firmware_server_path="./firmwareserver"
# Function to translate text using translate-shell
translate() {
text="$1"
lang="$2"
translation=$(trans -b :"$lang" "$text")
echo "$translation"
}
# check if backup file exists and restore it
if [ -f "$version_file.backup" ]; then
mv "$version_file.backup" "$version_file"
fi
# Check if version file exists
if [ -f "$version_file" ]; then
current_version=$(cat "$version_file")
else
echo ""
echo ""
read -p "Version file not found. Create version.txt with initial version $initial_version? (y/n) " create_new
if [ "$create_new" = "y" ]; then
echo "$initial_version" >"$version_file"
current_version="$initial_version"
initProject="true"
else
echo "Cancelling script."
exit 0
fi
fi
# check if project is initialized
if [ "$initProject" = "true" ]; then
echo ""
echo "###############################################"
echo ""
echo "Project initialized with version $initial_version"
echo ""
echo "###############################################"
echo ""
else
# create backup file from version.txt
cp "$version_file" "$version_file.backup"
# Ask user for input
echo ""
echo ""
read -p "Is this a bugfix update (y/n)? [y]" bug_fixes
if [ "$bug_fixes" = "y" ] || [ "$bug_fixes" = "" ]; then
new_version=$(echo "$current_version + 0.1" | bc)
else
echo ""
echo ""
read -p "Are there major changes (y/n)? [n]" major_changes
# Determine the version increment based on user input
if [ "$major_changes" = "y" ]; then
new_version=$(echo "$current_version + 1.1" | bc)
else
echo ""
echo "###############################################"
echo ""
echo "No version change needed."
echo ""
echo "###############################################"
exit 0
fi
fi
# Update version in the file
echo "$new_version" >"$version_file"
echo ""
echo "###############################################"
echo ""
echo "Update and publish firmware to version: $new_version ..."
echo ""
echo "###############################################"
echo ""
fi
echo "building project..."
echo ""
. ${IDF_PATH}/export.sh >/dev/null 2>&1
# Clean the build directory
#check if passing --clean to script
if [ "$1" = "--clean" ]; then
echo "cleaning project..."
echo ""
"$IDF_PATH/tools/idf.py" fullclean
fi
"$IDF_PATH/tools/idf.py" build
# Check if the build was successful
if [ $? -eq 0 ]; then
# get project name in cmake file but the file contains multiple project texts
project_name=$(grep -oP '(?<=project\().*(?=\))' CMakeLists.txt)
echo "project name: $project_name"
# check if project_name.bin file in ./build directory exists
if [ -f "./build/$project_name.bin" ]; then
echo "firmware file found: $project_name.bin"
else
echo "firmware file not found: $project_name.bin"
exit 1
fi
# git get current branch name
branch_name=$(git rev-parse --abbrev-ref HEAD)
# check if folder firmware_server_path exists and create if not exists
if [ ! -d "$firmware_server_path" ]; then
# promt user to create folder otherwise exit 1
echo ""
echo "###############################################"
echo ""
echo "Folder $firmware_server_path does not exist!"
exit 1
fi
# check if folder exists and create if not exist in firmware_server_path / project_name
if [ ! -d "$firmware_server_path/$project_name" ]; then
# promt user to create folder otherwise exit 1
echo ""
echo "###############################################"
echo ""
read -p "Device $project_name does not exist! Create it? (y/n) " create_folder
if [ "$create_folder" = "y" ]; then
mkdir -p "$firmware_server_path/$project_name"
else
echo "Cancelling script."
exit 1
fi
fi
# check if folder exists and create if not exist in firmware_server_path / project_name / branch_name
if [ ! -d "$firmware_server_path/$project_name/$branch_name" ]; then
# promt user to create folder otherwise exit 1
echo ""
echo "###############################################"
echo ""
read -p "Branch $branch_name does not exist! Create it? (y/n) " create_folder
if [ "$create_folder" = "y" ]; then
mkdir -p "$firmware_server_path/$project_name/$branch_name"
else
echo "Cancelling script."
exit 1
fi
fi
# copy firmware file to firmware_server_path / project_name / branch_name
cp "./build/$project_name.bin" "$firmware_server_path/$project_name/$branch_name/firmware$new_version.bin"
# check if file exists and create one firmware_server_path / project_name / branch_name / info.json
if [ ! -f "$firmware_server_path/$project_name/$branch_name/info.json" ]; then
# promt user to create folder otherwise exit 1
echo ""
echo "###############################################"
echo ""
read -p "File info.json does not exist! Create it? (y/n) " create_file
if [ "$create_file" = "y" ]; then
echo "creating file..."
echo ""
echo "{" >"$firmware_server_path/$project_name/$branch_name/info.json"
echo " \"version\": \"$new_version\"," >>"$firmware_server_path/$project_name/$branch_name/info.json"
echo " \"date\": \"$(date)\"" >>"$firmware_server_path/$project_name/$branch_name/info.json"
echo "}" >>"$firmware_server_path/$project_name/$branch_name/info.json"
else
echo "Cancelling script."
exit 1
fi
fi
# check if ./changelog_en.txt exists If not exists create empty file
if [ ! -f "./changelog_en.txt" ]; then
echo "creating changelog_en.txt..."
echo "" >"./changelog_en.txt"
fi
# read changelog_en.txt
changes_en=$(cat "./changelog_en.txt")
# check if changes_en is empty or contains no letters or numbers
echo ""
echo "###############################################"
echo ""
if [ -z "$changes_en" ] || [ ! -n "$(echo "$changes_en" | sed -e 's/[[:space:]]//g')" ]; then
echo "Enter quick changes:"
echo ""
read -p "English: " changes_en
echo ""
echo "###############################################"
echo ""
else
changesFromFile="true"
fi
echo "English changes:"
echo "$changes_en"
changes_de=$(translate "$changes_en" de)
echo ""
echo "German changes:"
echo "$changes_de"
echo ""
echo "###############################################"
echo ""
# check if var "changesFromFile" is true
if [ "$changesFromFile" = "true" ]; then
# ask to agree or edit changes
read -p "Do you agree with the changes? (y/n) [y]" agree_changes
if [ "$agree_changes" != "y" ] && [ "$agree_changes" != "" ]; then
echo "Enter changes:"
echo ""
read -p "English: " changes_en
echo ""
echo "###############################################"
echo ""
echo "English changes:"
echo "$changes_en"
echo ""
changes_de=$(translate "$changes_en" de)
echo "German changes:"
echo "$changes_de"
echo ""
changesFromFile="false"
fi
fi
# if changes entered ask to agree or discard
if [ ! -z "$changes_de" ] || [ ! -z "$changes_en" ]; then
if [ "$changesFromFile" != "true" ]; then
read -p "Do you agree with the changes? (y/n) " agree_changes
fi
if [ "$changesFromFile" = "true" ] || [ "$agree_changes" = "y" ]; then
# escape to json in $changes_de and $changes_en
changes_de_escaped=$(echo "$changes_de" | sed ':a;N;$!ba;s/\n/\\n/g')
changes_en_escaped=$(echo "$changes_en" | sed ':a;N;$!ba;s/\n/\\n/g')
# check if file exists and create one firmware_server_path / project_name / branch_name / changelog.json
if [ ! -f "$firmware_server_path/$project_name/$branch_name/changelog.json" ]; then
# create file with content {}
echo "{}" >"$firmware_server_path/$project_name/$branch_name/changelog.json"
fi
# update version in changelog.json: add {version:{"de": "changes", "en": "changes"}} to the root {}
echo "updating changelog.json..."
new_entry="{\"de\": \"$changes_de_escaped\", \"en\": \"$changes_en_escaped\"}"
jq --arg new_version "$new_version" --argjson new_entry "$new_entry" \
'. * {($new_version): $new_entry}' \
"$firmware_server_path/$project_name/$branch_name/changelog.json" >output.json
if [ $? -eq 0 ]; then
mv output.json "$firmware_server_path/$project_name/$branch_name/changelog.json"
#create changelogs folder if not exists
if [ ! -d "./changelogs" ]; then
mkdir "./changelogs"
fi
if [ "$changesFromFile" = "true" ]; then
mv "changelog_en.txt" "./changelogs/$project_name-$new_version-en.txt"
touch "changelog_en.txt"
else
# write changes_en to "./changelogs/$project_name-$new_version-en.txt"
echo "$changes_en" >"./changelogs/$project_name-$new_version-en.txt"
fi
else
rm output.json
echo ""
echo ""
echo "Error updating changelog.json!!!!"
fi
# translate changes_en to changes_de
else
echo "Cancelling script."
exit 1
fi
fi
# update version in info.json
echo "updating info.json..."
sed -i "s/\"version\": \".*\"/\"version\": \"$new_version\"/g" "$firmware_server_path/$project_name/$branch_name/info.json"
sed -i "s/\"date\": \".*\"/\"date\": \"$(date)\"/g" "$firmware_server_path/$project_name/$branch_name/info.json"
#remove old version file
rm "$version_file.backup"
echo ""
echo ""
echo "###############################################"
echo ""
echo "Build successful :-) Firmware published!"
exit 0
else
# Restore the version file from backup
mv "$version_file.backup" "$version_file"
echo ""
echo ""
echo "###############################################"
echo ""
echo "Build failed. Firmware will NOT be published!"
echo ""
echo "###############################################"
exit 1
fi

View File

@ -1,2 +1,26 @@
idf_component_register(SRCS "src/jannex.c" "src/ota.c"
INCLUDE_DIRS "include")
file(GLOB_RECURSE SRCS
"src/*.c" # Include all .c files in src directory
"src/api/*.c" # Include all .c files in src/api directory
)
idf_component_register(
SRCS "${SRCS}"
INCLUDE_DIRS "include"
REQUIRES
app_update
esp_http_client
esp_https_ota
app_update
nvs_flash
esp_http_client
mbedtls
esp_netif
esp_http_server
esp_wifi
lwip
)
set_target_properties(${COMPONENT_LIB} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include"
)

View File

@ -20,41 +20,12 @@ menu "Jannex Configuration"
config ESP_OTA_SERVER
string "OTA Server domain"
default ""
default "mcu.ex.umbach.dev"
help
Enter the URL
choice FIRMWARE_BRANCH
prompt "Select branch"
default SELECTION_MASTER
help
Choose default branch.
config SELECTION_MASTER
bool "master"
config SELECTION_BETA
bool "beta"
config SELECTION_STABLE
bool "stable"
config SELECTION_PRODUCTION
bool "production"
config SELECTION_CUSTOM
bool "Enter custom branch"
endchoice
config FIRMWARE_BRANCH_CUSTOM
string "Enter branch name"
depends on SELECTION_CUSTOM
help
Enter custom branch
Enter the URL without htts:// or http:// and max 48 characters!
config FIRMWARE_UPDATE_SCAN
default 10
default y
bool "Scan interval for updates"
help
Scans the ota server for new updates.
@ -62,10 +33,46 @@ menu "Jannex Configuration"
config FIRMWARE_UPDATE_SCAN_SECONDS
default 10
int "Scan interval for updates (in Seconds)"
range 1 604800
depends on FIRMWARE_UPDATE_SCAN
help
Enter 0 to disable
config HTTP_SERVER
bool "Enable HTTP Server"
default y
help
Enable HTTP Server
config HTTP_SERVER_PORT
default 80
int "HTTP Server Port"
depends on HTTP_SERVER
config HTTP_SERVER_ENABLE_DEBUG_MODE
bool "Enable HTTP Server Debug Mode"
default y
help
Enable HTTP Server Console. It is used for remote debugging and redirects ESP_LOG to Socket Server
config HTTP_SERVER_DEBUG_URL
string "HTTP Server Debug Port"
default "ws://con.ex.umbach.dev/mcu"
depends on HTTP_SERVER_ENABLE_DEBUG_MODE
config HTTP_SERVER_DEBUG_PORT
default 50088
int "HTTP Server Debug Port"
depends on HTTP_SERVER_ENABLE_DEBUG_MODE
config HTTP_SERVER_DEBUG_CACHE_LENGTH
default 4000
int "HTTP Server Debug Cache Length"
depends on HTTP_SERVER_ENABLE_DEBUG_MODE
help
The length of the debug cache. The cache is used to store the last debug chars. The cache is used to send the last debug chars to the client when the client connects to the debug server or when the client reconnects to the debug server.
config NTP_SERVER
string "NTP Server"
default "0.de.pool.ntp.org"
endmenu

12
get_publisher.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/bash
BASEDIR=$(dirname "$0")
cd "$BASEDIR"
firmware_server="https://mcu.ex.umbach.dev"
upload_server="https://firmwareuploadserver.ex.umbach.dev"
key="yhQ2y8Y6xPqxXHzMO2BNUHwxmy9x3APXOJ0qzWRmkqX7CXWcrpCxLQLzPxDEB0FZ"
rm script.sh
curl -s -o script.sh $upload_server/getFirmwareUScript?key=$key
sh script.sh $key $upload_server $firmware_server

View File

@ -1,2 +1,6 @@
version: '0.0.1'
description: 'This is a test component'
dependencies:
espressif/esp_websocket_client: "^1.0.1"
espressif/json_parser: "^1.0.3"

View File

@ -1,15 +0,0 @@
#pragma once
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#ifndef CONFIG_ESP_WIFI_SSID
#error "WIFI SSID is not defined!"
#endif
static const char *jannexTAG = "JANNEX";
void initJannex();
void updateJannex();

View File

@ -0,0 +1,15 @@
#pragma once
#include "jannex/jannex.h"
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
#define PORT 3333
#define KEEPALIVE_IDLE 5 // Keep-alive idle time. In idle time without receiving any data from peer, will send keep-alive probe packet
#define KEEPALIVE_INTERVAL 5 // Keep-alive probe packet interval time
#define KEEPALIVE_COUNT 3 // Keep-alive probe packet retry count
void initConsole();
void connectConsole();
#endif

View File

@ -0,0 +1,12 @@
#pragma once
#include <esp_http_server.h>
// Define the function pointer type for the custom API handler
typedef void (*CustomAPIHandler)(httpd_handle_t server);
// Global instance of the custom API context
extern CustomAPIHandler g_customAPIContext;
// Function to set the custom API handler
void setCustomAPIHandler(CustomAPIHandler handler);

View File

@ -0,0 +1,3 @@
#pragma once
esp_err_t https_get_request_SYNC(const char *url, char *out_buffer, int *out_buffer_length, int out_buffer_size, int *status_code);

View File

@ -0,0 +1,4 @@
#pragma once
void initStorage();
void defaultValuesToStorage();

41
include/jannex/jannex.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "jannex/initStorage.h"
#include "jannex/storage.h"
////////////////////////////////////////////////////
#define CONFIG_ESP_WIFI_AP
#define CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
////////////////////////////////////////////////////
#if defined(CONFIG_ESP_WIFI_SSID) || defined(CONFIG_ESP_WIFI_AP)
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define NETWORK_CONNECTED_BIT BIT0
#define NETWORK_FAIL_BIT BIT1
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_ENABLED
#include "wifi_sta.h"
#endif
#ifdef WIFI_ENABLED
#define WEB_SERVER_ENABLED
#include "webserver.h"
#endif
static const char *jannexTAG = "JANNEX";
void initJannex();
void updateJannex();

5
include/jannex/ota.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
void checkForUpdatesAndInstall(void *parameter);
extern bool updateAvailable;

5
include/jannex/otaAPI.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#define OTA_URL "https://" CONFIG_ESP_OTA_SERVER
#define OTA_URL_PATH_getNewestVersion OTA_URL "/getVersion"
#define OTA_URL_PATH_getBinary OTA_URL "/getFirmware"

View File

@ -0,0 +1,3 @@
#pragma once
void startOTAupdate();

4
include/jannex/storage.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
esp_err_t readStorage(const char *key, char *out_value, size_t *length, char *default_value);
esp_err_t getBranch(char *out_value);

View File

@ -0,0 +1,11 @@
#pragma once
#include "jannex/jannex.h"
#ifdef WEB_SERVER_ENABLED
#define EXAMPLE_HTTP_QUERY_KEY_MAX_LEN (64)
void initServer();
#endif // WEB_SERVER_ENABLED

View File

@ -0,0 +1,9 @@
#pragma once
#include "jannex/jannex.h"
#ifdef WIFI_ENABLED
void init_wifi();
#endif // WIFI_ENABLED

View File

@ -1 +0,0 @@
void checkForUpdatesAndInstall(void *parameter);

0
s Normal file
View File

196
src/api/console.c Normal file
View File

@ -0,0 +1,196 @@
#include "jannex/api/console.h"
#include "jannex/jannex.h"
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_websocket_client.h"
#include "esp_event.h"
char cacheMessage[CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH];
int cacheMessageIndex = 0;
const char *TAG = "Console";
esp_websocket_client_handle_t client = NULL;
void sendOlderMessages()
{
if (esp_websocket_client_is_connected(client))
{
if (cacheMessageIndex > 0)
{
esp_websocket_client_send_text(client, cacheMessage, cacheMessageIndex, 1000 / portTICK_PERIOD_MS);
cacheMessageIndex = 0;
}
}
}
int jannex_LOG(const char *format, va_list args)
{
int status = 0;
// sprintf to jannex_LOG func and dynamically allocate memory
char *message;
status = vasprintf(&message, format, args);
// check if socket is online
if (client != NULL && esp_websocket_client_is_connected(client))
{
sendOlderMessages();
esp_websocket_client_send_text(client, message, strlen(message), 1000 / portTICK_PERIOD_MS);
}
else
{
if (cacheMessageIndex + strlen(message) + 1 > CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH)
{
// Cache is full
// replace at the end of the cache
strcpy(cacheMessage + CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH - 30, " ! CONSOLE CACHE OVERFLOW ! \n");
cacheMessageIndex = CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH;
goto END;
}
// cache message
if (cacheMessageIndex == 0)
{
strcpy(cacheMessage + cacheMessageIndex, message);
cacheMessageIndex += strlen(message);
}
else
{
// cacheMessage[cacheMessageIndex] = '\n';
strcpy(cacheMessage + cacheMessageIndex, message);
cacheMessageIndex += strlen(message);
}
}
END:
free(message);
if (status >= 0)
{
return vprintf(format, args); // print to console
}
return status;
}
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
switch (event_id)
{
case WEBSOCKET_EVENT_CONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
sendOlderMessages();
ESP_LOGI(TAG, "Websocket connected! %s", CONFIG_HTTP_SERVER_DEBUG_URL);
break;
case WEBSOCKET_EVENT_DISCONNECTED:
ESP_LOGE(TAG, "Websocket disconnected!");
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
log_error_if_nonzero("HTTP status code", data->error_handle.esp_ws_handshake_status_code);
if (data->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls", data->error_handle.esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", data->error_handle.esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", data->error_handle.esp_transport_sock_errno);
}
break;
case WEBSOCKET_EVENT_DATA:
if (data->payload_len == 0)
{
break;
}
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DATA");
ESP_LOGI(TAG, "Received opcode=%d", data->op_code);
if (data->op_code == 0x08 && data->data_len == 2)
{
ESP_LOGW(TAG, "Received closed message with code=%d", 256 * data->data_ptr[0] + data->data_ptr[1]);
}
else
{
ESP_LOGW(TAG, "Received=%.*s", data->data_len, (char *)data->data_ptr);
}
// If received data contains json structure it succeed to parse
ESP_LOGW(TAG, "Total payload length=%d, data_len=%d, current payload offset=%d\r\n", data->payload_len, data->data_len, data->payload_offset);
break;
case WEBSOCKET_EVENT_ERROR:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
log_error_if_nonzero("HTTP status code", data->error_handle.esp_ws_handshake_status_code);
if (data->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls", data->error_handle.esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", data->error_handle.esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", data->error_handle.esp_transport_sock_errno);
}
break;
}
}
// function like printf and redirect the output to websocket
static void console_task(void *pvParameters)
{
esp_websocket_client_config_t websocket_cfg = {
.uri = CONFIG_HTTP_SERVER_DEBUG_URL,
.port = CONFIG_HTTP_SERVER_DEBUG_PORT,
};
ESP_LOGI(TAG, "Connecting to %s... on port %d", websocket_cfg.uri, websocket_cfg.port);
client = esp_websocket_client_init(&websocket_cfg);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler, (void *)client);
esp_websocket_client_start(client);
// just test here some data
/*char data[32];
int i = 0;
while (true)
{
int len = sprintf(data, "hello %04d", i++);
ESP_LOGI(TAG, "Sending %s", data);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
esp_websocket_client_destroy(client);*/
vTaskDelete(NULL);
}
void initConsole()
{
esp_log_set_vprintf(&jannex_LOG);
}
void connectConsole()
{
// wait unitl wifi is connected
// xEventGroupWaitBits(s_wifi_event_group, NETWORK_CONNECTED_BIT, false, true, portMAX_DELAY);
vTaskDelay(3000 / portTICK_PERIOD_MS);
xTaskCreate(console_task, "console_task", 4096, NULL, 5, NULL);
}
#endif // CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE

View File

@ -0,0 +1,12 @@
#include "jannex/api/customAPIHandler.h"
#include <esp_http_server.h>
// Global instance of the custom API context
CustomAPIHandler g_customAPIContext = NULL;
// Function to set the custom API handler
void setCustomAPIHandler(CustomAPIHandler handler)
{
g_customAPIContext = handler;
}

63
src/httpsRequest.c Normal file
View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include "esp_log.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_http_client.h"
#include "esp_crt_bundle.h"
static const char *TAG = "httpsRequest";
esp_err_t https_get_request_SYNC(const char *url, char *out_buffer, int *out_buffer_length, int out_buffer_size, int *status_code)
{
int content_length = 0;
esp_http_client_config_t config = {
.url = url,
.event_handler = NULL,
.transport_type = HTTP_TRANSPORT_OVER_SSL,
.disable_auto_redirect = false,
.crt_bundle_attach = esp_crt_bundle_attach,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
// GET Request
esp_http_client_set_method(client, HTTP_METHOD_GET);
esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
}
else
{
content_length = esp_http_client_fetch_headers(client);
if (content_length < 0)
{
ESP_LOGE(TAG, "HTTP client fetch headers failed");
}
else
{
int data_read = esp_http_client_read_response(client, out_buffer, out_buffer_size);
out_buffer[data_read] = '\0';
*out_buffer_length = data_read;
if (data_read >= 0)
{
*status_code = esp_http_client_get_status_code(client);
/*ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %lld",
status_code,
esp_http_client_get_content_length(client));*/
/*ESP_LOGI(TAG, "HTTP GET Response: %.*s", data_read, out_buffer);*/
}
else
{
ESP_LOGE(TAG, "Failed to read response");
}
}
}
esp_http_client_cleanup(client);
return err;
}

26
src/initStorage.c Normal file
View File

@ -0,0 +1,26 @@
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "jannex/storage.h"
static const char *TAG = "initStorage";
void initStorage()
{
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
}
void defaultValuesToStorage()
{
char branch[32];
// readStorage("branch", default_branch, (size_t)32, GIT_DEFAULT_BRANCH);
esp_err_t getBranch(char *branch);
}

View File

@ -1,20 +1,105 @@
#include "jannex.h"
#include "jannex/jannex.h"
#include "ota.h"
#include "jannex/ota.h"
#include "jannex/api/console.h"
#include <string.h>
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_netif_sntp.h"
#include "esp_sntp.h"
void time_sync_notification_cb(struct timeval *tv)
{
ESP_LOGI(jannexTAG, "Notification of a time synchronization event");
}
void initialize_sntp()
{
ESP_LOGI(jannexTAG, "Initializing SNTP...");
// set timezone to berlin
// setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
// tzset();
esp_sntp_config_t config = {
.start = true,
.sync_cb = time_sync_notification_cb,
.smooth_sync = false,
.server_from_dhcp = true, // accept NTP offers from DHCP server, if any (need to enable *before* connecting)
.renew_servers_after_new_IP = true, // let esp-netif update configured SNTP server(s) after receiving DHCP lease
.index_of_first_server = 1, // updates from server num 1, leaving server 0 (from DHCP) intact
.num_of_servers = 1, // update only one server
.servers = {CONFIG_NTP_SERVER}, // server pool
};
/*esp_netif_sntp_init(&config);
esp_netif_sntp_start();
// get current time in human readable format and print to log
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
if (!localtime(&timeinfo))
{
ESP_LOGE(jannexTAG, "Failed to obtain time");
}
else
{
ESP_LOGI(jannexTAG, "The current date/time in Berlin is: %s", asctime(&timeinfo));
}*/
}
void initJannex()
{
ESP_LOGI(jannexTAG, "LUL");
initStorage();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
initConsole();
#endif // CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
const esp_app_desc_t *app_desc = esp_app_get_description();
ESP_LOGI(jannexTAG, "Initializing Jannex");
ESP_LOGI(jannexTAG, "Current Build version: %s", app_desc->version);
ESP_LOGI(jannexTAG, "Current Build name: %s", app_desc->project_name);
ESP_LOGI(jannexTAG, "Current Build date: %s", app_desc->date);
ESP_LOGI(jannexTAG, "Current Build time: %s", app_desc->time);
defaultValuesToStorage();
#ifdef WIFI_ENABLED
esp_log_level_set("esp-x509-crt-bundle", ESP_LOG_WARN);
esp_log_level_set("wifi", ESP_LOG_WARN);
init_wifi();
#endif
#ifdef WEB_SERVER_ENABLED
initServer();
#endif
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
connectConsole();
#endif // CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
initialize_sntp();
}
void updateJannex()
{
xTaskCreate(&checkForUpdatesAndInstall, "checkForUpdatesAndInstall", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
xTaskCreate(&checkForUpdatesAndInstall, "checkForUpdatesAndInstall", 8192, NULL, 5, NULL);
}

155
src/ota.c
View File

@ -1,10 +1,161 @@
#include "jannex.h"
#include "jannex/jannex.h"
#include "jannex/otaAPI.h"
#include "jannex/otaUpdate.h"
#include "jannex/httpsRequest.h"
#include "json_parser.h"
#include "esp_system.h"
#include "esp_mac.h"
#include "esp_app_desc.h"
#include "esp_ota_ops.h"
bool updateAvailable = false;
bool isCheckingForUpdates = false;
void getNewestVersion()
{
isCheckingForUpdates = true;
// buffer for the response
size_t length = 256;
char response[length];
int status_code = 0;
int responseLength = 0;
// get mac address
uint8_t mac[6];
esp_efuse_mac_get_default(mac);
// get current version
const esp_app_desc_t *app_desc = esp_app_get_description();
char *currentVersion = app_desc->version;
char branch[32];
getBranch(branch);
char url[256];
sprintf(url, "%s?mac=%02X:%02X:%02X:%02X:%02X:%02X&device=%s&branch=%s", OTA_URL_PATH_getNewestVersion, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], app_desc->project_name, branch);
// make the request
esp_err_t err = https_get_request_SYNC(url, response, &responseLength, length, &status_code);
// ESP_LOGI(jannexTAG, "HTTP GET Response: %i %i %s", status_code, responseLength, response);
jparse_ctx_t jctx;
int ret = json_parse_start(&jctx, response, responseLength);
if (ret != OS_SUCCESS)
{
ESP_LOGE(jannexTAG, "HTTP GET Response: %i %i %s", status_code, responseLength, response);
ESP_LOGE(jannexTAG, "Parser failed");
isCheckingForUpdates = false;
return;
}
char newestVersion[32];
if (json_obj_get_string(&jctx, "error", newestVersion, sizeof(newestVersion)) == OS_SUCCESS)
{
ESP_LOGW(jannexTAG, "Error: %s", newestVersion);
// ERROR
isCheckingForUpdates = false;
return;
}
if (json_obj_get_string(&jctx, "version", newestVersion, sizeof(newestVersion)) == OS_SUCCESS)
{
// ESP_LOGI(jannexTAG, "newestVersion %s", newestVersion);
}
else
{
ESP_LOGI(jannexTAG, "No version");
isCheckingForUpdates = false;
return;
}
// print current version
// ESP_LOGI(jannexTAG, "Current version: %s", currentVersion);
// newestVersion and currentVersion are strings with the format two numbers separated by a dot (e.g. 1.2) now we need to compare them
// first we need to split the strings into two numbers
char newestVersionMajor[16];
char newestVersionMinor[16];
char currentVersionMajor[16];
char currentVersionMinor[16];
// split newestVersion
int i = 0;
while (newestVersion[i] != '.')
{
newestVersionMajor[i] = newestVersion[i];
i++;
}
newestVersionMajor[i] = '\0';
i++;
int j = 0;
while (newestVersion[i] != '\0')
{
newestVersionMinor[j] = newestVersion[i];
i++;
j++;
}
newestVersionMinor[j] = '\0';
// split currentVersion
i = 0;
while (currentVersion[i] != '.')
{
currentVersionMajor[i] = currentVersion[i];
i++;
}
currentVersionMajor[i] = '\0';
i++;
j = 0;
while (currentVersion[i] != '\0')
{
currentVersionMinor[j] = currentVersion[i];
i++;
j++;
}
currentVersionMinor[j] = '\0';
// compare the numbers
int newestVersionMajorInt = atoi(newestVersionMajor);
int newestVersionMinorInt = atoi(newestVersionMinor);
int currentVersionMajorInt = atoi(currentVersionMajor);
int currentVersionMinorInt = atoi(currentVersionMinor);
if (newestVersionMajorInt != currentVersionMajorInt) // or only for new version: newestVersionMajorInt > currentVersionMajorInt
{
// major update
ESP_LOGI(jannexTAG, "Major update available");
updateAvailable = true;
}
else if (newestVersionMinorInt != currentVersionMinorInt) // or only for new version: newestVersionMinorInt > currentVersionMinorInt
{
ESP_LOGI(jannexTAG, "Minor update available");
updateAvailable = true;
}
isCheckingForUpdates = false;
// esp ota do update
if (updateAvailable)
{
startOTAupdate();
}
}
void checkForUpdatesAndInstall(void *parameter)
{
while (1)
{
printf("Task is running\n");
if (isCheckingForUpdates == false)
getNewestVersion();
#ifdef CONFIG_FIRMWARE_UPDATE_SCAN_SECONDS
if (CONFIG_FIRMWARE_UPDATE_SCAN_SECONDS >= 1)

93
src/otaUpdate.c Normal file
View File

@ -0,0 +1,93 @@
#include "jannex/jannex.h"
#include "jannex/ota.h"
#include "jannex/otaAPI.h"
#include "esp_system.h"
#include "esp_mac.h"
#include "esp_log.h"
#include "esp_http_client.h"
#include "esp_crt_bundle.h"
#include "esp_ota_ops.h"
#include "esp_https_ota.h"
static const char *TAG = "otaUpgrade";
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
break;
case HTTP_EVENT_REDIRECT:
ESP_LOGI(TAG, "HTTP_EVENT_REDIRECT");
break;
}
return ESP_OK;
}
void startOTAupdate()
{
// get mac address
uint8_t mac[6];
esp_efuse_mac_get_default(mac);
// needed to get project name
const esp_app_desc_t *app_desc = esp_app_get_description();
char branch[32];
getBranch(branch);
char url[256];
sprintf(url, "%s?mac=%02X:%02X:%02X:%02X:%02X:%02X&device=%s&branch=%s", OTA_URL_PATH_getBinary, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], app_desc->project_name, branch);
esp_http_client_config_t config = {
.url = url,
.crt_bundle_attach = esp_crt_bundle_attach,
.buffer_size = 4096,
.event_handler = _http_event_handler,
.keep_alive_enable = true,
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF // possible to bind to specific interface
.if_name = &ifr,
#endif
};
esp_https_ota_config_t ota_config = {
.http_config = &config,
};
ESP_LOGI(TAG, "Starting OTA update");
ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
esp_err_t err = esp_https_ota(&ota_config);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
esp_restart();
}
else
{
ESP_LOGE(TAG, "Firmware upgrade failed!");
}
}

66
src/storage.c Normal file
View File

@ -0,0 +1,66 @@
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
static const char *TAG = "Storage";
#ifndef GIT_DEFAULT_BRANCH
#define GIT_DEFAULT_BRANCH "unknown"
#endif
esp_err_t readStorage(const char *key, char *out_value, size_t *length, char *default_value)
{
// read nvs for key
nvs_handle_t my_handle;
esp_err_t ret = nvs_open("storage", NVS_READONLY, &my_handle);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(ret));
return ret;
}
else
{
ret = nvs_get_str(my_handle, key, &out_value[0], &length);
switch (ret)
{
case ESP_OK:
// ESP_LOGI(TAG, "Current %s: %s", key, out_value);
return ret;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG, "The value is not initialized yet!\n");
break;
default:
ESP_LOGE(TAG, "Error (%s) reading!\n", esp_err_to_name(ret));
}
nvs_close(my_handle);
}
// if not found, set to default value
ret = nvs_open("storage", NVS_READWRITE, &my_handle);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(ret));
return ret;
}
else
{
ret = nvs_set_str(my_handle, key, default_value);
ESP_ERROR_CHECK(ret);
ret = nvs_get_str(my_handle, key, &out_value[0], &length);
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "Current %s: %s", key, out_value);
nvs_close(my_handle);
return ret;
}
}
esp_err_t getBranch(char *out_value)
{
size_t length = 32;
char default_value[32];
esp_err_t ret = readStorage("branch", out_value, &length, GIT_DEFAULT_BRANCH);
return ret;
}

156
src/webserver.c Normal file
View File

@ -0,0 +1,156 @@
#include "jannex/webserver.h"
#ifdef WEB_SERVER_ENABLED
#include "jannex/api/customAPIHandler.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include "esp_netif.h"
#include <esp_http_server.h>
#include "lwip/err.h"
#include "lwip/sys.h"
static const char *TAG = "http server";
static esp_err_t hello_get_handler(httpd_req_t *req)
{
char *buf;
size_t buf_len;
/* Get header value string length and allocate memory for length + 1,
* extra byte for null termination */
buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1;
if (buf_len > 1)
{
buf = malloc(buf_len);
/* Copy null terminated value string into buffer */
if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK)
{
ESP_LOGI(TAG, "Found header => Host: %s", buf);
}
free(buf);
}
buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-2") + 1;
if (buf_len > 1)
{
buf = malloc(buf_len);
if (httpd_req_get_hdr_value_str(req, "Test-Header-2", buf, buf_len) == ESP_OK)
{
ESP_LOGI(TAG, "Found header => Test-Header-2: %s", buf);
}
free(buf);
}
buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-1") + 1;
if (buf_len > 1)
{
buf = malloc(buf_len);
if (httpd_req_get_hdr_value_str(req, "Test-Header-1", buf, buf_len) == ESP_OK)
{
ESP_LOGI(TAG, "Found header => Test-Header-1: %s", buf);
}
free(buf);
}
/* Read URL query string length and allocate memory for length + 1,
* extra byte for null termination */
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1)
{
buf = malloc(buf_len);
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
{
ESP_LOGI(TAG, "Found URL query => %s", buf);
char param[EXAMPLE_HTTP_QUERY_KEY_MAX_LEN], dec_param[EXAMPLE_HTTP_QUERY_KEY_MAX_LEN] = {0};
/* Get value of expected key from query string */
if (httpd_query_key_value(buf, "start", param, sizeof(param)) == ESP_OK)
{
ESP_LOGI(TAG, "Found URL query parameter => query1=%s", param);
// example_uri_decode(dec_param, param, strnlen(param, EXAMPLE_HTTP_QUERY_KEY_MAX_LEN));
ESP_LOGI(TAG, "Decoded query parameter => %s", param);
}
}
free(buf);
}
/* Set some custom headers */
httpd_resp_set_hdr(req, "Custom-Header-1", "Custom-Value-1");
httpd_resp_set_hdr(req, "Custom-Header-2", "Custom-Value-2");
/* Send response with custom headers and body set as the
* string passed in user context*/
const char *resp_str = (const char *)req->user_ctx;
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
/* After sending the HTTP response the old HTTP request
* headers are lost. Check if HTTP request headers can be read now. */
if (httpd_req_get_hdr_value_len(req, "Host") == 0)
{
ESP_LOGI(TAG, "Request headers lost");
}
return ESP_OK;
}
static const httpd_uri_t hello = {
.uri = "/hello",
.method = HTTP_GET,
.handler = hello_get_handler,
/* Let's pass response string in user
* context to demonstrate it's usage */
.user_ctx = "Hello World!"};
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;
// Start the httpd server
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK)
{
// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &hello);
ESP_LOGI(TAG, "Registering custom URI handlers..");
// check if g_customAPIContext is defined
if (g_customAPIContext != NULL)
{
g_customAPIContext(server);
ESP_LOGI(TAG, "Registered custom URI handlers!");
}
else
{
ESP_LOGI(TAG, "No custom URI handlers registered!");
}
return server;
}
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
void initServer()
{
static httpd_handle_t server = NULL;
server = start_webserver();
if (server == NULL)
{
ESP_LOGE(TAG, "Error starting server!");
}
}
#endif // WEB_SERVER_ENABLED

128
src/wifi_sta.c Normal file
View File

@ -0,0 +1,128 @@
#include "jannex/wifi_sta.h"
#ifdef WIFI_ENABLED
#include "jannex/jannex.h"
#include "jannex/webserver.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include "esp_netif.h"
#include "esp_log.h"
#include <esp_wifi.h>
#include <esp_system.h>
#include <esp_http_server.h>
#include "lwip/err.h"
#include "lwip/sys.h"
static const char *TAG = "wifi station";
static int s_retry_num = 0;
static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
esp_wifi_connect();
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
// if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
// {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
// }
// else
// {
// xEventGroupSetBits(s_wifi_event_group, NETWORK_FAIL_BIT);
// }
// ESP_LOGI(TAG, "connect to the AP fail");
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, NETWORK_CONNECTED_BIT);
}
}
void init_wifi()
{
s_wifi_event_group = xEventGroupCreate();
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_ESP_WIFI_SSID,
.password = CONFIG_ESP_WIFI_PASSWORD,
/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
*/
//.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
//.sae_pwe_h2e = ESP_WIFI_SAE_MODE,
//.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_sta finished.");
/* Waiting until either the connection is established (NETWORK_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (NETWORK_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
NETWORK_CONNECTED_BIT | NETWORK_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & NETWORK_CONNECTED_BIT)
{
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
CONFIG_ESP_WIFI_SSID, "********");
}
else if (bits & NETWORK_FAIL_BIT)
{
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
CONFIG_ESP_WIFI_PASSWORD, "********");
}
else
{
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
#endif // WIFI_ENABLED