diff --git a/data/README.md b/data/README.md new file mode 100644 index 000000000..a580baee2 --- /dev/null +++ b/data/README.md @@ -0,0 +1,11 @@ +

+ +

+ +# µCNC + +µCNC - Universal CNC firmware for microcontrollers + +# µCNC data + +Insert your files to be written to the board file system here. For example the index.html.gz file for web plugins diff --git a/dependencies.lock b/dependencies.lock index 2ac9dd9b4..7a46da17a 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -4,6 +4,6 @@ dependencies: source: type: idf version: 4.4.4 -manifest_hash: 748d9ec66daab24a00486d8debd2679ce41df5cbbb709cf23e88f269990f02b2 +manifest_hash: dcf4d39b94252de130019eadceb989d72b0dbc26b552cfdcbb50f6da531d2b92 target: esp32 version: 1.0.0 diff --git a/uCNC/src/hal/boards/esp32/esp32.ini b/uCNC/src/hal/boards/esp32/esp32.ini index 903f61b07..5a3a2c267 100644 --- a/uCNC/src/hal/boards/esp32/esp32.ini +++ b/uCNC/src/hal/boards/esp32/esp32.ini @@ -13,8 +13,16 @@ board_build.f_cpu = 240000000L board_build.partitions = min_spiffs.csv monitor_filters=esp32_exception_decoder upload_speed = 921600 -lib_deps = SPI, Wire, Wifi, WebServer, HTTPUpdatedServer, BluetoothSerial -debug_tool=esp-prog +lib_deps = + https://github.com/Links2004/arduinoWebSockets/archive/refs/heads/master.zip + SPI + Wire + Wifi + WebServer + HTTPUpdatedServer + BluetoothSerial + Hash + ################## # Arduino builds # @@ -25,25 +33,29 @@ extends = common_esp32 board = wemos_d1_uno32 build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_WEMOS_D1_R32 -DMCU_FLASH_FS=1 board_build.filesystem = littlefs -lib_deps = ${common_esp32.lib_deps}, LittleFS +lib_deps = ${common_esp32.lib_deps} + LittleFS [env:ESP32-MKS-DLC32] extends = common_esp32 build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_MKS_DLC32 -DMCU_FLASH_FS=1 board_build.filesystem = littlefs -lib_deps = ${common_esp32.lib_deps}, LittleFS +lib_deps = ${common_esp32.lib_deps} + LittleFS [env:ESP32-MKS-TINYBEE] extends = common_esp32 build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_MKS_TINYBEE -DMCU_FLASH_FS=1 board_build.filesystem = littlefs -lib_deps = ${common_esp32.lib_deps}, LittleFS +lib_deps = ${common_esp32.lib_deps} + LittleFS [env:ESP32-Shield-V3] extends = common_esp32 build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_ESP32_SHIELD_V3 -DMCU_FLASH_FS=1 board_build.filesystem = littlefs -lib_deps = ${common_esp32.lib_deps}, LittleFS +lib_deps = ${common_esp32.lib_deps} + LittleFS ################# # ESPIDF builds # @@ -54,16 +66,26 @@ extends = common_esp32 framework = arduino, espidf board = wemos_d1_uno32 build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_WEMOS_D1_R32 -lib_deps = ${common_esp32.lib_deps}, SPIFFS +lib_deps = ${common_esp32.lib_deps} + SPIFFS [env:ESP32IDF-MKS-DLC32] extends = common_esp32 framework = arduino, espidf build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_MKS_DLC32 -lib_deps = ${common_esp32.lib_deps}, SPIFFS +lib_deps = ${common_esp32.lib_deps} + SPIFFS [env:ESP32IDF-MKS-TINYBEE] extends = common_esp32 framework = arduino, espidf build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_MKS_TINYBEE -lib_deps = ${common_esp32.lib_deps}, SPIFFS +lib_deps = ${common_esp32.lib_deps} + SPIFFS + +[env:ESP32IDF-Shield-V3] +extends = common_esp32 +framework = arduino, espidf +build_flags = ${common_esp32.build_flags} -DBOARD=BOARD_ESP32_SHIELD_V3 +lib_deps = ${common_esp32.lib_deps} + SPIFFS diff --git a/uCNC/src/hal/boards/esp8266/esp8266.ini b/uCNC/src/hal/boards/esp8266/esp8266.ini index 8d9cca9b6..e4fde3beb 100644 --- a/uCNC/src/hal/boards/esp8266/esp8266.ini +++ b/uCNC/src/hal/boards/esp8266/esp8266.ini @@ -7,9 +7,19 @@ platform = espressif8266 framework = arduino board = d1 build_src_filter = +<*>- -; lib_deps = -; https://github.com/tzapu/WiFiManager/archive/refs/heads/master.zip +lib_deps = + SPI + EEPROM + ESP8266WiFi + ESP8266WebServer + ESP8266HTTPUpdateServer + LittleFS + Hash + https://github.com/Links2004/arduinoWebSockets/archive/refs/heads/master.zip build_flags = -DBOARD=BOARD_WEMOS_D1 -DENABLE_WIFI upload_speed = 256000 +board_build.f_flash = 80000000L board_build.f_cpu = 160000000L -board_build.ldscript=eagle.flash.2m512.ld +board_build.flash_mode = qio +board_build.ldscript=eagle.flash.4m2m.ld +board_build.filesystem = littlefs diff --git a/uCNC/src/hal/boards/rp2040/rp2040.ini b/uCNC/src/hal/boards/rp2040/rp2040.ini index ddb23ee37..c88220d08 100644 --- a/uCNC/src/hal/boards/rp2040/rp2040.ini +++ b/uCNC/src/hal/boards/rp2040/rp2040.ini @@ -27,4 +27,16 @@ build_flags = -DBOARD=BOARD_RPI_PICO [env:RP2040-PICO-W] extends = common_rp2040 board = rpipicow +lib_deps = + SPI + Wire + Wifi + WebServer + HTTPUpdatedServer + BluetoothSerial + Hash + DNSServer + SerialBT + LittleFS + https://github.com/Links2004/arduinoWebSockets/archive/refs/heads/master.zip build_flags = -DBOARD=BOARD_RPI_PICO_W -DENABLE_WIFI -DENABLE_BLUETOOTH -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH diff --git a/uCNC/src/hal/mcus/esp32/esp32_arduino.cpp b/uCNC/src/hal/mcus/esp32/esp32_arduino.cpp index c55f554a0..c4f372c94 100644 --- a/uCNC/src/hal/mcus/esp32/esp32_arduino.cpp +++ b/uCNC/src/hal/mcus/esp32/esp32_arduino.cpp @@ -48,8 +48,20 @@ uint16_t bt_settings_offset; #include #include -#ifndef WIFI_PORT -#define WIFI_PORT 23 +#ifndef TELNET_PORT +#define TELNET_PORT 23 +#endif + +#ifndef WEBSERVER_PORT +#define WEBSERVER_PORT 80 +#endif + +#ifndef WEBSOCKET_PORT +#define WEBSOCKET_PORT 8080 +#endif + +#ifndef WEBSOCKET_MAX_CLIENTS +#define WEBSOCKET_MAX_CLIENTS 2 #endif #ifndef WIFI_USER @@ -60,13 +72,13 @@ uint16_t bt_settings_offset; #define WIFI_PASS "pass" #endif -WebServer web_server(80); +WebServer web_server(WEBSERVER_PORT); HTTPUpdateServer httpUpdater; const char *update_path = "/firmware"; const char *update_username = WIFI_USER; const char *update_password = WIFI_PASS; #define MAX_SRV_CLIENTS 1 -WiFiServer telnet_server(WIFI_PORT); +WiFiServer telnet_server(TELNET_PORT); WiFiClient server_client; typedef struct @@ -394,18 +406,12 @@ extern "C" #define FLASH_FS SPIFFS #endif - // call to the webserver initializer - DECL_MODULE(endpoint) - { -#ifndef CUSTOM_OTA_ENDPOINT - httpUpdater.setup(&web_server, update_path, update_username, update_password); -#endif - FLASH_FS.begin(); - web_server.begin(); - } - void endpoint_add(const char *uri, uint8_t method, endpoint_delegate request_handler, endpoint_delegate file_handler) { + if (!method) + { + method = 255; + } web_server.on(uri, (HTTPMethod)method, request_handler, file_handler); } @@ -449,15 +455,110 @@ extern "C" #endif +#if defined(ENABLE_WIFI) && defined(MCU_HAS_WEBSOCKETS) +#include "WebSocketsServer.h" +#include "../../../modules/websocket.h" + WebSocketsServer socket_server(WEBSOCKET_PORT); + + WEAK_EVENT_HANDLER(websocket_client_connected) + { + DEFAULT_EVENT_HANDLER(websocket_client_connected); + } + + WEAK_EVENT_HANDLER(websocket_client_disconnected) + { + DEFAULT_EVENT_HANDLER(websocket_client_disconnected); + } + + WEAK_EVENT_HANDLER(websocket_client_receive) + { + DEFAULT_EVENT_HANDLER(websocket_client_receive); + } + + WEAK_EVENT_HANDLER(websocket_client_error) + { + DEFAULT_EVENT_HANDLER(websocket_client_error); + } + + void websocket_send(uint8_t clientid, uint8_t *data, size_t length, uint8_t flags) + { + switch (flags & WS_SEND_TYPE) + { + case WS_SEND_TXT: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_BIN: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_PING: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastPing(data, length); + } + else + { + socket_server.sendPing(clientid, data, length); + } + break; + } + } + + void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) + { + websocket_event_t event = {num, (uint32_t)socket_server.remoteIP(num), type, payload, length}; + switch (type) + { + case WStype_DISCONNECTED: + EVENT_INVOKE(websocket_client_disconnected, &event); + break; + case WStype_CONNECTED: + EVENT_INVOKE(websocket_client_connected, &event); + break; + case WStype_ERROR: + EVENT_INVOKE(websocket_client_error, &event); + break; + case WStype_TEXT: + case WStype_BIN: + case WStype_FRAGMENT_TEXT_START: + case WStype_FRAGMENT_BIN_START: + case WStype_FRAGMENT: + case WStype_FRAGMENT_FIN: + case WStype_PING: + case WStype_PONG: + EVENT_INVOKE(websocket_client_receive, &event); + break; + } + } +#endif + #ifdef ENABLE_WIFI void mcu_wifi_task(void *arg) { WiFi.begin(); telnet_server.begin(); telnet_server.setNoDelay(true); -#if !defined(MCU_HAS_ENDPOINTS) +#ifndef CUSTOM_OTA_ENDPOINT httpUpdater.setup(&web_server, update_path, update_username, update_password); +#endif + FLASH_FS.begin(); web_server.begin(); +#ifdef MCU_HAS_WEBSOCKETS + socket_server.begin(); + socket_server.onEvent(webSocketEvent); #endif WiFi.disconnect(); @@ -495,7 +596,13 @@ extern "C" for (;;) { - web_server.handleClient(); + if (wifi_settings.wifi_on) + { + web_server.handleClient(); +#ifdef MCU_HAS_WEBSOCKETS + socket_server.loop(); +#endif + } taskYIELD(); } } @@ -517,7 +624,13 @@ extern "C" settings_save(wifi_settings_offset, (uint8_t *)&wifi_settings, sizeof(wifi_settings_t)); } - xTaskCreatePinnedToCore(mcu_wifi_task, "wifiTask", 4069, NULL, 3, NULL, CONFIG_ARDUINO_RUNNING_CORE); + xTaskCreatePinnedToCore(mcu_wifi_task, "wifiTask", 4069, NULL, 1, NULL, 0); + // taskYIELD(); + +// #ifdef MCU_HAS_WEBSOCKETS +// socket_server.begin(); +// socket_server.onEvent(webSocketEvent); +// #endif #endif #ifdef ENABLE_BLUETOOTH bt_settings_offset = settings_register_external_setting(1); @@ -733,6 +846,10 @@ extern "C" #endif } } + +// #ifdef MCU_HAS_WEBSOCKETS +// socket_server.loop(); +// #endif #endif } diff --git a/uCNC/src/hal/mcus/esp32/mcumap_esp32.h b/uCNC/src/hal/mcus/esp32/mcumap_esp32.h index aebaba86d..efe061bce 100644 --- a/uCNC/src/hal/mcus/esp32/mcumap_esp32.h +++ b/uCNC/src/hal/mcus/esp32/mcumap_esp32.h @@ -2704,8 +2704,13 @@ extern "C" #endif #ifdef ENABLE_WIFI #define MCU_HAS_WIFI +#ifndef DISABLE_ENDPOINTS #define MCU_HAS_ENDPOINTS #endif +#ifndef DISABLE_WEBSOCKETS +#define MCU_HAS_WEBSOCKETS +#endif +#endif #ifdef ENABLE_BLUETOOTH #define MCU_HAS_BLUETOOTH #endif diff --git a/uCNC/src/hal/mcus/esp8266/esp8266_arduino.cpp b/uCNC/src/hal/mcus/esp8266/esp8266_arduino.cpp index a48f37ce0..55ea8024f 100644 --- a/uCNC/src/hal/mcus/esp8266/esp8266_arduino.cpp +++ b/uCNC/src/hal/mcus/esp8266/esp8266_arduino.cpp @@ -28,8 +28,20 @@ #include #include -#ifndef WIFI_PORT -#define WIFI_PORT 23 +#ifndef TELNET_PORT +#define TELNET_PORT 23 +#endif + +#ifndef WEBSERVER_PORT +#define WEBSERVER_PORT 80 +#endif + +#ifndef WEBSOCKET_PORT +#define WEBSOCKET_PORT 8080 +#endif + +#ifndef WEBSOCKET_MAX_CLIENTS +#define WEBSOCKET_MAX_CLIENTS 2 #endif #ifndef WIFI_USER @@ -46,14 +58,14 @@ #define ARG_MAX_LEN WIFI_SSID_MAX_LEN -ESP8266WebServer web_server(80); +ESP8266WebServer web_server(WEBSERVER_PORT); ESP8266HTTPUpdateServer httpUpdater; const char *update_path = "/firmware"; const char *update_username = WIFI_USER; const char *update_password = WIFI_PASS; #define MAX_SRV_CLIENTS 1 -WiFiServer telnet_server(WIFI_PORT); -WiFiClient server_client; +WiFiServer telnet_server(TELNET_PORT); +WiFiClient telnet_client; typedef struct { @@ -314,20 +326,20 @@ extern "C" if (telnet_server.hasClient()) { - if (server_client) + if (telnet_client) { - if (server_client.connected()) + if (telnet_client.connected()) { - server_client.stop(); + telnet_client.stop(); } } - server_client = telnet_server.accept(); - server_client.println("[MSG:New client connected]"); + telnet_client = telnet_server.accept(); + telnet_client.println("[MSG:New client connected]"); return false; } - else if (server_client) + else if (telnet_client) { - if (server_client.connected()) + if (telnet_client.connected()) { return true; } @@ -357,15 +369,6 @@ extern "C" #endif // call to the webserver initializer - DECL_MODULE(endpoint) - { -#ifndef CUSTOM_OTA_ENDPOINT - httpUpdater.setup(&web_server, update_path, update_username, update_password); -#endif - FLASH_FS.begin(); - web_server.begin(); - } - void endpoint_add(const char *uri, uint8_t method, endpoint_delegate request_handler, endpoint_delegate file_handler) { web_server.on(uri, (HTTPMethod)method, request_handler, file_handler); @@ -411,6 +414,96 @@ extern "C" #endif +#if defined(ENABLE_WIFI) && defined(MCU_HAS_WEBSOCKETS) +#include "WebSocketsServer.h" +#include "../../../modules/websocket.h" + WebSocketsServer socket_server(WEBSOCKET_PORT); + + WEAK_EVENT_HANDLER(websocket_client_connected) + { + DEFAULT_EVENT_HANDLER(websocket_client_connected); + } + + WEAK_EVENT_HANDLER(websocket_client_disconnected) + { + DEFAULT_EVENT_HANDLER(websocket_client_disconnected); + } + + WEAK_EVENT_HANDLER(websocket_client_receive) + { + DEFAULT_EVENT_HANDLER(websocket_client_receive); + } + + WEAK_EVENT_HANDLER(websocket_client_error) + { + DEFAULT_EVENT_HANDLER(websocket_client_error); + } + + void websocket_send(uint8_t clientid, uint8_t *data, size_t length, uint8_t flags) + { + switch (flags & WS_SEND_TYPE) + { + case WS_SEND_TXT: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_BIN: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_PING: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastPing(data, length); + } + else + { + socket_server.sendPing(clientid, data, length); + } + break; + } + } + + void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) + { + websocket_event_t event = {num, (uint32_t)socket_server.remoteIP(num), type, payload, length}; + switch (type) + { + case WStype_DISCONNECTED: + EVENT_INVOKE(websocket_client_disconnected, &event); + break; + case WStype_CONNECTED: + EVENT_INVOKE(websocket_client_connected, &event); + break; + case WStype_ERROR: + EVENT_INVOKE(websocket_client_error, &event); + break; + case WStype_TEXT: + case WStype_BIN: + case WStype_FRAGMENT_TEXT_START: + case WStype_FRAGMENT_BIN_START: + case WStype_FRAGMENT: + case WStype_FRAGMENT_FIN: + case WStype_PING: + case WStype_PONG: + EVENT_INVOKE(websocket_client_receive, &event); + break; + } + } +#endif + void esp8266_uart_init(int baud) { Serial.begin(baud); @@ -459,9 +552,18 @@ extern "C" } telnet_server.begin(); telnet_server.setNoDelay(true); -#if !defined(MCU_HAS_ENDPOINTS) + +#ifdef MCU_HAS_ENDPOINTS + FLASH_FS.begin(); +#endif +#ifndef CUSTOM_OTA_ENDPOINT httpUpdater.setup(&web_server, update_path, update_username, update_password); +#endif web_server.begin(); + +#ifdef MCU_HAS_WEBSOCKETS + socket_server.begin(); + socket_server.onEvent(webSocketEvent); #endif #endif } @@ -555,10 +657,10 @@ extern "C" uint8_t tmp[WIFI_TX_BUFFER_SIZE + 1]; memset(tmp, 0, sizeof(tmp)); uint8_t r; - uint8_t max = (uint8_t)MIN(server_client.availableForWrite(), WIFI_TX_BUFFER_SIZE); + uint8_t max = (uint8_t)MIN(telnet_client.availableForWrite(), WIFI_TX_BUFFER_SIZE); BUFFER_READ(wifi_tx, tmp, max, r); - server_client.write(tmp, r); + telnet_client.write(tmp, r); } } else @@ -575,7 +677,7 @@ extern "C" #ifdef ENABLE_WIFI if (esp8266_wifi_clientok()) { - wifiready = (server_client.available() > 0); + wifiready = (telnet_client.available() > 0); } #endif return ((Serial.available() > 0) || wifiready); @@ -604,14 +706,13 @@ extern "C" } #ifdef ENABLE_WIFI - web_server.handleClient(); if (esp8266_wifi_clientok()) { - while (server_client.available() > 0) + while (telnet_client.available() > 0) { system_soft_wdt_feed(); #ifndef DETACH_WIFI_FROM_MAIN_PROTOCOL - uint8_t c = (uint8_t)server_client.read(); + uint8_t c = (uint8_t)telnet_client.read(); if (mcu_com_rx_cb(c)) { if (BUFFER_FULL(wifi_rx)) @@ -623,10 +724,18 @@ extern "C" BUFFER_STORE(wifi_rx); } #else - mcu_wifi_rx_cb((uint8_t)server_client.read()); + mcu_wifi_rx_cb((uint8_t)telnet_client.read()); #endif } } + + if (wifi_settings.wifi_on) + { + web_server.handleClient(); +#ifdef MCU_HAS_WEBSOCKETS + socket_server.loop(); +#endif + } #endif } } diff --git a/uCNC/src/hal/mcus/esp8266/mcu_esp8266.c b/uCNC/src/hal/mcus/esp8266/mcu_esp8266.c index d96e2e519..180e546aa 100644 --- a/uCNC/src/hal/mcus/esp8266/mcu_esp8266.c +++ b/uCNC/src/hal/mcus/esp8266/mcu_esp8266.c @@ -338,7 +338,7 @@ void mcu_init(void) timer1_write((APB_CLK_FREQ / ITP_SAMPLE_RATE)); #ifndef RAM_ONLY_SETTINGS - esp8266_eeprom_init(1024); // 1K Emulated EEPROM + esp8266_eeprom_init(2048); // 2K Emulated EEPROM #endif #ifdef MCU_HAS_SPI esp8266_spi_init(SPI_FREQ, SPI_MODE); diff --git a/uCNC/src/hal/mcus/esp8266/mcumap_esp8266.h b/uCNC/src/hal/mcus/esp8266/mcumap_esp8266.h index ff50c8327..e0b4e1037 100644 --- a/uCNC/src/hal/mcus/esp8266/mcumap_esp8266.h +++ b/uCNC/src/hal/mcus/esp8266/mcumap_esp8266.h @@ -990,7 +990,12 @@ extern "C" #endif #ifdef ENABLE_WIFI #define MCU_HAS_WIFI +#ifndef DISABLE_ENDPOINTS #define MCU_HAS_ENDPOINTS +#endif +#ifndef DISABLE_WEBSOCKETS +#define MCU_HAS_WEBSOCKETS +#endif #define BOARD_HAS_CUSTOM_SYSTEM_COMMANDS #endif diff --git a/uCNC/src/hal/mcus/rp2040/mcumap_rp2040.h b/uCNC/src/hal/mcus/rp2040/mcumap_rp2040.h index 01fbc6db3..a6578556d 100644 --- a/uCNC/src/hal/mcus/rp2040/mcumap_rp2040.h +++ b/uCNC/src/hal/mcus/rp2040/mcumap_rp2040.h @@ -988,8 +988,13 @@ extern "C" #endif #ifdef ENABLE_WIFI #define MCU_HAS_WIFI +#ifndef DISABLE_ENDPOINTS #define MCU_HAS_ENDPOINTS #endif +#ifndef DISABLE_WEBSOCKETS +#define MCU_HAS_WEBSOCKETS +#endif +#endif #ifdef ENABLE_BLUETOOTH #define MCU_HAS_BLUETOOTH #endif diff --git a/uCNC/src/hal/mcus/rp2040/rp2040_arduino.cpp b/uCNC/src/hal/mcus/rp2040/rp2040_arduino.cpp index ad1117970..8e87ee93f 100644 --- a/uCNC/src/hal/mcus/rp2040/rp2040_arduino.cpp +++ b/uCNC/src/hal/mcus/rp2040/rp2040_arduino.cpp @@ -29,7 +29,8 @@ * * **/ -#if (defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH)) +#if (defined(MCU_HAS_WIFI) || defined(ENABLE_BLUETOOTH)) + #ifndef WIFI_SSID_MAX_LEN #define WIFI_SSID_MAX_LEN 32 #endif @@ -47,13 +48,25 @@ uint8_t bt_on; uint16_t bt_settings_offset; #endif -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI #include #include #include -#ifndef WIFI_PORT -#define WIFI_PORT 23 +#ifndef TELNET_PORT +#define TELNET_PORT 23 +#endif + +#ifndef WEBSERVER_PORT +#define WEBSERVER_PORT 80 +#endif + +#ifndef WEBSOCKET_PORT +#define WEBSOCKET_PORT 8080 +#endif + +#ifndef WEBSOCKET_MAX_CLIENTS +#define WEBSOCKET_MAX_CLIENTS 2 #endif #ifndef WIFI_USER @@ -64,13 +77,13 @@ uint16_t bt_settings_offset; #define WIFI_PASS "pass\0" #endif -WebServer web_server(80); +WebServer web_server(WEBSERVER_PORT); HTTPUpdateServer httpUpdater; const char *update_path = "/firmware"; const char *update_username = WIFI_USER; const char *update_password = WIFI_PASS; #define MAX_SRV_CLIENTS 1 -WiFiServer telnet_server(WIFI_PORT); +WiFiServer telnet_server(TELNET_PORT); WiFiClient server_client; typedef struct @@ -131,7 +144,7 @@ uint8_t mcu_custom_grbl_cmd(uint8_t *grbl_cmd_str, uint8_t grbl_cmd_len, uint8_t } } #endif -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI if (!strncmp((const char *)grbl_cmd_str, "WIFI", 4)) { if (!strcmp((const char *)&grbl_cmd_str[4], "ON")) @@ -318,7 +331,7 @@ uint8_t mcu_custom_grbl_cmd(uint8_t *grbl_cmd_str, uint8_t grbl_cmd_len, uint8_t bool rp2040_wifi_clientok(void) { -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI static uint32_t next_info = 30000; static bool connected = false; uint8_t str[128]; @@ -374,7 +387,7 @@ bool rp2040_wifi_clientok(void) return false; } -#if defined(ENABLE_WIFI) && defined(MCU_HAS_ENDPOINTS) +#if defined(MCU_HAS_WIFI) && defined(MCU_HAS_ENDPOINTS) #include "../../../modules/endpoint.h" #define MCU_FLASH_FS_LITTLE_FS 1 @@ -394,18 +407,12 @@ bool rp2040_wifi_clientok(void) #define FLASH_FS SPIFFS #endif -// call to the webserver initializer -DECL_MODULE(endpoint) -{ -#ifndef CUSTOM_OTA_ENDPOINT - httpUpdater.setup(&web_server, update_path, update_username, update_password); -#endif - FLASH_FS.begin(); - web_server.begin(); -} - void endpoint_add(const char *uri, uint8_t method, endpoint_delegate request_handler, endpoint_delegate file_handler) { + if (!method) + { + method = 255; + } web_server.on(uri, (HTTPMethod)method, request_handler, file_handler); } @@ -449,9 +456,99 @@ bool endpoint_send_file(const char *file_path, const char *content_type) #endif +#if defined(MCU_HAS_WIFI) && defined(MCU_HAS_WEBSOCKETS) +#include "WebSocketsServer.h" +#include "../../../modules/websocket.h" +WebSocketsServer socket_server(WEBSOCKET_PORT); + +WEAK_EVENT_HANDLER(websocket_client_connected) +{ + DEFAULT_EVENT_HANDLER(websocket_client_connected); +} + +WEAK_EVENT_HANDLER(websocket_client_disconnected) +{ + DEFAULT_EVENT_HANDLER(websocket_client_disconnected); +} + +WEAK_EVENT_HANDLER(websocket_client_receive) +{ + DEFAULT_EVENT_HANDLER(websocket_client_receive); +} + +WEAK_EVENT_HANDLER(websocket_client_error) +{ + DEFAULT_EVENT_HANDLER(websocket_client_error); +} + +void websocket_send(uint8_t clientid, uint8_t *data, size_t length, uint8_t flags) +{ + switch (flags & WS_SEND_TYPE) + { + case WS_SEND_TXT: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_BIN: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastTXT(data, length); + } + else + { + socket_server.sendTXT(clientid, data, length); + } + break; + case WS_SEND_PING: + if (flags & WS_SEND_BROADCAST) + { + socket_server.broadcastPing(data, length); + } + else + { + socket_server.sendPing(clientid, data, length); + } + break; + } +} + +void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) +{ + websocket_event_t event = {num, (uint32_t)socket_server.remoteIP(num), type, payload, length}; + switch (type) + { + case WStype_DISCONNECTED: + EVENT_INVOKE(websocket_client_disconnected, &event); + break; + case WStype_CONNECTED: + EVENT_INVOKE(websocket_client_connected, &event); + break; + case WStype_ERROR: + EVENT_INVOKE(websocket_client_error, &event); + break; + case WStype_TEXT: + case WStype_BIN: + case WStype_FRAGMENT_TEXT_START: + case WStype_FRAGMENT_BIN_START: + case WStype_FRAGMENT: + case WStype_FRAGMENT_FIN: + case WStype_PING: + case WStype_PONG: + EVENT_INVOKE(websocket_client_receive, &event); + break; + } +} +#endif + void rp2040_wifi_bt_init(void) { -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI wifi_settings_offset = settings_register_external_setting(sizeof(wifi_settings_t)); if (settings_load(wifi_settings_offset, (uint8_t *)&wifi_settings, sizeof(wifi_settings_t))) @@ -495,9 +592,17 @@ void rp2040_wifi_bt_init(void) } telnet_server.begin(); telnet_server.setNoDelay(true); -#if !defined(MCU_HAS_ENDPOINTS) +#ifdef MCU_HAS_ENDPOINTS + FLASH_FS.begin(); +#endif +#ifndef CUSTOM_OTA_ENDPOINT httpUpdater.setup(&web_server, update_path, update_username, update_password); +#endif web_server.begin(); + +#ifdef MCU_HAS_WEBSOCKETS + socket_server.begin(); + socket_server.onEvent(webSocketEvent); #endif #endif #ifdef ENABLE_BLUETOOTH @@ -619,7 +724,7 @@ void mcu_bt_flush(void) uint8_t rp2040_wifi_bt_read(void) { -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI if (rp2040_wifi_clientok()) { if (server_client.available() > 0) @@ -639,7 +744,7 @@ uint8_t rp2040_wifi_bt_read(void) bool rp2040_wifi_bt_rx_ready(void) { bool wifiready = false; -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI if (rp2040_wifi_clientok()) { wifiready = (server_client.available() > 0); @@ -656,7 +761,7 @@ bool rp2040_wifi_bt_rx_ready(void) void rp2040_wifi_bt_process(void) { -#ifdef ENABLE_WIFI +#ifdef MCU_HAS_WIFI DECL_BUFFER(uint8_t, wifi_rx, RX_BUFFER_SIZE); if (rp2040_wifi_clientok()) @@ -682,7 +787,13 @@ void rp2040_wifi_bt_process(void) } } - web_server.handleClient(); + if (wifi_settings.wifi_on) + { + web_server.handleClient(); +#ifdef MCU_HAS_WEBSOCKETS + socket_server.loop(); +#endif + } #endif #ifdef ENABLE_BLUETOOTH @@ -729,7 +840,7 @@ extern "C" COM2_UART.setRX(RX2_BIT); COM2_UART.begin(BAUDRATE2); #endif -#if (defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH)) +#if (defined(MCU_HAS_WIFI) || defined(ENABLE_BLUETOOTH)) rp2040_wifi_bt_init(); #endif } @@ -881,7 +992,7 @@ extern "C" bool rp2040_uart_rx_ready(void) { bool wifiready = false; -#if (defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH)) +#if (defined(MCU_HAS_WIFI) || defined(ENABLE_BLUETOOTH)) if (rp2040_wifi_clientok()) { wifiready = (rp2040_wifi_bt_rx_ready() > 0); @@ -957,7 +1068,7 @@ extern "C" } #endif -#if (defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH)) +#if (defined(MCU_HAS_WIFI) || defined(ENABLE_BLUETOOTH)) rp2040_wifi_bt_process(); #endif } diff --git a/uCNC/src/module.c b/uCNC/src/module.c index a9f10c217..e9ea5c24b 100644 --- a/uCNC/src/module.c +++ b/uCNC/src/module.c @@ -68,10 +68,4 @@ void mod_init(void) #endif load_modules(); - -// load modules after all other modules -// web server is started here after all endpoints are added -#if defined(ENABLE_WIFI) && defined(MCU_HAS_ENDPOINTS) - LOAD_MODULE(endpoint); -#endif } diff --git a/uCNC/src/modules/endpoint.h b/uCNC/src/modules/endpoint.h index 91e30c91f..5c4cbf8fd 100644 --- a/uCNC/src/modules/endpoint.h +++ b/uCNC/src/modules/endpoint.h @@ -4,7 +4,7 @@ Copyright: Copyright (c) João Martins Author: João Martins - Date: 25-10-0223 + Date: 25-10-2023 µCNC is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,6 @@ extern "C" typedef void (*endpoint_delegate)(void); - DECL_MODULE(endpoint); void endpoint_add(const char* uri, uint8_t method, endpoint_delegate request_handler, endpoint_delegate file_handler); int endpoint_request_hasargs(void); bool endpoint_request_arg(const char* argname, char* argvalue, size_t maxlen); diff --git a/uCNC/src/modules/websocket.h b/uCNC/src/modules/websocket.h new file mode 100644 index 000000000..20eead471 --- /dev/null +++ b/uCNC/src/modules/websocket.h @@ -0,0 +1,74 @@ +/* + Name: websocket.h + Description: Websocket for µCNC. + + Copyright: Copyright (c) João Martins + Author: João Martins + Date: 29-01-2024 + + µCNC is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. Please see + + µCNC is distributed WITHOUT ANY WARRANTY; + Also without the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. +*/ + +#ifndef WEBSOCKET_H +#define WEBSOCKET_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "../cnc.h" +#include + +#define WS_EVENT_ERROR 0 +#define WS_EVENT_DISCONNECTED 1 +#define WS_EVENT_CONNECTED 2 +#define WS_EVENT_TEXT 3 +#define WS_EVENT_BIN 4 +#define WS_EVENT_FRAGMENT_TEXT_START 5 +#define WS_EVENT_FRAGMENT_BIN_START 6 +#define WS_EVENT_FRAGMENT 7 +#define WS_EVENT_FRAGMENT_FIN 8 +#define WS_EVENT_PING 9 +#define WS_EVENT_PONG 10 + +#define WS_SEND_TXT 1 +#define WS_SEND_BIN 2 +#define WS_SEND_PING 4 +#define WS_SEND_TYPE (WS_SEND_TXT | WS_SEND_BIN | WS_SEND_PING) +#define WS_SEND_BROADCAST 128 + + typedef struct websocket_client_ + { + uint8_t id; + uint32_t ip; + } websocket_client_t; + + typedef struct websocket_event_ + { + uint8_t id; + uint32_t ip; + uint8_t event; + uint8_t *data; + size_t length; + } websocket_event_t; + + /*These must be implemented by the MCU HAL*/ + DECL_EVENT_HANDLER(websocket_client_connected); + DECL_EVENT_HANDLER(websocket_client_disconnected); + DECL_EVENT_HANDLER(websocket_client_error); + DECL_EVENT_HANDLER(websocket_client_receive); + void __attribute__((weak)) websocket_send(uint8_t clientid, uint8_t *data, size_t length, uint8_t flags); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file