add base uri api using http post/json
This commit is contained in:
parent
96821809ad
commit
b00f2b2dd4
|
@ -9,6 +9,7 @@
|
||||||
#include "wt_mdns_config.h"
|
#include "wt_mdns_config.h"
|
||||||
#include "wt_storage.h"
|
#include "wt_storage.h"
|
||||||
#include "wifi_manager.h"
|
#include "wifi_manager.h"
|
||||||
|
#include "web_server.h"
|
||||||
|
|
||||||
void app_main()
|
void app_main()
|
||||||
{
|
{
|
||||||
|
@ -18,6 +19,7 @@ void app_main()
|
||||||
|
|
||||||
wifi_manager_init();
|
wifi_manager_init();
|
||||||
DAP_Setup();
|
DAP_Setup();
|
||||||
|
start_webserver();
|
||||||
|
|
||||||
wt_mdns_init();
|
wt_mdns_init();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
file(GLOB SOURCES *
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
idf_component_register(
|
||||||
|
SRCS ${SOURCES}
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES json
|
||||||
|
)
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "api_json_module.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <esp_compiler.h>
|
||||||
|
|
||||||
|
#define TAG __FILE_NAME__
|
||||||
|
|
||||||
|
#define API_MODULE_MAX 10
|
||||||
|
|
||||||
|
typedef struct api_json_module_t {
|
||||||
|
api_json_on_req on_req;
|
||||||
|
} api_json_module_t;
|
||||||
|
|
||||||
|
static api_json_module_t module_arr[API_MODULE_MAX] = {0};
|
||||||
|
static uint8_t module_count = 0;
|
||||||
|
|
||||||
|
void api_json_module_dump()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < API_MODULE_MAX; ++i) {
|
||||||
|
printf("%d = %p\n", i, module_arr[i].on_req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int api_json_module_add(api_json_init_func func)
|
||||||
|
{
|
||||||
|
api_json_module_cfg_t api_module;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
api_module.module_id = -1;
|
||||||
|
api_module.on_req = NULL;
|
||||||
|
|
||||||
|
err = func(&api_module);
|
||||||
|
if (err) {
|
||||||
|
printf("module %p init failed\n", func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api_module.module_id >= API_MODULE_MAX) {
|
||||||
|
printf("module ID should be smaller than API_MODULE_MAX=%d\n", API_MODULE_MAX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module_arr[api_module.module_id].on_req != NULL) {
|
||||||
|
printf("module ID %d is already in use\n", api_module.module_id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_arr[api_module.module_id].on_req = api_module.on_req;
|
||||||
|
module_count++;
|
||||||
|
printf("%p is added\n", func);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int api_json_module_call(uint8_t id, uint16_t cmd, api_json_req_t *in, api_json_resp_t *out)
|
||||||
|
{
|
||||||
|
if (unlikely(id >= API_MODULE_MAX || module_arr[id].on_req == NULL)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return module_arr[id].on_req(cmd, in, out);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef API_JSON_MODULE_H_GUARD
|
||||||
|
#define API_JSON_MODULE_H_GUARD
|
||||||
|
|
||||||
|
#include <cJSON.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct api_json_req_t {
|
||||||
|
cJSON *json;
|
||||||
|
} api_json_req_t;
|
||||||
|
|
||||||
|
typedef struct api_json_resp_t {
|
||||||
|
cJSON *json;
|
||||||
|
} api_json_resp_t;
|
||||||
|
|
||||||
|
typedef int (*api_json_on_req)(uint16_t cmd, api_json_req_t *req, api_json_resp_t *rsp);
|
||||||
|
|
||||||
|
typedef struct api_json_module_cfg_t {
|
||||||
|
api_json_on_req on_req;
|
||||||
|
uint8_t module_id;
|
||||||
|
} api_json_module_cfg_t;
|
||||||
|
|
||||||
|
typedef int (*api_json_init_func)(api_json_module_cfg_t *api_module);
|
||||||
|
|
||||||
|
void api_json_module_dump();
|
||||||
|
|
||||||
|
int api_json_module_add(api_json_init_func);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a module that will be init with PRI(priority) order.
|
||||||
|
*/
|
||||||
|
#define API_JSON_MODULE_REGISTER(PRI, INIT) \
|
||||||
|
__attribute__((used, constructor(PRI))) void cons_ ## INIT(); \
|
||||||
|
void cons_ ## INIT() { api_json_module_add(INIT); }
|
||||||
|
|
||||||
|
int api_json_module_call(uint8_t id, uint16_t cmd, api_json_req_t *in, api_json_resp_t *out);
|
||||||
|
|
||||||
|
#endif //API_JSON_MODULE_H_GUARD
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "api_json_router.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <esp_compiler.h>
|
||||||
|
|
||||||
|
int api_json_router_init()
|
||||||
|
{
|
||||||
|
api_json_module_dump();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int api_json_route(api_json_req_t *req, api_json_resp_t *rsp)
|
||||||
|
{
|
||||||
|
uint16_t cmd;
|
||||||
|
uint8_t module_id;
|
||||||
|
cJSON *cmd_json;
|
||||||
|
cJSON *module_json;
|
||||||
|
|
||||||
|
if (unlikely(req->json == NULL)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_json = cJSON_GetObjectItem(req->json, "cmd");
|
||||||
|
module_json = cJSON_GetObjectItem(req->json, "module");
|
||||||
|
|
||||||
|
if (!cJSON_IsNumber(cmd_json) || !cJSON_IsNumber(module_json)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = cmd_json->valueint;
|
||||||
|
module_id = module_json->valueint;
|
||||||
|
|
||||||
|
printf("cmd %d received\n", cmd);
|
||||||
|
|
||||||
|
return api_json_module_call(module_id, cmd, req, rsp);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef API_JSON_ROUTER_H_GUARD
|
||||||
|
#define API_JSON_ROUTER_H_GUARD
|
||||||
|
|
||||||
|
#include "api_json_module.h"
|
||||||
|
|
||||||
|
int api_json_router_init();
|
||||||
|
|
||||||
|
int api_json_route(api_json_req_t *req, api_json_resp_t *out);
|
||||||
|
|
||||||
|
#endif //API_JSON_ROUTER_H_GUARD
|
|
@ -0,0 +1,15 @@
|
||||||
|
file(GLOB SOURCES
|
||||||
|
web_server.c
|
||||||
|
web_uri_module.c
|
||||||
|
uri_modules/uri_html_base.c
|
||||||
|
uri_modules/uri_api.c
|
||||||
|
)
|
||||||
|
|
||||||
|
idf_component_register(
|
||||||
|
SRCS ${SOURCES}
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES esp_http_server api_router json
|
||||||
|
)
|
||||||
|
|
||||||
|
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include "web_uri_module.h"
|
||||||
|
#include "api_json_router.h"
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
#include <cJSON.h>
|
||||||
|
|
||||||
|
#define TAG __FILE_NAME__
|
||||||
|
|
||||||
|
static char buf[2048];
|
||||||
|
static api_json_req_t json_in;
|
||||||
|
static api_json_resp_t json_out;
|
||||||
|
|
||||||
|
static esp_err_t api_post_handler(httpd_req_t *req)
|
||||||
|
{
|
||||||
|
int data_len;
|
||||||
|
int err;
|
||||||
|
uint32_t remaining = req->content_len;
|
||||||
|
|
||||||
|
data_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
|
||||||
|
if (unlikely(data_len <= 0)) {
|
||||||
|
ESP_LOGE(TAG, "httpd recv error");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
|
||||||
|
ESP_LOGI(TAG, "%.*s", data_len, buf);
|
||||||
|
ESP_LOGI(TAG, "====================================");
|
||||||
|
|
||||||
|
/* Decode */
|
||||||
|
json_in.json = cJSON_ParseWithLength(buf, data_len);
|
||||||
|
if (unlikely(json_in.json == NULL)) {
|
||||||
|
httpd_resp_set_status(req, HTTPD_400);
|
||||||
|
httpd_resp_send(req, NULL, 0);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEBUG print the actual decoded string */
|
||||||
|
cJSON_PrintPreallocated(json_in.json, buf, sizeof(buf), 0);
|
||||||
|
printf("json: %s\n", buf);
|
||||||
|
|
||||||
|
err = api_json_route(&json_in, &json_out);
|
||||||
|
if (err) {
|
||||||
|
httpd_resp_set_status(req, HTTPD_400);
|
||||||
|
httpd_resp_send(req, NULL, 0);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
cJSON_Delete(json_in.json);
|
||||||
|
|
||||||
|
if (json_out.json == NULL) {
|
||||||
|
return httpd_resp_send(req, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* api function returns something, send back to http client */
|
||||||
|
httpd_resp_set_type(req, HTTPD_TYPE_JSON);
|
||||||
|
err = !cJSON_PrintPreallocated(json_out.json, buf, sizeof(buf) - 5, 0);
|
||||||
|
cJSON_Delete(json_out.json);
|
||||||
|
json_out.json = NULL;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
httpd_resp_set_status(req, HTTPD_500);
|
||||||
|
return httpd_resp_send(req, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpd_resp_send(req, buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REGISTER MODULE
|
||||||
|
* */
|
||||||
|
|
||||||
|
static const httpd_uri_t uri_api = {
|
||||||
|
.uri = "/api",
|
||||||
|
.method = HTTP_POST,
|
||||||
|
.handler = api_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int URI_API_INIT(const httpd_uri_t **uri_conf) {
|
||||||
|
*uri_conf = &uri_api;
|
||||||
|
api_json_router_init();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int URI_API_EXIT(const httpd_uri_t **uri_conf) {
|
||||||
|
*uri_conf = &uri_api;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEB_URI_MODULE_REGISTER(0x81, URI_API_INIT, URI_API_EXIT);
|
|
@ -0,0 +1,96 @@
|
||||||
|
#include "web_uri_module.h"
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
#define TAG __FILE_NAME__
|
||||||
|
|
||||||
|
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);
|
||||||
|
/* Get value of expected key from query string */
|
||||||
|
ESP_LOGI(TAG, "query: %s", buf);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REGISTER MODULE
|
||||||
|
* */
|
||||||
|
|
||||||
|
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!"
|
||||||
|
};
|
||||||
|
|
||||||
|
int URI_HTML_BASE_INIT(const httpd_uri_t **uri_conf) {
|
||||||
|
*uri_conf = &hello;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int URI_HTML_BASE_EXIT(const httpd_uri_t **uri_conf) {
|
||||||
|
*uri_conf = &hello;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEB_URI_MODULE_REGISTER(0x90, URI_HTML_BASE_INIT, URI_HTML_BASE_EXIT);
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include "web_server.h"
|
||||||
|
#include "web_uri_module.h"
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
#include <esp_event.h>
|
||||||
|
|
||||||
|
#include <esp_system.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
|
||||||
|
#define TAG "web server"
|
||||||
|
#define EXAMPLE_HTTP_QUERY_KEY_MAX_LEN (64)
|
||||||
|
#define MAKE_U32(b0, b1, b2, b3) ((b0) | (b1) << 8 | (b2) << 16 | (b3) << 24)
|
||||||
|
|
||||||
|
#define URI_WS_STR MAKE_U32('/', 'w', 's', '\0')
|
||||||
|
#define URI_API_STR MAKE_U32('/', 'a', 'p', 'i')
|
||||||
|
|
||||||
|
static httpd_handle_t http_server = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3 types of ref:
|
||||||
|
* - 1. "/"
|
||||||
|
* - 2. "/entry"
|
||||||
|
* - 3. "/dir/"
|
||||||
|
* 4 types of target
|
||||||
|
* - 1. "/.*"
|
||||||
|
* - 2. "/entry"
|
||||||
|
* - 2. "/dir/"
|
||||||
|
* - 3. "/dir/.*"
|
||||||
|
* */
|
||||||
|
static bool uri_match(const char *reference_uri, const char *uri_to_match, size_t match_upto)
|
||||||
|
{
|
||||||
|
const uint32_t *ptr32_ref = (const uint32_t *) reference_uri;
|
||||||
|
const uint32_t *ptr32_target = (const uint32_t *) uri_to_match;
|
||||||
|
size_t ref_length;
|
||||||
|
|
||||||
|
/* optimized for /ws quick access */
|
||||||
|
if (likely(match_upto == 3)) {
|
||||||
|
if (likely(*ptr32_ref == URI_WS_STR)) {
|
||||||
|
ESP_LOGI(TAG, "cmp ws");
|
||||||
|
return *ptr32_target == *ptr32_ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ref should be shorter than target */
|
||||||
|
ref_length = strlen(reference_uri);
|
||||||
|
if (ref_length > match_upto) {
|
||||||
|
ESP_LOGI(TAG, "no match length");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// strict matching "/entry" for ref = "/entry"
|
||||||
|
if (ref_length == match_upto) {
|
||||||
|
if (memcmp(reference_uri, uri_to_match, ref_length) == 0) {
|
||||||
|
ESP_LOGI(TAG, "strict match %s", reference_uri);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if ref = /dir/ targets are /dir/ and /dir/*
|
||||||
|
if (reference_uri[ref_length - 1] == '/' && ref_length > 1) {
|
||||||
|
if (memcmp(reference_uri, uri_to_match, ref_length) == 0) {
|
||||||
|
ESP_LOGI(TAG, "match /dir/");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "no match /dir/");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fall back to root pages */
|
||||||
|
// match /* when ref if /
|
||||||
|
if (reference_uri[ref_length - 1] == '/') {
|
||||||
|
ESP_LOGI(TAG, "match /");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "fall back false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t opened_socket = 0;
|
||||||
|
|
||||||
|
static esp_err_t web_server_on_open(httpd_handle_t hd, int sockfd)
|
||||||
|
{
|
||||||
|
opened_socket++;
|
||||||
|
printf("%d open, now: %d\n", sockfd, opened_socket);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void web_server_on_close(httpd_handle_t hd, int sockfd)
|
||||||
|
{
|
||||||
|
opened_socket--;
|
||||||
|
printf("%d closed, now: %d\n", sockfd, opened_socket);
|
||||||
|
close(sockfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_webserver(void)
|
||||||
|
{
|
||||||
|
httpd_handle_t server = NULL;
|
||||||
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
int err;
|
||||||
|
|
||||||
|
config.lru_purge_enable = true;
|
||||||
|
config.uri_match_fn = uri_match;
|
||||||
|
config.open_fn = web_server_on_open;
|
||||||
|
config.close_fn = web_server_on_close;
|
||||||
|
|
||||||
|
// Start the httpd server
|
||||||
|
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
||||||
|
|
||||||
|
if ((err = httpd_start(&server, &config) != ESP_OK)) {
|
||||||
|
ESP_LOGE(TAG, "Error starting server!");
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set URI handlers
|
||||||
|
ESP_LOGI(TAG, "Registering URI handlers");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load http service
|
||||||
|
* TODO: make ws a module
|
||||||
|
* make http api POST a module
|
||||||
|
* make update a module
|
||||||
|
* */
|
||||||
|
|
||||||
|
uri_module_init(server);
|
||||||
|
http_server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t stop_webserver(httpd_handle_t server)
|
||||||
|
{
|
||||||
|
// Stop the httpd server
|
||||||
|
return httpd_stop(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_is_running()
|
||||||
|
{
|
||||||
|
return http_server != NULL;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef WEB_SERVER_H_GUARD
|
||||||
|
#define WEB_SERVER_H_GUARD
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <esp_event_base.h>
|
||||||
|
|
||||||
|
void disconnect_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data);
|
||||||
|
void connect_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data);
|
||||||
|
|
||||||
|
void start_webserver(void);
|
||||||
|
int server_is_running();
|
||||||
|
|
||||||
|
|
||||||
|
#endif //WEB_SERVER_H_GUARD
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "web_uri_module.h"
|
||||||
|
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
#define URI_MODULE_MAX 8
|
||||||
|
|
||||||
|
#define TAG __FILE_NAME__
|
||||||
|
|
||||||
|
static uri_module_t module_arr[URI_MODULE_MAX];
|
||||||
|
static uint8_t module_count = 0;
|
||||||
|
|
||||||
|
int uri_module_init(httpd_handle_t server)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
const httpd_uri_t *uri;
|
||||||
|
|
||||||
|
for (int i = 0; i < module_count; ++i) {
|
||||||
|
err = module_arr[i].init(&uri);
|
||||||
|
ESP_LOGI(TAG, "uri %s init", uri->uri);
|
||||||
|
if (err) {
|
||||||
|
ESP_LOGE(TAG, "%d init error", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = httpd_register_uri_handler(server, uri);
|
||||||
|
if (err) {
|
||||||
|
ESP_LOGE(TAG, "%d %s", i, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uri_module_exit(httpd_handle_t server)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
const httpd_uri_t *uri;
|
||||||
|
for (int i = 0; i < module_count; ++i) {
|
||||||
|
module_arr[i].exit(&uri);
|
||||||
|
err = httpd_unregister_uri_handler(server, uri->uri, uri->method);
|
||||||
|
if (err) {
|
||||||
|
ESP_LOGE(TAG, "%d %s", i, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uri_module_add(uri_module_func init, uri_module_func exit)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "adding module %p", init);
|
||||||
|
|
||||||
|
if (module_count >= URI_MODULE_MAX) {
|
||||||
|
ESP_LOGE(TAG, "too much module > URI_MODULE_MAX");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_arr[module_count].exit = exit;
|
||||||
|
module_arr[module_count].init = init;
|
||||||
|
module_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef WEB_URI_MODULE_H_GUARD
|
||||||
|
#define WEB_URI_MODULE_H_GUARD
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
|
||||||
|
typedef int (*uri_module_func)(const httpd_uri_t **uri);
|
||||||
|
|
||||||
|
typedef struct uri_module_t {
|
||||||
|
uri_module_func init;
|
||||||
|
uri_module_func exit;
|
||||||
|
} uri_module_t;
|
||||||
|
|
||||||
|
int uri_module_add(uri_module_func init, uri_module_func exit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a uri module that will be init with PRI(priority) order.
|
||||||
|
*/
|
||||||
|
#define WEB_URI_MODULE_REGISTER(PRI, INIT, EXIT) \
|
||||||
|
__attribute__((used, constructor(PRI))) void cons_ ## INIT(); \
|
||||||
|
void cons_ ## INIT() { uri_module_add(INIT, EXIT); }
|
||||||
|
|
||||||
|
int uri_module_init(httpd_handle_t server);
|
||||||
|
int uri_module_exit(httpd_handle_t server);
|
||||||
|
|
||||||
|
#endif //WEB_URI_MODULE_H_GUARD
|
|
@ -1,11 +1,16 @@
|
||||||
file(GLOB SOURCES
|
file(GLOB SOURCES
|
||||||
wifi_event_handler.c
|
wifi_event_handler.c
|
||||||
wifi_manager.c
|
wifi_manager.c
|
||||||
|
wifi_api_json.c
|
||||||
|
wifi_api.c
|
||||||
|
wifi_json_utils.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCES}
|
SRCS ${SOURCES}
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES mdns esp_wifi esp_event
|
PRIV_REQUIRES mdns esp_wifi esp_event api_router
|
||||||
)
|
)
|
||||||
|
|
||||||
|
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "wifi_api.h"
|
||||||
|
#include "wifi_manager.h"
|
||||||
|
#include <esp_wifi.h>
|
||||||
|
|
||||||
|
void wifi_api_get_ap_info(wifi_api_ap_info_t *ap_info)
|
||||||
|
{
|
||||||
|
wifi_ap_record_t ap_record;
|
||||||
|
esp_wifi_sta_get_ap_info(&ap_record);
|
||||||
|
strncpy(ap_info->ssid, (const char *)ap_record.ssid, sizeof(ap_info->ssid));
|
||||||
|
strncpy(ap_info->mac, (const char *)ap_record.bssid, sizeof(ap_info->mac));
|
||||||
|
ap_info->rssi = ap_record.rssi;
|
||||||
|
|
||||||
|
esp_netif_t *sta_netif = wifi_manager_get_sta_netif();
|
||||||
|
esp_netif_ip_info_t ip_info;
|
||||||
|
esp_netif_get_ip_info(sta_netif, &ip_info);
|
||||||
|
ip4_addr_set(&ap_info->ip, &ip_info.ip);
|
||||||
|
ip4_addr_set(&ap_info->gateway, &ip_info.gw);
|
||||||
|
ip4_addr_set(&ap_info->netmask, &ip_info.netmask);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef WIFI_API_H_GUARD
|
||||||
|
#define WIFI_API_H_GUARD
|
||||||
|
|
||||||
|
#include <lwip/ip4_addr.h>
|
||||||
|
|
||||||
|
typedef struct wifi_api_ap_info_t {
|
||||||
|
ip4_addr_t ip;
|
||||||
|
ip4_addr_t gateway;
|
||||||
|
ip4_addr_t netmask;
|
||||||
|
char ssid[33];
|
||||||
|
char mac[6];
|
||||||
|
signed char rssi;
|
||||||
|
} wifi_api_ap_info_t;
|
||||||
|
|
||||||
|
void wifi_api_get_ap_info(wifi_api_ap_info_t *ap_info);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //WIFI_API_H_GUARD
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "wifi_api_json.h"
|
||||||
|
|
||||||
|
#include "api_json_router.h"
|
||||||
|
#include "wifi_api.h"
|
||||||
|
#include "wifi_json_utils.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int wifi_api_json_get_ap_info(api_json_req_t *req, api_json_resp_t *resp);
|
||||||
|
|
||||||
|
static int wifi_api_json_get_scan(api_json_req_t *req, api_json_resp_t *resp);
|
||||||
|
|
||||||
|
static int on_json_req(uint16_t cmd, api_json_req_t *req, api_json_resp_t *rsp)
|
||||||
|
{
|
||||||
|
wifi_api_json_cmd_t wifi_cmd = cmd;
|
||||||
|
switch (wifi_cmd) {
|
||||||
|
case WIFI_API_JSON_GET_AP_INFO:
|
||||||
|
return wifi_api_json_get_ap_info(req, rsp);
|
||||||
|
case WIFI_API_JSON_CONNECT:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case WIFI_API_JSON_GET_SCAN:
|
||||||
|
return wifi_api_json_get_scan(req, rsp);
|
||||||
|
break;
|
||||||
|
case UNKNOWN:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%d\n", cmd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wifi_api_json_get_ap_info(api_json_req_t *req, api_json_resp_t *resp)
|
||||||
|
{
|
||||||
|
wifi_api_ap_info_t ap_info;
|
||||||
|
wifi_api_get_ap_info(&ap_info);
|
||||||
|
resp->json = wifi_api_json_serialize_ap_info(&ap_info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wifi_api_json_get_scan(api_json_req_t *req, api_json_resp_t *resp)
|
||||||
|
{
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ****
|
||||||
|
* register module
|
||||||
|
* */
|
||||||
|
|
||||||
|
static int wifi_api_json_init(api_json_module_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
cfg->on_req = on_json_req;
|
||||||
|
cfg->module_id = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_JSON_MODULE_REGISTER(0x90, wifi_api_json_init);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef WIFI_API_JSON_H_GUARD
|
||||||
|
#define WIFI_API_JSON_H_GUARD
|
||||||
|
|
||||||
|
typedef enum wifi_api_json_cmd_t {
|
||||||
|
UNKNOWN = 0,
|
||||||
|
WIFI_API_JSON_GET_AP_INFO,
|
||||||
|
WIFI_API_JSON_CONNECT,
|
||||||
|
WIFI_API_JSON_GET_SCAN,
|
||||||
|
|
||||||
|
} wifi_api_json_cmd_t;
|
||||||
|
|
||||||
|
#endif //WIFI_API_JSON_H_GUARD
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <cJSON.h>
|
||||||
|
|
||||||
|
#include "wifi_json_utils.h"
|
||||||
|
#include "wifi_api.h"
|
||||||
|
|
||||||
|
cJSON *wifi_api_json_serialize_ap_info(wifi_api_ap_info_t *ap_info)
|
||||||
|
{
|
||||||
|
cJSON *root;
|
||||||
|
|
||||||
|
root = cJSON_CreateObject();
|
||||||
|
|
||||||
|
cJSON_AddStringToObject(root, "ip", ip4addr_ntoa(&ap_info->ip));
|
||||||
|
cJSON_AddStringToObject(root, "gateway", ip4addr_ntoa(&ap_info->gateway));
|
||||||
|
cJSON_AddStringToObject(root, "netmask", ip4addr_ntoa(&ap_info->netmask));
|
||||||
|
cJSON_AddNumberToObject(root, "rssi", ap_info->rssi);
|
||||||
|
cJSON_AddStringToObject(root, "ssid", ap_info->ssid);
|
||||||
|
|
||||||
|
char mac_str[18];
|
||||||
|
char *m = ap_info->mac;
|
||||||
|
snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||||
|
cJSON_AddStringToObject(root, "mac", mac_str);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef WIFI_JSON_UTILS_H_GUARD
|
||||||
|
#define WIFI_JSON_UTILS_H_GUARD
|
||||||
|
|
||||||
|
#include "wifi_api.h"
|
||||||
|
|
||||||
|
cJSON *wifi_api_json_serialize_ap_info(wifi_api_ap_info_t *ap_info);
|
||||||
|
|
||||||
|
#endif //WIFI_JSON_UTILS_H_GUARD
|
|
@ -83,3 +83,27 @@ void wifi_manager_init(void)
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
ESP_LOGI(TAG, "wifi started");
|
ESP_LOGI(TAG, "wifi started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *wifi_manager_get_ap_netif()
|
||||||
|
{
|
||||||
|
return ap_netif;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wifi_manager_get_sta_netif()
|
||||||
|
{
|
||||||
|
return sta_netif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
// esp_netif_get_ip_info()
|
||||||
|
wifi_sta_list_t list;
|
||||||
|
wifi_ap_config_t ap_conf;
|
||||||
|
wifi_ap_record_t ap_info;
|
||||||
|
|
||||||
|
/* ESP_ERR_WIFI_NOT_CONNECT / ESP_ERR_WIFI_CONN */
|
||||||
|
esp_wifi_sta_get_ap_info(&ap_info);
|
||||||
|
|
||||||
|
// esp_wifi_ap_get_sta_list()
|
||||||
|
}
|
||||||
|
|
|
@ -7,4 +7,7 @@ int wifi_set_ap_cred(const char *ssid, const char *password);
|
||||||
|
|
||||||
int wifi_set_sta_cred(const char *ssid, const char *password);
|
int wifi_set_sta_cred(const char *ssid, const char *password);
|
||||||
|
|
||||||
|
void *wifi_manager_get_ap_netif();
|
||||||
|
void *wifi_manager_get_sta_netif();
|
||||||
|
|
||||||
#endif //WIFI_MANAGER_H_GUARD
|
#endif //WIFI_MANAGER_H_GUARD
|
Loading…
Reference in New Issue