diff -Naur orig/lib/lv_bindings/driver/esp32/espidf.h new/lib/lv_bindings/driver/esp32/espidf.h
--- orig/lib/lv_bindings/driver/esp32/espidf.h 2021-02-10 18:24:03.605801218 +0100
+++ new/lib/lv_bindings/driver/esp32/espidf.h 2021-02-10 18:24:34.254373767 +0100
@@ -122,6 +122,64 @@
config->user_data = user_data;
}
+// -vv- http server -vv-------------------------------------------------------
+
+#include "esp_http_server.h"
+
+typedef void * SemaphoreHandle_t;
+#include "http_server.h"
+
+static inline esp_err_t http_server_start(http_server_t *server) {
+ return http_server_start_internal(server);
+}
+
+static inline esp_err_t http_server_stop(http_server_t *server) {
+ return http_server_stop_internal(server);
+}
+
+static inline esp_err_t http_server_register(http_server_t *server, http_server_handler_t *data, esp_err_t (*handler_cb)(struct http_server_handler *handler_data, httpd_req_t *req), void *user_data)
+{
+ data->handler_cb = handler_cb;
+ data->user_data = user_data;
+
+ data->httpd_uri.handler = http_server_internal_handler;
+ data->httpd_uri.user_ctx = data;
+ data->cmd = HTTP_SERVER_CMD_INIT;
+ data->data = NULL;
+
+ data->event_httpd = NULL;
+ data->event_python = NULL;
+ data->lock = xSemaphoreCreateBinary(); // handler lock, initially taken
+ xSemaphoreGive(data->lock); // release it
+
+ return httpd_register_uri_handler(server->handle, &(data->httpd_uri));
+}
+
+static inline void http_server_handler_give_control(http_server_handler_t *data) {
+ xSemaphoreGive(data->event_httpd); // let httpd run
+ xSemaphoreTake(data->event_python, portMAX_DELAY); // wait for python callback to give
+}
+
+// send a string either complete or chunk'ed
+static inline void http_server_handler_send_str(http_server_handler_t *data, char *str, bool chunk) {
+ data->cmd = chunk?HTTP_SERVER_CMD_SENDSTR_CHUNK:HTTP_SERVER_CMD_SENDSTR; // send string
+ data->data = (void*)str;
+ http_server_handler_give_control(data);
+}
+
+static inline void http_server_handler_send(http_server_handler_t *data, char *bytes, int len, bool chunk) {
+ data->cmd = chunk?HTTP_SERVER_CMD_SEND_CHUNK:HTTP_SERVER_CMD_SEND; // send bytes
+ data->data = (void*)bytes;
+ data->len = len;
+ http_server_handler_give_control(data);
+}
+
+static inline const char *httpd_req_get_uri(httpd_req_t *req) {
+ return req->uri;
+}
+
+// -^^- http server -^^-------------------------------------------------------
+
// We don't want the whole FreeRTOS, only selected functions
void task_delay_ms(int ms);
diff -Naur orig/lib/lv_bindings/driver/esp32/http_server.c new/lib/lv_bindings/driver/esp32/http_server.c
--- orig/lib/lv_bindings/driver/esp32/http_server.c 1970-01-01 01:00:00.000000000 +0100
+++ new/lib/lv_bindings/driver/esp32/http_server.c 2021-02-10 19:30:59.511115597 +0100
@@ -0,0 +1,95 @@
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "esp_http_server.h"
+
+#include "http_server.h"
+#include "lib/lv_bindings/driver/include/common.h"
+
+#if CONFIG_HTTPD_MAX_REQ_HDR_LEN < 1024
+#error Please increase CONFIG_HTTPD_MAX_REQ_HDR_LEN to 1024
+#endif
+
+esp_err_t http_server_start_internal(http_server_t *server) {
+ /* Generate default configuration */
+ static const httpd_config_t dc = HTTPD_DEFAULT_CONFIG();
+ memcpy(&(server->config), &dc, sizeof(httpd_config_t));
+ /* enable wildcard matching by default */
+ server->config.uri_match_fn = httpd_uri_match_wildcard;
+ /* force running on core 1 */
+ server->config.core_id = 1;
+ server->config.stack_size = 8192;
+
+ return httpd_start(&(server->handle), &(server->config));
+}
+
+esp_err_t http_server_stop_internal(http_server_t *server) {
+ return httpd_stop(server->handle);
+}
+
+// This is the function that is scheduled and run in Micropython thread
+STATIC mp_obj_t http_server_handler_cb(mp_obj_t arg)
+{
+ mp_ptr_t *ctx = MP_OBJ_TO_PTR(arg);
+ httpd_req_t *req = ctx->ptr;
+ http_server_handler_t *data = req->user_ctx;
+
+ data->res = data->handler_cb(data, req);
+
+ data->cmd = HTTP_SERVER_CMD_DONE;
+ xSemaphoreGive(data->event_httpd); // final "give" as we are done
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(http_server_handler_cb_obj, http_server_handler_cb);
+
+esp_err_t http_server_internal_handler(httpd_req_t *req)
+{
+ http_server_handler_t *data = req->user_ctx;
+
+ xSemaphoreTake(data->lock, portMAX_DELAY); // handler in use
+
+ data->event_httpd = xSemaphoreCreateBinary(); // the binary is by default "taken"
+ data->event_python = xSemaphoreCreateBinary(); // -"-
+ if(!mp_sched_schedule((mp_obj_t)&http_server_handler_cb_obj, NEW_PTR_OBJ(httpd_req_t, req))) {
+ printf("Scheduling failed ...\n");
+ httpd_resp_set_status(req, "503 Service Unavailable");
+ httpd_resp_sendstr(req, "
Internal problem: Scheduler failed
");
+ vSemaphoreDelete(data->event_httpd);
+ vSemaphoreDelete(data->event_python);
+ xSemaphoreGive(data->lock); // handler free
+ return 0;
+ }
+
+ xSemaphoreTake(data->event_httpd, portMAX_DELAY); // wait for python callback to give
+
+ // wait for cmd 1 "callback done"
+ while(data->cmd != HTTP_SERVER_CMD_DONE) {
+ switch(data->cmd) {
+ case HTTP_SERVER_CMD_SENDSTR:
+ httpd_resp_sendstr(req, (char*)(data->data));
+ break;
+
+ case HTTP_SERVER_CMD_SENDSTR_CHUNK:
+ httpd_resp_sendstr_chunk(req, (char*)(data->data));
+ break;
+
+ case HTTP_SERVER_CMD_SEND:
+ httpd_resp_send(req, (char*)(data->data), data->len);
+ break;
+
+ case HTTP_SERVER_CMD_SEND_CHUNK:
+ httpd_resp_send_chunk(req, (char*)(data->data), data->len);
+ break;
+ }
+ xSemaphoreGive(data->event_python);
+
+ xSemaphoreTake(data->event_httpd, portMAX_DELAY); // wait for python callback to give
+ }
+
+ // whole transfer done.
+ vSemaphoreDelete(data->event_httpd);
+ vSemaphoreDelete(data->event_python);
+ xSemaphoreGive(data->lock); // handler free
+ return data->res;
+}
+
diff -Naur orig/lib/lv_bindings/driver/esp32/http_server.h new/lib/lv_bindings/driver/esp32/http_server.h
--- orig/lib/lv_bindings/driver/esp32/http_server.h 1970-01-01 01:00:00.000000000 +0100
+++ new/lib/lv_bindings/driver/esp32/http_server.h 2021-02-10 18:23:05.440704053 +0100
@@ -0,0 +1,53 @@
+// httpd_server.h
+
+#ifndef HTTPD_SERVER_H
+#define HTTPD_SERVER_H
+
+extern esp_err_t http_server_internal_handler(httpd_req_t *req);
+
+enum {
+ http_server_DELETE = 0,
+ http_server_GET,
+ http_server_HEAD,
+ http_server_POST,
+ http_server_PUT
+};
+typedef uint8_t http_server_method_t;
+
+typedef struct {
+ httpd_handle_t handle;
+ httpd_config_t config;
+
+ void *user_data;
+} http_server_t;
+
+extern esp_err_t http_server_start_internal(http_server_t *server);
+extern esp_err_t http_server_stop_internal(http_server_t *server);
+
+#define HTTP_SERVER_CMD_INIT 0
+#define HTTP_SERVER_CMD_DONE 1
+#define HTTP_SERVER_CMD_SENDSTR 2
+#define HTTP_SERVER_CMD_SENDSTR_CHUNK 3
+#define HTTP_SERVER_CMD_SEND 4
+#define HTTP_SERVER_CMD_SEND_CHUNK 5
+
+typedef struct http_server_handler {
+ SemaphoreHandle_t lock; // main handler lock
+
+ // Filled by the Python user (only "uri" and "method" on httpd_uri):
+ httpd_uri_t httpd_uri;
+
+ esp_err_t (*handler_cb)(struct http_server_handler *handler_data, httpd_req_t *req);
+ void *user_data;
+
+ SemaphoreHandle_t event_httpd; // httpd waits for python
+ SemaphoreHandle_t event_python; // python waits for httpd
+ esp_err_t res; // callback result
+
+ // command structure to exchange data between python and httpd
+ int cmd;
+ void *data;
+ int len;
+} http_server_handler_t;
+
+#endif // HTTPD_SERVER_H
diff -Naur orig/lib/lv_bindings/gen/gen_mpy.py new/lib/lv_bindings/gen/gen_mpy.py
--- orig/lib/lv_bindings/gen/gen_mpy.py 2021-02-10 18:33:39.287947309 +0100
+++ new/lib/lv_bindings/gen/gen_mpy.py 2021-02-10 18:33:21.107660176 +0100
@@ -868,7 +868,18 @@
STATIC inline const char *convert_from_str(mp_obj_t str)
{
- return (str == NULL || str == mp_const_none)? NULL: mp_obj_str_get_str(str);
+ if (str == NULL || str == mp_const_none)
+ return NULL;
+
+ if (MP_OBJ_IS_TYPE(str, &mp_type_bytearray) ||
+ MP_OBJ_IS_TYPE(str, &mp_type_memoryview)) {
+ mp_buffer_info_t buffer_info;
+ if (mp_get_buffer(str, &buffer_info, MP_BUFFER_READ)) {
+ return buffer_info.buf;
+ }
+ }
+
+ return mp_obj_str_get_str(str);
}
// struct handling
diff -Naur orig/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk new/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk
--- orig/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk 2021-02-10 18:28:10.474323021 +0100
+++ new/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk 2021-02-10 18:28:41.370876602 +0100
@@ -1,3 +1,4 @@
SDKCONFIG += boards/sdkconfig.base
SDKCONFIG += boards/sdkconfig.spiram
SDKCONFIG += boards/sdkconfig.240mhz
+SDKCONFIG += boards/sdkconfig.http_server
diff -Naur orig/ports/esp32/boards/sdkconfig.http_server new/ports/esp32/boards/sdkconfig.http_server
--- orig/ports/esp32/boards/sdkconfig.http_server 1970-01-01 01:00:00.000000000 +0100
+++ new/ports/esp32/boards/sdkconfig.http_server 2021-02-10 18:30:28.760784218 +0100
@@ -0,0 +1,4 @@
+# MicroPython on ESP32, ESP IDF configuration for httpd
+
+CONFIG_HTTPD_WS_SUPPORT=y
+CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
diff -Naur orig/ports/esp32/Makefile new/ports/esp32/Makefile
--- orig/ports/esp32/Makefile 2021-02-10 18:25:43.375652299 +0100
+++ new/ports/esp32/Makefile 2021-02-10 18:26:37.656645139 +0100
@@ -167,6 +167,9 @@
INC_ESPCOMP += -I$(ESPCOMP)/esp_http_client/include
INC_ESPCOMP += -I$(ESPCOMP)/esp_http_client/lib/include
+INC_ESPCOMP += -I$(ESPCOMP)/esp_http_server/include
+INC_ESPCOMP += -I$(ESPCOMP)/esp_http_server/src/port/esp32
+INC_ESPCOMP += -I$(ESPCOMP)/esp_http_server/src/util
INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include
INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes
INC_ESPCOMP += -I$(ESPCOMP)/nghttp/private_include
@@ -403,8 +406,9 @@
lib/lv_bindings/driver/esp32/modrtch.c \
lib/lv_bindings/driver/esp32/espidf.c \
lib/lv_bindings/driver/esp32/sh2lib.c \
+ lib/lv_bindings/driver/esp32/http_server.c \
$(ESPIDFMOD_MODULE)
-
+
# lib/lv_bindings/driver/esp32/modxpt2046.c
# lib/lv_bindings/driver/esp32/modILI9341.c
@@ -559,6 +563,11 @@
$(wildcard $(ESPCOMP)/esp_http_client/lib/*.c) \
)
+ESPIDF_HTTP_SERVER_O = $(patsubst %.c,%.o,\
+ $(wildcard $(ESPCOMP)/esp_http_server/src/*.c) \
+ $(wildcard $(ESPCOMP)/esp_http_server/src/util/*.c) \
+ )
+
ESPIDF_NGHTTP_O = $(patsubst %.c,%.o,\
$(wildcard $(ESPCOMP)/nghttp/nghttp2/lib/*.c) \
$(wildcard $(ESPCOMP)/nghttp/port/*.c) \
@@ -692,6 +701,7 @@
$(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O)))
$(eval $(call gen_espidf_lib_rule,esp_http_client,$(ESPIDF_HTTP_CLIENT_O)))
+$(eval $(call gen_espidf_lib_rule,esp_http_server,$(ESPIDF_HTTP_SERVER_O)))
$(eval $(call gen_espidf_lib_rule,esp_nghttp,$(ESPIDF_NGHTTP_O)))
$(eval $(call gen_espidf_lib_rule,esp_tcp_transport,$(ESPIDF_TCP_TRANSPORT_O)))
$(eval $(call gen_espidf_lib_rule,esp_tls,$(ESPIDF_TLS_O)))