add source code that exists so far

This commit is contained in:
Florian Hoss 2022-04-05 20:05:16 +02:00
parent 275c84b48f
commit ef307a24f5
21 changed files with 3276 additions and 0 deletions

7
SourceCode/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
include/network/secrets.h

View file

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.8)
set(CMAKE_CXX_STANDARD 17)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32)

View file

@ -0,0 +1,12 @@
#ifndef GPIO_H
#define GPIO_H
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../network/theWebServer.h"
esp_err_t relay_put_handler(httpd_req_t *req);
#endif

View file

@ -0,0 +1,12 @@
#ifndef LOGGER_H
#define LOGGER_H
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
void print_logo();
void print_esp32_information();
void setup_all_log_levels();
#endif

View file

@ -0,0 +1,9 @@
#ifndef NVS_H
#define NVS_H
#include "nvs_flash.h"
#include "esp_log.h"
void setup_nvs(void);
#endif

View file

@ -0,0 +1,9 @@
#ifndef SNTP_H
#define SNTP_H
#include "esp_sntp.h"
#include "esp_log.h"
void setup_sntp();
#endif

View file

@ -0,0 +1,9 @@
#ifndef FIREWALL_H
#define FIREWALL_H
#include "theWebServer.h"
esp_err_t firewall_get_handler(httpd_req_t *req);
esp_err_t firewall_post_handler(httpd_req_t *req);
#endif

View file

@ -0,0 +1,18 @@
#ifndef WEBSERVER_H
#define WEBSERVER_H
#include "esp_system.h"
#include "esp_event.h"
#include "esp_http_server.h"
#include "esp_log.h"
#include "cJSON.h"
#include "stdlib.h"
#include "../common/theGPIO.h"
#include "theFirewall.h"
void custom_json_response(httpd_req_t *req, char *message, char *type);
void custom_request_middleware(httpd_req_t *req);
void setup_web_server(char *serverIp);
#endif

View file

@ -0,0 +1,26 @@
#ifndef WIFI_H
#define WIFI_H
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "secrets.h"
#define ESP_WIFI_SSID SSID
#define ESP_WIFI_PASS PSK
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
void setup_wifi(char *serverIp);
#endif

23
SourceCode/platformio.ini Normal file
View file

@ -0,0 +1,23 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-evb]
platform = espressif32
board = esp32-evb
framework = espidf
monitor_speed = 115200
monitor_flags = --raw
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = espidf
monitor_speed = 115200
monitor_flags = --raw

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
# This file was automatically generated for projects
# without default 'CMakeLists.txt' file.
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
idf_component_register(SRCS ${app_sources})

View file

@ -0,0 +1,100 @@
#include "common/theGPIO.h"
static const char *TAG = "GPIO";
struct GPIO
{
int pin;
char description[20];
int state;
};
// OLIMEX ESP-32-EVB Relays
struct GPIO Relay1 = {32, "Relay 1", 0};
struct GPIO Relay2 = {33, "Relay 2", 0};
static void print_gpio_status(struct GPIO *gpio)
{
ESP_LOGI(TAG, "%s (Pin: %i) is %s", gpio->description, gpio->pin, gpio->state == 0 ? "Off" : "On");
}
static void change_gpio_state(struct GPIO *gpio, int state)
{
gpio_set_direction(gpio->pin, GPIO_MODE_OUTPUT);
gpio_set_level(gpio->pin, state);
gpio->state = state;
print_gpio_status(gpio);
}
static void turn_gpio_on(struct GPIO *gpio)
{
change_gpio_state(gpio, 1);
}
static void turn_gpio_off(struct GPIO *gpio)
{
change_gpio_state(gpio, 0);
}
static void toggle_gpio_state(struct GPIO *gpio)
{
change_gpio_state(gpio, gpio->state == 0 ? 1 : 0);
}
static void inching_gpio_state(struct GPIO *gpio, int duration)
{
toggle_gpio_state(gpio);
vTaskDelay(duration / portTICK_PERIOD_MS);
toggle_gpio_state(gpio);
}
esp_err_t relay_put_handler(httpd_req_t *req)
{
custom_request_middleware(req);
size_t buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1)
{
char *buf = malloc(buf_len);
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
{
char relayParameter[2];
char stateParameter[7];
struct GPIO *relayPtr = NULL;
if ((httpd_query_key_value(buf, "relay", relayParameter, sizeof(relayParameter)) == ESP_OK) &&
(httpd_query_key_value(buf, "state", stateParameter, sizeof(stateParameter)) == ESP_OK))
{
if (strcmp(relayParameter, "1") == 0)
relayPtr = &Relay1;
else if (strcmp(relayParameter, "2") == 0)
relayPtr = &Relay2;
else
{
custom_json_response(req, "not a valid relay", HTTPD_400);
return ESP_FAIL;
}
if (strcmp(stateParameter, "on") == 0)
turn_gpio_on(relayPtr);
else if (strcmp(stateParameter, "off") == 0)
turn_gpio_off(relayPtr);
else if (strcmp(stateParameter, "toggle") == 0)
toggle_gpio_state(relayPtr);
else if (strcmp(stateParameter, "inch") == 0)
inching_gpio_state(relayPtr, 1000);
else
{
custom_json_response(req, "not a valid state", HTTPD_400);
return ESP_FAIL;
}
}
else
{
custom_json_response(req, "please provide relay and state query parameter", HTTPD_400);
return ESP_FAIL;
}
}
free(buf);
custom_json_response(req, "success", HTTPD_200);
return ESP_OK;
}
custom_json_response(req, "please provide relay and state query parameter", HTTPD_400);
return ESP_FAIL;
}

View file

@ -0,0 +1,48 @@
#include "common/theLogger.h"
static const char *TAG = "System";
void print_logo()
{
const char *Logo[] = {
"\n ______ _____ _____ ____ ___ ______ _ _ _ \n",
" | ____|/ ____| __ \\___ \\__ \\ | ____(_) | | |\n",
" | |__ | (___ | |__) |__) | ) |_____| |__ _ _ __ _____ ____ _| | |\n",
" | __| \\___ \\| ___/|__ < / /______| __| | | '__/ _ \\ \\ /\\ / / _` | | |\n",
" | |____ ____) | | ___) / /_ | | | | | | __/\\ V V / (_| | | |\n",
" |______|_____/|_| |____/____| |_| |_|_| \\___| \\_/\\_/ \\__,_|_|_|\n\n",
};
int logoSize = sizeof Logo / sizeof *Logo;
for (int i = 0; i < logoSize; ++i)
{
printf(Logo[i]);
}
}
void print_esp32_information()
{
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGI(TAG, "This is an ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision %d",
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
chip_info.revision);
ESP_LOGI(TAG, "%dMB %s flash, minimum free heap size: %d bytes\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external",
esp_get_minimum_free_heap_size());
}
void setup_all_log_levels()
{
esp_log_level_set("*", ESP_LOG_ERROR);
esp_log_level_set(TAG, ESP_LOG_INFO);
esp_log_level_set("NVS", ESP_LOG_INFO);
esp_log_level_set("WiFi", ESP_LOG_INFO);
esp_log_level_set("SNTP", ESP_LOG_INFO);
esp_log_level_set("GPIO", ESP_LOG_INFO);
esp_log_level_set("WebServer", ESP_LOG_INFO);
esp_log_level_set("Firewall", ESP_LOG_INFO);
}

View file

@ -0,0 +1,15 @@
#include "common/theNVS.h"
static const char *TAG = "NVS";
void setup_nvs(void)
{
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);
ESP_LOGI(TAG, "Initialization done");
}

View file

@ -0,0 +1,37 @@
#include "common/theSNTP.h"
static const char *TAG = "SNTP";
void sntp_sync_notification_call_back(struct timeval *tv)
{
ESP_LOGI(TAG, "Time synchronization done");
}
static void initialize_sntp()
{
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_set_time_sync_notification_cb(sntp_sync_notification_call_back);
sntp_init();
ESP_LOGI(TAG, "Getting current time from \"%s\"", sntp_getservername(0));
}
static void set_time_zone_to_germany()
{
// Timezone Codes: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
time_t now;
struct tm timeinfo;
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
tzset();
time(&now);
localtime_r(&now, &timeinfo);
ESP_LOGI(TAG, "Timezone set to Europe/Berlin");
}
void setup_sntp()
{
set_time_zone_to_germany();
initialize_sntp();
}

20
SourceCode/src/main.c Normal file
View file

@ -0,0 +1,20 @@
#include "common/theLogger.h"
#include "common/theSNTP.h"
#include "common/theNVS.h"
#include "network/theWifi.h"
#include "network/theWebServer.h"
char server_ip[IP4ADDR_STRLEN_MAX] = "0.0.0.0";
void app_main()
{
setup_all_log_levels();
print_logo();
print_esp32_information();
setup_nvs();
setup_wifi(server_ip);
setup_sntp();
setup_web_server(server_ip);
}

View file

@ -0,0 +1,104 @@
#include "network/theFirewall.h"
static const char *TAG = "Firewall";
static struct rule_node *head = NULL;
static int amount_of_rules = 0;
typedef struct rule_node
{
int key;
char source[IP4ADDR_STRLEN_MAX];
char destination[IP4ADDR_STRLEN_MAX];
char protocol[4];
char target[7];
struct rule_node *next;
} rule_node_t;
static rule_node_t *add_rule_to_firewall(char *source, char *destination, char *protocol, char *target)
{
struct rule_node *temp;
struct rule_node *link = (struct rule_node *)malloc(sizeof(struct rule_node));
link->key = ++amount_of_rules;
strcpy(link->source, source);
strcpy(link->destination, destination);
strcpy(link->protocol, protocol);
strcpy(link->target, target);
if (head == NULL)
{
head = link;
link->next = NULL;
return link;
}
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = link;
link->next = NULL;
return link;
}
static void prepare_firewall_json(cJSON *jsonResponse, rule_node_t *link)
{
cJSON_AddStringToObject(jsonResponse, "status", "success");
cJSON_AddNumberToObject(jsonResponse, "rule", link->key);
cJSON_AddStringToObject(jsonResponse, "source", link->source);
cJSON_AddStringToObject(jsonResponse, "destination", link->destination);
cJSON_AddStringToObject(jsonResponse, "protocol", link->protocol);
cJSON_AddStringToObject(jsonResponse, "target", link->target);
}
esp_err_t firewall_get_handler(httpd_req_t *req)
{
ESP_LOGI(TAG, "Total firewall rulse: %i", amount_of_rules);
custom_request_middleware(req);
struct rule_node *ptr = head;
cJSON *jsonArray = cJSON_CreateArray();
while (ptr != NULL)
{
cJSON *jsonRrule = cJSON_CreateObject();
prepare_firewall_json(jsonRrule, ptr);
cJSON_AddItemToArray(jsonArray, jsonRrule);
ptr = ptr->next;
}
const char *stringResponse = cJSON_Print(jsonArray);
cJSON_Delete(jsonArray);
httpd_resp_sendstr(req, stringResponse);
free((void *)stringResponse);
return ESP_OK;
}
esp_err_t firewall_post_handler(httpd_req_t *req)
{
custom_request_middleware(req);
size_t buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1)
{
char *buf = malloc(buf_len);
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
{
char sourceParameter[IP4ADDR_STRLEN_MAX];
char destinationParameter[IP4ADDR_STRLEN_MAX];
char protocolParameter[4];
char targetParameter[7];
if ((httpd_query_key_value(buf, "source", sourceParameter, sizeof(sourceParameter)) == ESP_OK) &&
(httpd_query_key_value(buf, "destination", destinationParameter, sizeof(destinationParameter)) == ESP_OK) &&
(httpd_query_key_value(buf, "protocol", protocolParameter, sizeof(protocolParameter)) == ESP_OK) &&
(httpd_query_key_value(buf, "target", targetParameter, sizeof(targetParameter)) == ESP_OK))
{
rule_node_t *link = add_rule_to_firewall(sourceParameter, destinationParameter, protocolParameter, targetParameter);
cJSON *jsonResponse = cJSON_CreateObject();
prepare_firewall_json(jsonResponse, link);
const char *stringResponse = cJSON_Print(jsonResponse);
cJSON_Delete(jsonResponse);
httpd_resp_sendstr(req, stringResponse);
free((void *)stringResponse);
free(buf);
return ESP_OK;
}
}
}
custom_json_response(req, "please provide query parameter", HTTPD_400);
return ESP_FAIL;
}

View file

@ -0,0 +1,136 @@
#include "network/theWebServer.h"
static const char *TAG = "WebServer";
static char *server_ip_ptr = NULL;
static httpd_config_t *server_config_ptr = NULL;
static struct route *head = NULL;
static int amount_of_routes = 1;
struct route
{
const char *uri;
const char *method;
int key;
struct route *next;
};
static char *convert_method_to_string(httpd_method_t method)
{
switch (method)
{
case HTTP_GET:
return "GET";
break;
case HTTP_POST:
return "POST";
break;
case HTTP_PUT:
return "PUT";
break;
case HTTP_DELETE:
return "DELETE";
break;
default:
return "not configured";
break;
}
}
static void print_routes_linked_list()
{
struct route *ptr = head;
printf("\n");
ESP_LOGW(TAG, "Available Routes:");
while (ptr != NULL)
{
ESP_LOGW(TAG, "%2d: %-8s-> http://%s:%d%s", ptr->key, ptr->method, server_ip_ptr, server_config_ptr->server_port, ptr->uri);
ptr = ptr->next;
}
printf("\n");
}
static void add_route_to_linked_list(const httpd_uri_t *uri_handler)
{
struct route *temp;
struct route *link = (struct route *)malloc(sizeof(struct route));
link->key = amount_of_routes;
amount_of_routes++;
link->uri = uri_handler->uri;
link->method = convert_method_to_string(uri_handler->method);
if (head == NULL)
{
head = link;
link->next = NULL;
return;
}
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = link;
link->next = NULL;
}
void custom_request_middleware(httpd_req_t *req)
{
ESP_LOGI(TAG, "%s: %s", convert_method_to_string(req->method), req->uri);
httpd_resp_set_type(req, HTTPD_TYPE_JSON);
}
void custom_json_response(httpd_req_t *req, char *message, char *type)
{
httpd_resp_set_status(req, type);
cJSON *json_response = cJSON_CreateObject();
cJSON_AddStringToObject(json_response, "status", message);
httpd_resp_sendstr(req, cJSON_Print(json_response));
cJSON_Delete(json_response);
}
static void register_request_helper(httpd_handle_t *server, const httpd_uri_t *uri_handler)
{
add_route_to_linked_list(uri_handler);
httpd_register_uri_handler(server, uri_handler);
}
static void register_all_request_handlers(httpd_handle_t *server)
{
// FIREWALL ROUTES
httpd_uri_t firewall_get_uri = {.uri = "/api/v1/firewall", .method = HTTP_GET, .handler = firewall_get_handler};
register_request_helper(server, &firewall_get_uri);
httpd_uri_t firewall_post_uri = {.uri = "/api/v1/firewall", .method = HTTP_POST, .handler = firewall_post_handler};
register_request_helper(server, &firewall_post_uri);
httpd_uri_t firewall_put_uri = {.uri = "/api/v1/firewall", .method = HTTP_PUT, .handler = firewall_get_handler};
register_request_helper(server, &firewall_put_uri);
httpd_uri_t firewall_delete_uri = {.uri = "/api/v1/firewall", .method = HTTP_DELETE, .handler = firewall_get_handler};
register_request_helper(server, &firewall_delete_uri);
// GPIO ROUTES
httpd_uri_t gpio_put_uri = {.uri = "/api/v1/gpio", .method = HTTP_POST, .handler = relay_put_handler};
register_request_helper(server, &gpio_put_uri);
print_routes_linked_list();
}
static esp_err_t start_web_server()
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_wildcard;
config.lru_purge_enable = true;
config.server_port = 8080;
server_config_ptr = &config;
if (httpd_start(&server, &config) == ESP_OK)
{
register_all_request_handlers(server);
return ESP_OK;
}
return ESP_FAIL;
}
void setup_web_server(char *server_ip)
{
server_ip_ptr = server_ip;
ESP_ERROR_CHECK(start_web_server());
}

View file

@ -0,0 +1,87 @@
#include "network/theWifi.h"
static const char *TAG = "WiFi";
static EventGroupHandle_t s_wifi_event_group;
static int s_retry_num = 0;
static int s_retry_max = 10;
static char *server_ip_ptr = NULL;
static void wifi_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 < s_retry_max)
{
esp_wifi_connect();
s_retry_num++;
ESP_LOGW(TAG, "Retrying to connect to the AP...");
}
else
{
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
ESP_LOGE(TAG, "Connecting to the AP failed");
}
}
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_ip4_addr_t ipv4 = event->ip_info.ip;
esp_ip4addr_ntoa(&ipv4, server_ip_ptr, IP4ADDR_STRLEN_MAX);
ESP_LOGI(TAG, "Assigned IP-Address: %s", server_ip_ptr);
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void setup_wifi(char *server_ip)
{
server_ip_ptr = server_ip;
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t init_config = WIFI_INIT_CONFIG_DEFAULT();
vTaskDelay(2000 / portTICK_PERIOD_MS);
ESP_ERROR_CHECK(esp_wifi_init(&init_config));
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, &wifi_event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = ESP_WIFI_SSID,
.password = ESP_WIFI_PASS,
},
};
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, "Initialization done");
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT)
{
ESP_LOGI(TAG, "Connected to SSID: %s",
ESP_WIFI_SSID);
}
else if (bits & WIFI_FAIL_BIT)
{
ESP_LOGE(TAG, "Failed to connect to SSID: %s",
ESP_WIFI_SSID);
}
else
{
ESP_LOGE(TAG, "Unexpected event");
}
}